From 70055aea8389fb8a04427a2ccc29bf1c570ee895 Mon Sep 17 00:00:00 2001 From: rsashka Date: Sat, 23 Mar 2024 22:03:23 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20=D0=B8?= =?UTF-8?q?=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B2=D0=BE=D0=B4=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D0=B8=20?= =?UTF-8?q?+=20=D0=BE=D0=B3=D1=80=D0=B0=D0=BD=D0=B8=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B4=D0=BB=D1=8F=20playground?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 32 +- README.md | 154 +- docs/blog/_print/index.html | 2506 +---------------- docs/blog/complex-prog/bag.jpeg | Bin 204893 -> 0 bytes docs/blog/complex-prog/complex-prog.jpeg | Bin 106820 -> 0 bytes docs/blog/complex-prog/drupal.jpeg | Bin 24372 -> 0 bytes docs/blog/complex-prog/graph1.jpeg | Bin 172763 -> 0 bytes docs/blog/complex-prog/graph2.png | Bin 31535 -> 0 bytes docs/blog/complex-prog/graph3.jpeg | Bin 61410 -> 0 bytes docs/blog/complex-prog/index.html | 437 --- .../index.html | 44 +- docs/blog/index.html | 225 +- docs/blog/index.xml | 2242 +-------------- docs/blog/inter-prog/index.html | 462 --- docs/blog/lang-final/index.html | 344 --- docs/blog/lang-final/lang-final.jpeg | Bin 51058 -> 0 bytes docs/blog/langs.jpeg | Bin 227272 -> 0 bytes docs/blog/logic-prog/index.html | 390 --- docs/blog/matrix.jpeg | Bin 377403 -> 0 bytes docs/blog/newlang/index.html | 879 ------ docs/blog/page/2/index.html | 342 --- docs/blog/parser-nuances/index.html | 391 --- docs/blog/prog-styles-same-time/index.html | 511 ---- docs/blog/release-v0.1/index.html | 727 ----- docs/blog/release-v0.2/index.html | 437 --- docs/blog/release-v0.3/index.html | 506 ---- docs/blog/release-v0.4/index.html | 100 +- docs/blog/unusual-prog/index.html | 453 --- docs/docs/_print/index.html | 851 ++---- docs/docs/arch/errors/index.html | 4 +- docs/docs/arch/index.html | 4 +- docs/docs/arch/mangling/index.html | 4 +- docs/docs/index.html | 64 +- docs/docs/index.xml | 808 ++---- docs/docs/ops/block/index.html | 4 +- docs/docs/ops/compare/index.html | 4 +- docs/docs/ops/create/index.html | 4 +- docs/docs/ops/if/index.html | 4 +- docs/docs/ops/index.html | 4 +- docs/docs/ops/match/index.html | 4 +- docs/docs/ops/math/index.html | 4 +- docs/docs/ops/throw/index.html | 4 +- docs/docs/ops/while/index.html | 4 +- docs/docs/ops/with/index.html | 4 +- docs/docs/syntax/_print/index.html | 747 ++--- docs/docs/syntax/dsl/index.html | 269 +- docs/docs/syntax/index.html | 18 +- docs/docs/syntax/index.xml | 731 ++--- docs/docs/syntax/macros/index.html | 563 +--- docs/docs/syntax/memory/index.html | 4 +- docs/docs/syntax/modules/index.html | 4 +- docs/docs/syntax/namespace/index.html | 4 +- docs/docs/syntax/naming/index.html | 4 +- docs/docs/syntax/pragmas/index.html | 4 +- docs/docs/syntax/sysmacro/index.html | 4 +- docs/docs/syntax/sysprop/index.html | 4 +- docs/docs/types/_print/index.html | 47 +- docs/docs/types/class/index.html | 4 +- docs/docs/types/convert/index.html | 4 +- docs/docs/types/dicts/index.html | 4 +- docs/docs/types/funcs/index.html | 4 +- docs/docs/types/generics/index.html | 4 +- docs/docs/types/index.html | 6 +- docs/docs/types/index.xml | 43 +- docs/docs/types/iter/index.html | 4 +- docs/docs/types/native/index.html | 98 +- docs/docs/types/numbers/index.html | 4 +- docs/docs/types/other/index.html | 4 +- docs/docs/types/strings/index.html | 4 +- docs/en/sitemap.xml | 177 +- docs/index.html | 200 +- docs/index.xml | 2242 +-------------- docs/offline-search-index.json | 2 +- docs/playground/_print/index.html | 55 +- docs/playground/index.html | 55 +- docs/ru/blog/_print/index.html | 35 +- docs/ru/blog/complex-prog/index.html | 6 +- docs/ru/blog/dsl-with-macros/index.html | 2 +- docs/ru/blog/index.html | 13 +- docs/ru/blog/index.xml | 33 +- docs/ru/blog/inter-prog/index.html | 6 +- docs/ru/blog/lang-final/index.html | 6 +- docs/ru/blog/logic-prog/index.html | 6 +- docs/ru/blog/newlang/index.html | 6 +- docs/ru/blog/page/2/index.html | 2 +- docs/ru/blog/parser-nuances/index.html | 8 +- docs/ru/blog/prog-styles-same-time/index.html | 6 +- docs/ru/blog/release-v0.1/index.html | 6 +- docs/ru/blog/release-v0.2/index.html | 6 +- docs/ru/blog/release-v0.3/index.html | 6 +- docs/ru/blog/release-v0.4/index.html | 76 +- docs/ru/blog/unusual-prog/index.html | 6 +- docs/ru/docs/_print/index.html | 622 ++-- docs/ru/docs/arch/_print/index.html | 39 +- docs/ru/docs/arch/index.html | 44 +- docs/ru/docs/index.html | 49 +- docs/ru/docs/index.xml | 545 +--- docs/ru/docs/syntax/_print/index.html | 514 +--- docs/ru/docs/syntax/dsl/index.html | 237 +- docs/ru/docs/syntax/index.xml | 514 +--- docs/ru/docs/syntax/macros/index.html | 360 +-- docs/ru/docs/types/_print/index.html | 31 +- docs/ru/docs/types/index.xml | 31 +- docs/ru/docs/types/native/index.html | 61 +- docs/ru/index.xml | 33 +- docs/ru/playground/_print/index.html | 55 +- docs/ru/playground/index.html | 55 +- docs/ru/sitemap.xml | 130 +- .../index.xml" | 31 +- .../index.xml" | 31 +- .../index.xml" | 31 +- docs/sitemap.xml | 4 +- .../index.html" | 4 +- .../index.xml" | 43 +- .../index.html" | 4 +- .../index.xml" | 43 +- .../index.html" | 4 +- .../index.xml" | 43 +- make_version.sh | 2 +- site.sh | 2 +- site/content/en/_index.html | 200 +- site/content/en/blog/complex-prog/bag.jpeg | Bin 204893 -> 0 bytes .../en/blog/complex-prog/complex-prog.jpeg | Bin 106820 -> 0 bytes site/content/en/blog/complex-prog/drupal.jpeg | Bin 24372 -> 0 bytes site/content/en/blog/complex-prog/graph1.jpeg | Bin 172763 -> 0 bytes site/content/en/blog/complex-prog/graph2.png | Bin 31535 -> 0 bytes site/content/en/blog/complex-prog/graph3.jpeg | Bin 61410 -> 0 bytes site/content/en/blog/complex-prog/index.md | 179 -- site/content/en/blog/dsl-with-macros.en.md | 11 +- site/content/en/blog/dsl-with-macros.md | 213 -- site/content/en/blog/inter-prog.md | 212 -- site/content/en/blog/lang-final/index.md | 77 - .../en/blog/lang-final/lang-final.jpeg | Bin 51058 -> 0 bytes site/content/en/blog/langs.jpeg | Bin 227272 -> 0 bytes site/content/en/blog/logic-prog.md | 124 - site/content/en/blog/matrix.jpeg | Bin 377403 -> 0 bytes site/content/en/blog/newlang.md | 711 ----- site/content/en/blog/parser-nuances.md | 145 - site/content/en/blog/prog-styles-same-time.md | 265 -- site/content/en/blog/release-0.1.md | 501 ---- site/content/en/blog/release-0.2.md | 155 - site/content/en/blog/release-0.3.md | 253 -- site/content/en/blog/release-0.4.md | 34 +- site/content/en/blog/unusual-prog.md | 211 -- site/content/en/docs/_index.md | 17 +- site/content/en/docs/syntax/_index.md | 15 +- site/content/en/docs/syntax/dsl.md | 265 +- site/content/en/docs/syntax/macros.md | 598 +--- site/content/en/docs/types/native.md | 41 +- site/content/en/playground/_index.md | 56 +- site/content/ru/blog/release-0.4.md | 34 +- site/content/ru/docs/_index.md | 12 - site/content/ru/docs/arch/_index.md | 17 + site/content/ru/docs/syntax/dsl.md | 231 +- site/content/ru/docs/syntax/macros.md | 378 +-- site/content/ru/docs/types/native.md | 38 +- site/content/ru/playground/_index.md | 56 +- src/analysis.cpp | 22 +- src/nbproject/configurations.xml | 522 ---- src/runtime.cpp | 2 +- src/runtime.h | 13 +- 161 files changed, 3234 insertions(+), 24439 deletions(-) delete mode 100644 docs/blog/complex-prog/bag.jpeg delete mode 100644 docs/blog/complex-prog/complex-prog.jpeg delete mode 100644 docs/blog/complex-prog/drupal.jpeg delete mode 100644 docs/blog/complex-prog/graph1.jpeg delete mode 100644 docs/blog/complex-prog/graph2.png delete mode 100644 docs/blog/complex-prog/graph3.jpeg delete mode 100644 docs/blog/complex-prog/index.html delete mode 100644 docs/blog/inter-prog/index.html delete mode 100644 docs/blog/lang-final/index.html delete mode 100644 docs/blog/lang-final/lang-final.jpeg delete mode 100644 docs/blog/langs.jpeg delete mode 100644 docs/blog/logic-prog/index.html delete mode 100644 docs/blog/matrix.jpeg delete mode 100644 docs/blog/newlang/index.html delete mode 100644 docs/blog/page/2/index.html delete mode 100644 docs/blog/parser-nuances/index.html delete mode 100644 docs/blog/prog-styles-same-time/index.html delete mode 100644 docs/blog/release-v0.1/index.html delete mode 100644 docs/blog/release-v0.2/index.html delete mode 100644 docs/blog/release-v0.3/index.html delete mode 100644 docs/blog/unusual-prog/index.html delete mode 100644 site/content/en/blog/complex-prog/bag.jpeg delete mode 100644 site/content/en/blog/complex-prog/complex-prog.jpeg delete mode 100644 site/content/en/blog/complex-prog/drupal.jpeg delete mode 100644 site/content/en/blog/complex-prog/graph1.jpeg delete mode 100644 site/content/en/blog/complex-prog/graph2.png delete mode 100644 site/content/en/blog/complex-prog/graph3.jpeg delete mode 100644 site/content/en/blog/complex-prog/index.md delete mode 100644 site/content/en/blog/dsl-with-macros.md delete mode 100644 site/content/en/blog/inter-prog.md delete mode 100644 site/content/en/blog/lang-final/index.md delete mode 100644 site/content/en/blog/lang-final/lang-final.jpeg delete mode 100644 site/content/en/blog/langs.jpeg delete mode 100644 site/content/en/blog/logic-prog.md delete mode 100644 site/content/en/blog/matrix.jpeg delete mode 100644 site/content/en/blog/newlang.md delete mode 100644 site/content/en/blog/parser-nuances.md delete mode 100644 site/content/en/blog/prog-styles-same-time.md delete mode 100644 site/content/en/blog/release-0.1.md delete mode 100644 site/content/en/blog/release-0.2.md delete mode 100644 site/content/en/blog/release-0.3.md delete mode 100644 site/content/en/blog/unusual-prog.md diff --git a/CHANGELOG.md b/CHANGELOG.md index d06027c3..c0ae355d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,25 +1,27 @@ -# История версий +# Version history -## [Релиз v0.4 (в разработке)](https://github.com/rsashka/newlang/tree/dev) +## [Release v0.4 (23.03.2024) - current version](https://github.com/rsashka/newlang/releases/tag/v0.4.0)) -Версия c новым вариантом препроцессора, который может изменять входные данные непосредственно во время синтаксического анализа исходного кода. +## New features and changes in the syntax of NewLang v0.4 +- Reworked the definition of object types using [prefix naming (sigils)](https://newlang.net/docs/syntax/naming/) +- Interrupting the execution flow and returning can now be done for [named code blocks](https://newlang.net/docs/ops/throw/). +- Simplified the syntax for importing [native variables and functions (C/C++)](https://newlang.net/docs/types/native/) +- Stabilized the syntax for [initializing tensor, dictionary, and function argument values](https://newlang.net/docs/ops/create/#comprehensions) with initial data. +- Added built-in macros for writing code using keywords in a [DSL style](https://newlang.net/docs/syntax/dsl/) -### Новые возможности и изменения в синтаксисе NewLang v0.4 -- В лексер встроен новый препроцессор для анализа макросов. -- Изменены префиксы у макросов и модулей. Теперь [префиксы](https://newlang.net/en/syntax.html#prefix) у модулей обратный слеш **\\**, а у макросов собачка **@** как аннотации в Java. -- Синтаксис создания макросов [унифицирован](https://newlang.net/en/syntax.html#macro) с остальными операторами создания объектов. -????????? - Упрощенный синтаксис доступа к полям объекта -?????????? - Возможность выводы текста после обработки препроцессора (все макросы раскрыты). +## New compiler features (nlc) +- Completely redesigned the macroprocessor. +- Reworked the compiler architecture with division into parser, macroprocessor, syntax analyzer, interpreter, and code generator. - -### Разное в NewLang v0.4 -- Новая версия [сайта](https://newlang.net/) -- Раздел c документацией на Английском -- Выполнен переход на clang 16 +## Miscellaneous +- The documentation [website](http://newlang.net) has been translated to [Hugo](https://gohugo.io/) and made bilingual. +- Instead of binary builds, a section [Playground and example code](https://newlang.net/playground/) has been added to the website for small experiments. +- Transition to clang-16 has been completed (transition to clang-17 and newer is planned after full implementation of coroutines and support for extended floating-point number formats). +- The number of project contributors has increased to more than one! ------ -## [Релиз v0.3 (07.11.2022) - текущая версия](https://github.com/rsashka/newlang/releases/tag/v0.3.0) +## [Релиз v0.3 (07.11.2022)](https://github.com/rsashka/newlang/releases/tag/v0.3.0) ### Новые возможности и изменения в синтаксисе NewLang v0.3 diff --git a/README.md b/README.md index 86c08401..ceaa03ca 100644 --- a/README.md +++ b/README.md @@ -2,78 +2,90 @@ *NewLang* is a universal high-level programming language. The main feature of the language is a simple, logical and consistent syntax, based on a strict system of grammar rules. With the help of macros the language syntax can be easily extended to a more familiar form based on keywords. Tensor calculations and rational numbers of unlimited precision are supported at the level of language syntax and basic data types without the use of additional libraries. -Current version 0.3 of 07.11.2022 ([New in current version and release history](/en/versions.html)) +Current version 0.4 of 23.03.2024 ([New in current version and release history](https://github.com/rsashka/newlang/releases/tag/v0.4.0)) ## Main properties and features of the language: -- Ability to work both in interpreter and compiler mode*. -- Dynamic and static typing with the possibility of explicitly specifying types. -- Static typing is conditionally strict (there is no automatic type conversion, but conversion between some data types is allowed. For example, an integer may be automatically converted into a real or rational number, but not vice versa) -- Automatic memory management -- OOP in the form of explicit class inheritance and "duck typing". -- Several types of functions are supported at the syntax level (normal and pure functions without side effects) -- Optional and named parameters of functions -- It is possible to insert the code in the implementation language (C/C++)* -- Easy integration with already existing software libraries (including import of native variables, functions and classes from C/C++) -- Has a REPL [read-eval-print loop](https://wikipedia.org/wiki/REPL) +- The ability to work both in interpreter and compiler mode **\***. +- Dynamic and static typing with the ability to specify types explicitly. +- Static typing is conditionally strong (there is no automatic type casting, but conversion between some data types is allowed. *For example, an integer can be automatically converted to real or rational, but not vice versa.* +- Automatic memory management without garbage collector **\*** +- Object-oriented programming in the form of explicit class inheritance and "duck typing" **\*** +- Several types of functions (regular and pure functions without side effects) are supported at the syntax level of the language +- Optional and named function arguments +- Direct insertion of C/C++ code is possible **\*** +- Easy integration with existing software libraries (including import of native variables, functions and classes* from C/C++). +- There is a REPL (read-eval-print loop) +- Symbolic calculations **\*\*** --- -*) This feature is planned to be implemented when creating the compiler. +**\***) These features are planned for implementation when the compiler is created. +**\*\***) Symbolic calculations are supported at the syntax level, but not implemented. --- -[Language syntax](/en/syntax.html) -[Detailed description of the type system](/en/types.html) +--- +[Language syntax](http://newlang.net/docs/syntax/) +[Detailed description of the type system](http://newlang.net/docs/types/) -### Example of "Hello world!" script in NewLang language +[Operators and control structures](http://newlang.net/docs/ops/) -```bash - #!../output/nlc --eval +[Playground and example code](https://newlang.net/playground/?id=1) - hello(str) := { - # Import and call the standard function printf - printf := :Pointer('printf(format:FmtChar, ...):Int32'); - printf('call: %s', $str); - $str; - }; +### Example of "Hello world!" script in NewLang language + +```python + #!../output/nlc - hello('Hello, World!'); + print('Hello, world!\n'); ``` Output: -```bash - call: Hello, World! - Hello, World! +```python + Hello, world! + + 14 ``` -## Why do we need *NewLang*? -All modern programming languages constantly develop (complicate) their syntax as new versions are released. It is a kind of payment for appearance of new features and is perceived by users as a natural phenomenon. +## Why do we need NewLang? -But it is also a serious problem because with release of versions new keywords and syntactic constructions are added, which inevitably raises the entrance threshold for new users. Another consequence of this process is a constant increase of complexity of development and support of already created software products, when the old code is finalized using already new standards. +All modern programming languages have a constant development (complication) of syntax as new versions are released. +This is a kind of payment for the emergence of new features and is perceived by users as a natural process. -With *NewLang* the complexity of language constructions is naturally limited by dividing the language syntax into two parts - this makes it easier to learn and use. +But at the same time it is also a serious problem, since with the release of versions new keywords and syntactic constructions are added, which inevitably raises the entry threshold for new users. -*Base Syntax* - for writing programs in object-oriented (imperative) and declarative styles, which is based not on reserved keywords, but on a system of strict [grammar rules](/en/syntax.html). It is possible to extend the basic syntax by using macros. *Expanded syntax* - program inserts in the implementation language (C/C++) when the basic syntax becomes insufficient. +Another consequence of this process is the constant increase in the complexity of developing and supporting already created software products, when the old code is being finalized using the already new standards. -Another inconvenience of modern languages is that most of them were created before the era of machine learning, so tensor calculations in them are implemented as separate libraries. The same applies to calculations with unlimited precision, which also require additional library functions. +NewLang naturally limits the complexity of language constructs by splitting the syntax of the language into two parts, making it easier to learn and use. -In *NewLang*, tensor calculations and rational numbers of unlimited precision are available "out of the box". They are supported at the syntax level for writing literals of corresponding types, and simple arithmetic data types are scalars (zero-dimensional tensors). The implementation of tensor calculations is based on [libtorch](https://pytorch.org/) and rational numbers using [OpenSSL](https://github.com/openssl/openssl/blob/master/crypto/bn/README.pod). +Basic syntax - for writing programs in object-oriented (imperative) and declarative styles, which is based not on reserved keywords, but on a system of strict grammar rules. It is possible to extend the basic syntax through the use of macros. +Extended syntax - program inserts in the implementation language (C/C++), when the main syntax becomes insufficient. -### Example of calculating the factorial 40 in NewLang +Another disadvantage of modern languages is that most of them were created before the era of machine learning, therefore, tensor calculations are performed in the form of separate libraries. +The same applies to calculations with unlimited precision, which also require the use of additional library functions. -```bash - #!../output/nlc --eval +NewLang has tensor calculus and unlimited-precision rationals out of the box. +They are supported at the syntax level for writing literals of the corresponding types, and simple arithmetic data types are scalars (tensors of dimension zero). +The implementation of tensor calculations is based on the library libtorch, and rational numbers using OpenSSL. + + +### Example of calculating factorial 40 using DSL syntax + +```python + #!../output/nlc - fact := 1\1; # Rational number without precision restrictions - mult := 40...1...-1?; # Get iterator for multipliers from 40 to 2 - [mult ?!] <-> { # Cycle until the iterator data runs out - fact *= mult !; # Get the current multiplier and go to the next iterator element + fact := 1\1; # Rational number 1 (no precision limit) + mult := @iter( 40..1..-1 ); # Iterator from range for factors from 40 to 2 + @while( @curr(mult)) { # Loop until the iterator data runs out + fact *= @next(mult); # Get the current multiplier and move to the next iterator element }; - fact # Print the final result + @assert(fact == 815915283247897734345611269596115894272000000000\1); + + fact # Return final result ``` Output: @@ -82,65 +94,7 @@ Output: 815915283247897734345611269596115894272000000000\1 ``` -#### Downloading binary builds - -- [Windows Binary Builds and Tests](https://github.com/rsashka/newlang/releases/download/v0.3.0/nlc_win_64.zip) -- [Ubuntu binary builds and tests](https://github.com/rsashka/newlang/releases/download/v0.3.0/nlc_lin_64.tar.xz) -- You will need shared libraries libLLVM-15 and libtorch ([archive with libraries for Windows](https://github.com/rsashka/newlang/releases/download/v0.3.0/nlc_dll.zip)), ([archive with libraries for Ubuntu](https://github.com/rsashka/newlang/releases/download/v0.3.0/nlc_so.tar.xz)) to run binary builds. - -## Compiling the project from source - -### Preparing repository - -- Download the sources [https://github.com/rsashka/newlang](https://github.com/rsashka/newlang) -- Download and deploy archive [libtorch](https://pytorch.org/) in directory *contrib* (PyTorch Build: Stable (1.13.*) -> Your OS: Linux -> Package: LibTorch -> Language: C++ / Java -> Compute Platform: CPU -> Download here (cxx11 ABI): -[libtorch-shared-with-deps-1.13+cpu.zip](https://download.pytorch.org/libtorch/cpu/libtorch-shared-with-deps-1.13.0%2Bcpu.zip) -- Activate and download submodule sources (`git submodule init && git submodule update`) -- In the directory *contrib* run the file `build.sh` -- In directory *src* run file `compile_syntax.sh` to generate parser and lexical analyzer files. You may also need to install the utilities *flex* and *bison* (flex 2.6.4 and bison (GNU Bison) 3.7.4) - -### Build - -- Unit Tests (newlang-unit-tests): In the *src* directory, run the `make CONF=UnitTest` command. -- Interpreter (nlc): in the *src* directory, run the command `make CONF=Debug`. - ----; - -Builds are done with the usual make utility, but the build files are generated automatically in the outdated version NetBeans 8.2. This is the only universal development environment with Makefile support "out of the box", while the current Apache NetBeans version does not provide full support for C/C++ development. Started a gradual transition to using VSCodium editor (analog of VSCode, which cleaned up telemetry from Microsoft) and generation of build skips using smake, but this process is not completed yet. - ## Feedback If you have any suggestions for developing or improving NewLang, [writing](https://github.com/rsashka/newlang/discussions). - -## Roadmap - -### Макропроцессор - -[x] - Минимальный варинат с одним термином без анализа аргументов (для реализации keyword based синтаксиса) -[ ] - Поддержка именованных аргументов (аналог макропроцессора С/С++) -[ ] - Поддержка типов у аргументов макроса -[ ] - Шаблоны в идентификаторах макросов (поддержка импорта модулей, определения переменных, функций и классов для создание DSL) -[ ] - Поддержка Simple Python DSL - выполнение простых скриптов Python как собственного кода - -### Синтаксис -[ ] - Контроль множественных типов у аргументов функций <:Type1, :Type2, :Type3> -[ ] - Контроль возвращаемых типов у функций -[ ] - Ссылки на объекты в синтаксисе и коде -[ ] - Константные объекты в синтаксисе и коде -[ ] - Документирующие комментарии в коде - -### Функциональные возможности -[ ] - Поддержка ООП -[ ] - Импорт нативных С/С++ типов Struct\Union\Enum -[ ] - Импорт С++ переменных (namespace + mangled имена) -[ ] - Импорт С++ функций (namespace + mangled имена) -[ ] - Импорт С++ объектов - - -## Доп. возможности -[--] - Менеджер пакетов conda (mamba) -[--] - Поддержка jupyter notebook - - - diff --git a/docs/blog/_print/index.html b/docs/blog/_print/index.html index 70b77973..58088075 100644 --- a/docs/blog/_print/index.html +++ b/docs/blog/_print/index.html @@ -132,17 +132,7 @@

Articles

-
  • Релиз языка программрования NewLang 0.4
  • - - - - - - - - - -
  • Нюансы разработки парсера для своего языка программирования
  • +
  • Release of the programming language NewLang 0.4
  • @@ -158,106 +148,6 @@

    Articles

    - - - - -
  • Релиз языка программрования NewLang 0.3
  • - - - - - - - - - -
  • Релиз языка программрования NewLang 0.2
  • - - - - - - - - - -
  • Релиз языка программрования NewLang
  • - - - - - - - - - -
  • Новый язык программирования
  • - - - - - - - - - -
  • Можно ли использовать декларативный и императивный стили написания программ одновременно?
  • - - - - - - - - - -
  • Необычная концепция синтаксиса языка программирования
  • - - - - - - - - - -
  • Простое сложное программирование
  • - - - - - - - - - -
  • Какая «идеальная» цель развития у языков программирования?
  • - - - - - - - - - -
  • Проблема логических языков программирования
  • - - - - - - - - - -
  • Интернациональное программирование на естественных языках
  • - - - - - @@ -286,7 +176,7 @@

    Articles

    -

    Релиз языка программрования NewLang 0.4

    +

    Release of the programming language NewLang 0.4

    -

    КДПВ

    - - -
    -

    Внимание!!!

    -

    “nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии.

    -

    Актуальную версию синтаксиса языка можно посмотреть тут.

    - -
    - -

    ssssssssssssssssssssssssssssssssssssssssssssss

    +

    New features and changes in the syntax of NewLang

    + +

    New compiler features (nlc)

    + +

    Miscellaneous

    +
    @@ -324,125 +223,25 @@

    Релиз языка програ
    -

    Нюансы разработки парсера для своего языка программирования

    - +

    DSL (domain-specific language) implementation with macros

    +
    A short lead description about this content page. Text here can also be bold or italic and can even be split over multiple paragraphs.
    -

    КДПВ

    -

    Недавно прочитал на Хабре статью Свой язык, или как я устал от ассемблера и С, и невольно взглядом зацепился за один абзац:

    -
    -

    Я решил не сильно париться, поэтому использовал библиотеку parglare. Она очень легкая и удобная, всем рекомендую. Для описания синтаксиса парсер принимает строку в соответствующем формате, использует регулярные выражения (не надо осуждать регулярки, они всесильны!).

    -
    -

    В результате решил опубликовать статью на основе своих старых записей еще с тех времен, когда идея NewLang до конца еще не выкристаллизовалась, но уже хотелось писать реальный код и тестировать разные концепции.

    -

    Ведь в жизни практически любого программиста может наступить момент, когда ему в голову приходит светлая идея - разработать свой собственный язык программирования. Может быть и не ради захвата мира, наравне с C/C++, Python или хотя бы PHP, а в качестве личного пет-проекта, с которым он, длинными зимними вечерами будет оттачивать собственное мастерство.

    -

    А так как у любого языка (не только программирования), все начинается с анализа его грамматики, то самой первой задачей создателя будет выбор инструментов для синтаксического анализа исходного текста.

    -

    Это история — заметки на память о муках выбора связки лексер-парсер для разбора грамматики NewLang. А так же попытка описать и систематизировать выводы об особенностях разных анализаторов с которыми пришлось поработать при выборе парсера для разбора грамматики у своего языка программирования.

    -

    Используемые термины.

    -

    Чтобы было понятно, о чем в дальнейшем пойдет речь.

    -
    -

    Лексер — компьютерная программа или библиотека, в задачи которой входит разделить входной поток данных на отдельные, не связанные между собой отдельные фрагменты, которые принято называть токенами или лексемами.

    -

    Парсер — на основе последовательности токенов выполняется синтаксический анализ, например строит абстрактное синтаксическое дерево (AST).

    -
    -

    Заход № 1 - Flex + Bison

    -

    GitHub - westes/flex: The Fast Lexical Analyzer - scanner generator for lexing in C and C++ -Bison - GNU Project - Free Software Foundation

    -

    После прочтения умных книжек я начал с классики Flex + Bison. Это старые и давно отработанные приложения с широчайшими возможностями по настройке с помощью которых можно описать синтаксис и получить исходные файлы лексера и парсера для языка практически с любой грамматикой.

    -

    К сожалению, у этих старичков очень большой порог входа и тяжелая наследственность. Чего только стоит определение собственного класса лексера через #define, а так же отсутствие нормальной поддержки С++. Вынужденные танцы с бубном для пасинга отдельной строки, когда не требуется анализировать файл целиком и прочие не всегда очевидные проблемы и разные не понятные условности.

    -

    Другими словами, через несколько недель безуспешных мучений я решил посмотреть альтернативы, а так как начальный файл лексики после экспериментов с Flex + Bison кое-как уже был сделан, то следующая связка была Flex + lemon.

    -

    Заход № 2 - Flex + Lemon

    -

    The Lemon LALR(1) Parser Generator

    -

    Тут все оказалось до примитивности просто и понятно. Реально очень быстрый старт с боевыми примерами, очень наглядный и понятный способ записи правил (по сравнению с Bison). Все хорошо кроме одного, хорошее быстро заканчивается, если приходится анализировать более одной строки.

    -

    По сути, Lemon с Bison, это как Инь и Янь. Lemon простой и удобный для работы с одной строкой (для этого он и создавался), а Bison супер-пупер-мега комбайн для парсинга файлов любых размеров.

    -

    Поэтому, поиски связки лексер + парсер продолжились и после прочтения очередной статьи, что парсеры языков можно делать на регулярках, решил посмотреть, что есть в этом направлении:

    -

    Заход № 3 парсер на регулярках re2c

    -

    Из описания re2c:

    -
    -

    По сути, на этой штуке можно писать лексические анализаторы прямо на коленке за несколько минут.

    -
    -
        /*!re2c
    -        re2c:define:YYPEEK       = "*cursor";
    -        re2c:define:YYSKIP       = "++cursor;";
    -        re2c:define:YYBACKUP     = "marker = cursor;";
    -        re2c:define:YYRESTORE    = "cursor = marker;";
    -        re2c:define:YYBACKUPCTX  = "ctxmarker = cursor;";
    -        re2c:define:YYRESTORECTX = "cursor = ctxmarker;";
    -        re2c:define:YYRESTORETAG = "cursor = ${tag};";
    -        re2c:define:YYLESSTHAN   = "limit - cursor < @@{len}";
    -        re2c:define:YYSTAGP      = "@@{tag} = cursor;";
    -        re2c:define:YYSTAGN      = "@@{tag} = NULL;";
    -        re2c:define:YYSHIFT      = "cursor += @@{shift};";
    -        re2c:define:YYSHIFTSTAG  = "@@{tag} += @@{shift};";
    -    */
    -

    Показалось, что это самый удобный способ указания шаблонов для парсера! Достаточно описать в комментариях нужные шаблоны, напустить на исходный файл компилятор регулярок и все готово! Но нет, действительно, это только показалось.

    -

    Ведь для простеньких парсеров или регулярных выражений re2c может быть и действительно хорош, но отлаживать синтаксис большого языка на регулярках слишком хлопотное занятие.

    -

    После этого решил с ним не заморачиваться и посмотреть альтернативы классическим лексерам и парсерам.

    -

    Заход № 4 - flex (flexcpp) + bisoncpp

    -

    Тогда как у традиционных flex + bison поддержка С++ реализована через одно место на уровне - работает и не трогай, то решил посмотреть их альтернативную реализация flexcpp + bisoncpp с нативной поддержкой С++.

    -

    Первое впечатление было, то что доктор прописал!

    -

    Синтаксис записи лексики хоть немного и отличается от классической, но это не принципиально. Зато есть нативная и логичная поддержка С++ без оберток и выкрутасов, и как дополнительный плюс - более удобный синтаксис указания правил в парсере. Но и тут не обошлось без шероховатостей.

    -

    В шаблонах правил bisoncpp не поддерживает юникод (хотя сам лексер-парсер с ним справляется на ура), и совсем не понятная ситуация с поддержкой. Как я понял, разработчиком является вроде бы один человек, но пообщаться с ним насчет ошибок при обработке русских символов так и не получилось.*

    -

    Потом еще одно непонятное поведение вылезло в другом месте. В результате решил отказаться от недружелюбной поддержки и посмотреть, какие есть еще варианты парсеров.

    -
    -

    *) Через два года мой тикет был закрыт с комментарием, что поддерживаются только ascii символы.

    -

    Заход № 5 - неродной парсер ANTLR

    -

    От использования ANTLR (от англ. ANother Tool for Language Recognition — «ещё одно средство распознавания языков») — генератора нисходящих анализаторов для формальных языков, я решил сразу отказать из-за того, что он написан на Java,.

    -

    В этом нет никаких религиозных предпочтений, так как я искал генератор парсеров, который можно было бы сделать встроенным прямо в среду выполнения, а в случае с ANTLR и JRE это было бы затруднительно.

    -

    Таким образом я опять вернулся к старичкам Flex и Bison, с которых все и начиналось.

    -

    Заход № 6, последний - возвращение к Flex + Bison

    -

    Все описанные выше эксперименты заняли в общем итоге несколько месяцев, в результате которых были написаны килобайты исходного кода и тестовых примеров, прочитано десятки статей и как результат - возврат к изначальной связке Flex + Bison, но уже с солидным багажом опыта в применении различных вариантов лексеров-парсеров.

    -

    Но самое главное, с пониманием того, что же в результате хочется получить, и очень большой базой тестовых примеров синтаксиса.

    -

    Выводы на память

    -

    В итоге для себя решил следующее: если нужен простенький шаблонизатор, то идеальный вариант re2c (если почему-то не подходит regexp). Если требуется анализировать синтаксис сложнее обычных регулярок, но в одну строку, то идеальной будет связка flex+lemon, а если нужна серьезная артиллерия, то тут однозначно flex + bison.

    -

    От связки flexcpp + bisoncpp отказался совсем. Что с поддержкой — не понятно, синтаксис от классики отличается не очень сильно (хотя тоже нужно ломать голову), а обход выявленных косяков не стоят того синтаксического сахара.

    -

    И по итогам множества экспериментов с разными вариантами синтаксиса удалось сформулировать пару важных архитектурных моментов, которые могут очень сильно упростить жизнь создателям языком программирования:

    -

    Стратегия обработки ошибок синтаксиса

    -

    Обычно принято обрабатывать синтаксические ошибки непосредственно в парсере и для этого есть определенный резон — в этом случае нет необходимости в каких либо дальнейших действиях, нужна только полностью описанная корректная грамматика.

    -

    Но если грамматика языка очень сложная (привет C++), и её описание становится сложной задачей, то можно отказался и от анализа ошибок синтаксиса непосредственно в парсере! То есть, лучше сделать максимально широкую лексику (даже с теми вариантами, которые являются для языка ошибочными), но ловить эти ошибки уже при анализе AST!

    -

    В этом случае, поддерживать описание грамматики языка становится значительно проще (меньше синтаксических правил, проще их формальное описание и т.д.), а самое главное, при описании грамматики не нужно думать про lval или rval, где можно указывать ссылку, а где нет — т. е. можно указывать все и везде, а вот анализ допустимости использования конкретных терминов будет выполняться позднее при анализе AST.

    -

    Отказа от полного анализа грамматики языка на уровне лексера — парсера и перенос проверки корректности синтаксических конструкций на этап разбора синтаксического дерева позволяет в разы, если не на порядки сократить и значительно упростить описание грамматических правил!

    -

    Подобное допущение очень полезно на начальном этапе создания языка (можно сосредоточиться на общей концепции, вместо постоянных правок в грамматике), а так же значительно упростить в будущем поддержку и/или расширение синтаксиса.

    -

    Макросы и модификация грамматики в Runtime

    -

    Какими бы мощными не были flex+bison, но у этой связки есть одна архитектурная проблема. Логика flex и bison построена на конечных автоматах и изменить грамматику языка во время выполнения приложения невозможно, тем более Bison сам вызывает лексер для получения очередной порции данных и ему очень непросто подсунуть измененные данные прямо во время работы. А так хотелось сделать возможность раскрытия макросов и модификации синтаксиса за один проход анализатора!

    -

    Для этого пришлось переделать логику работы flex+bison, чтобы парсер получал данные из лексера не напрямую из yylex, а через функцию — прокси. Эта промежуточная функция, складывает считанные лексемы во внутренний буфер. Данные в буфере анализируется на предмет наличия макросов и только после их раскрытия, лексемы отдаются в парсер из вершины буфера по одной за раз. Подробнее о макросах NewLang можно почитать тут.

    -

    Самое главное при разработке грамматики!

    -

    Но самый важный совет мне подсказал друг, который некогда участвовал в проекте по разработке парсера для языка программирования. И в правильности его совета - пиши тесты для грамматики - я убеждался уже множество раз. Даже так, ПИШИ ТЕСТЫ ДЛЯ ГРАММАТИКИ.

    -

    Тесты для грамматики языка гораздо более важная вещь, чем любой из используемых инструментов. Только тесты позволяют убедиться в том, что новая фича в языке не сломала старые наработки. А если все же сломала, то в первую очередь нужно добавить новый тест, который бы фиксировал сломавшийся сценарий и только после этого можно будет со спокойной душой продолжать эксперименты с новыми грамматическими конструкциями.

    -

    И удачи всем языкописателям!

    -

    Ссылка на первую публикаци

    - -
    - - - - - - - - - - - +
    +

    Attention!!!

    +

    This article contains a description of the NewLnag syntax of the previous version.

    +

    Publication source https://habr.com/articles/720416/

    - +
    -
    -

    DSL (domain-specific language) implementation with macros

    -
    A short lead description about this content page. Text here can also be bold or italic and can even be split over multiple paragraphs.
    - -

    https://habr.com/articles/720416/

    -

    image -This is a translation of my own article

    +

    image

    +

    This is a translation of my own article

    The release of NewLang language with a brand new “feature” is coming, a remodeled version of the preprocessor that allows you to extend the language syntax to create different DSL dialects using macros.

    What is it about?

    @@ -597,2247 +396,6 @@

    Conclusion -

    Релиз языка программрования NewLang 0.3

    - - -

    КДПВ

    - - -
    - -

    NewLang — это язык программирования высокого уровня общего назначения. Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан на строгой системе грамматических правил. За счет использования макросов, синтаксис языка легко расширяется до более привычного вида на основе ключевых слов.

    -

    NewLang находится в процессе активного развития. Это третий публичный релиз в который добавлены новые существенные возможности по сравнению с предыдущей версией.

    -

    Зачем нужен NewLang?

    -

    У всех современных языков программирования происходит постоянное развитие (усложнение) синтаксиса по мере выхода новых версий. Это является своего рода платой за появление новых возможностей и воспринимается пользователями как естественное явление.

    -

    Но одновременно является и серьезной проблемой, так как с выходом версий добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки и поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.

    -

    У NewLang сложность языковых конструкций ограничена естественным образом за счет разделения синтаксиса языка на две части - это упрощает его изучение и использование.

    -

    Основной синтаксис — для написания программ в объектно-ориентированном (императивном) и декларативном стилях, который основан не на зарезервированных ключевых словах, а на системе строгих грамматических правил. Имеется возможность расширения основного синтаксиса за счет использования макросов. Расширенный синтаксис — программные вставки на языке реализации (С/С++), когда основного синтаксиса становится недостаточно.

    -

    Еще одно неудобство современных языков в том, что большинство из них были созданы до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек. Это же касается и вычислений с неограниченной точностью, которые так же требуют применения дополнительных библиотечных функций.

    -

    У NewLang тензорные вычисления и рациональные числа неограниченной точности доступны «из коробки». Они поддерживаются на уровне синтаксиса для записи литералов соответствующих типов, а простые арифметические типы данных являются скалярами (тензорами нулевой размерности). Реализация тензорных вычислений сделана на базе библиотеки libtorch, а рациональные числа с использованием OpenSSL.

    -

    Новые глобальные фичи и изменения в синтаксисе:

    -

    Простые чистые функции удалены

    -

    Раньше я пытался использовать синтаксис предикатов из Пролога, в котором проверки условий записываются через запятую. Но эта идея оказалась провальной, а сами операторы просто ужасными (тестировал разные варианты, но каждый раз получал много отрицательных отзывов), поэтому сейчас решил полностью от них отказаться.

    -

    Они получались не только сложными для восприятия, но и по факту не нужными, так как легко заменялись обычной функцией с комбинации обычных логических операций.

    -

    Зафиксирован синтаксис операторов проверки условия и циклов.

    -

    Изменен и упрощен синтаксис операторов проверки условия (импликации) и цикла, для которых оставлено только по одному варианту. Проверка условия записывается в виде оператора математического следования –>, а цикл с помощью оператора <->.

    -

    Но для упрощения записи можно пользоваться макросами, тогда в этом случае операции проверки условий и циклы превращаются в классические

    -
    \if(...){
    -    ...
    -} \elif(...) {
    -   ...
    -} \else {
    -   ...
    -};
    -

    или

    -
     \while( ... ){ 
    -     ...
    -}; 
    -

    Конструкция else у операторов цикла

    -

    Теперь оператор цикла while поддерживает конструкцию else, которая выполняется если условие входа в цикл не было выполнено. Это поведение отличается от аналогичных конструкций в языке Python, у которого секция else выполняется всегда, кроме прерывания цикла по break.

    -

    Ветка else у оператора цикла записывается так же как и ветка иначе в условном операторе, т. е.

    -
    [ cond ] <-> {
    -   ...
    -}, [_] --> {
    -   ...
    -};
    -

    Или тоже самое, но с использованием макросов:

    -
    \while(cond) {
    -   ...
    -} \else {
    -   ...
    -};
    -

    Пространства имен

    -

    В синтаксис NewLang добавлены пространства имен, в стиле очень похожим на С++. Имена разделяются двойным двоеточием, а для определение пространства имен, его нужно указать перед открывающейся фигурной скобкой.

    -
    ns {
    -    name {
    -        var := 0; # Имя переменной будет ns::name::var
    -        ::var := 1; # Переменная из глобального пространства имен
    -    }
    -}
    -

    Программные модули

    -

    Реализована концепция программных модулей - которая повторяет концепцию иерархического расположения файлов в структуре каталогов файловой системы, как в языках Python и Java.

    -

    Имя модуля начинается на префикс @, а структура каталогов указывается через точку. Причем концепции программных модулей и пространства имен объединены, и полное имя переменой из предыдущего абзаца будет @root.dir.module::ns::name::var, где root и dir это каталоги в файловой системе, а module — имя файла.

    -

    Объектно ориентированное программирование

    -

    Реализована часть концепции ООП и добавлена поддержка определения классов и их наследование, которая сейчас выглядит следующим образом:

    -
    :NewClass := :Class() { #  Новый тип (класс)
    -    field := 1;
    -    method() := {};
    -};
    -obj := :NewClass(); # Экземпляр класса
    -

    Неожиданно для самого себя понял, что имея полный набор вариантов проверок при создании объектов (::= - создать новый объект, := - создать новый или присвоить значение существующему, = - только присвоить значение, а если объект не существует будет ошибка), концепция переопределения наследуемых функций не требует вообще никаких ключевых слов:

    -
    :NewClass2 := :NewClass() { # Новый класс на базе существующего
    -    field ::= 2; # Будет ошибка, т. к. поле field уже есть в базовом классе
    -    method() = {}; # Аналог override, т.к. method должен существовать в базовом классе
    -};
    -

    Прерывания, возврат и обработка ошибок

    -

    Изменена, а точнее полностью переделана идеология возвратов из функций и обработки ошибок. -Теперь она чем-то похожа на подход, примененный в Ruby. Любая последовательность команд заключенные в фигурные скобки (в том числе тело функции), рассматривается как блок кода у которого нет специального оператора аналога return, который возвращает какое либо значение. -Просто любой блок кода всегда возвращает последнее вычисленное значение (это чем то похоже на оператор «запятая» в языках C/C++).

    -

    Для того, чтобы прервать выполнение кода используются две разные команды - прерывания, которые условно можно назвать положительным и отрицательным результатом. Что примерно соответствует семантике их записи. -“Отрицательное” прерывание записывается в виде двух минусов, а “положительное” прерывание в виде двух плюсов, т.е. -- или ++.

    -

    По умолчанию данные операции возвращают пустое значение. Чтобы прерывание вернуло результат, возвращаемые данные нужно записывать между парой соответствующих символов, -т.е. -- 100 --, что является близким аналогом оператора return 100; в других языках программирования, а ++«Строка»++ - аналогом return «Строка»;.

    -

    Хотя более точным аналогом этих операторов будет все таки не return, а throw, -т.к. эти команды не только прерывают выполнение последовательности команд в блоке, но их еще можно «ловить». -Для этого используется блок кода с соответствующей семантикой, {++} - блок кода, -который перехватывает положительные прерывания и {--} - блок кода, который перехватывает прерывания, созданные операторами .

    -

    Подобная концепция (в явном виде не разделять возвраты из функций и обработку исключений), -хоть и выглядит немного необычной, но позволяет реализовывать несколько очень полезных финтов, -которые сложно реализуемые в обычных языках программирования.

    -

    Например, возврат из нескольких вложенных функций без необходимости обрабатывать результат возврата каждой из них. -В этом примере функция Test перехватывает “положительные” прерывания из вложенных функций:

    -
        Test0(arg) := { \if($arg==0) \return("DONE - 0"); «FAIL» };
    -    Test1(arg) := { \if($arg==1) \return("DONE - 1"); Test0($arg); };
    -    Test(arg) := {+ \if($arg >= 0) Test1($arg); $arg; +};
    -
    -    Test(0); # Вернет «DONE — 0» возврат из вложенной функции Test0
    -    Test(1); # Вернет «DONE — 1» возврат из вложенной функции Test1
    -    Test(2); # Вернет «FAIL» возврат из вложенной функции Test0
    -    Test(-2); # Вернет -2 — возврат из функции Test
    -

    Есть еще блок {* … *}, который перехватывает оба типа прерываний. Такой блок кода поддерживает типизацию возвращаемого значения, что позволяет в явном виде указывать типы данных, которые нужно перехватывать. -Например, {* ... *} :Type1 — будет перехвачено прерывание вида ++ :Type1 ++ или --:Type1--, что позволяет очень гибко формировать логику работы программы.

    -

    Блоки кода с перехватом исключений также поддерживают оператор иначе (\else) который, по аналогии с оператором \else в циклах, выполняется только тогда, если прерывания не произошло.

    -

    Можно указать сразу несколько типов, которые нужно перехватывать:

    -
        {* 
    -        ....
    -    *} <:Type1, :Type2, :Type3>;
    -

    Бинарная сборка под Windws:

    -

    В текущем релизе версия clang повышена 15, а вызовы нативных функций опять реализованы с помощью libffi, что в итоге позволило собрать бинарную сборку не только под Linux, но и под Windows. И теперь чтобы поиграться с REPL read-eval-print loop можно скачать уже готовый бинарник.

    -

    Подробная информация о языке:

    - -

    Обратная связь

    -

    Если у вас появятся предложения по развитию нового или улучшению уже существующего функционала NewLang, пишите.

    -

    Примеры кода

    -
    #!../output/nlc --eval
    -# Определение функции hello
    -hello(str) := { 
    -    # Импорт стандартной C функции
    -    printf := :Pointer('printf(format:FmtChar, ...):Int32');
    -    # Вызов C функции с проверкой типов аргументов по строке формата
    -    printf('%s', $str);  
    -    # Возврат значения из функции hello
    -     $str;
    -};
    -
    -hello('Привет, мир!'); # Вызвать функцию</code>
    -

    Вывод (первая строка выводится с помощью printf, а вторая — возвращаемое значение функции hello):

    -
        Привет, мир!
    -    Привет, мир!
    -

    Пример скрипта для вычисления факториала 1000

    -
    #!../output/nlc --eval
    -
    -fact := 1\1;  # Рациональное число без ограничения точности
    -mult := 1000..1..-1?; # Сделать из диапазона итератор для множителей от 1000 до 2
    -[mult ?!] <-> {      # Цикл, пока не закончатся данные итератора
    -    # Получить текущий множитель и перейти на следующий элемент итератора
    -    fact *= mult !; 
    -};
    -fact # Вывести итоговый результат
    -

    Вывод:

    - -402387260077093773543702433923003985719374864210714632543799910429938512398629 -020592044208486969404800479988610197196058631666872994808558901323829669944590 -997424504087073759918823627727188732519779505950995276120874975462497043601418 -278094646496291056393887437886487337119181045825783647849977012476632889835955 -735432513185323958463075557409114262417474349347553428646576611667797396668820 -291207379143853719588249808126867838374559731746136085379534524221586593201928 -090878297308431392844403281231558611036976801357304216168747609675871348312025 -478589320767169132448426236131412508780208000261683151027341827977704784635868 -170164365024153691398281264810213092761244896359928705114964975419909342221566 -832572080821333186116811553615836546984046708975602900950537616475847728421889 -679646244945160765353408198901385442487984959953319101723355556602139450399736 -280750137837615307127761926849034352625200015888535147331611702103968175921510 -907788019393178114194545257223865541461062892187960223838971476088506276862967 -146674697562911234082439208160153780889893964518263243671616762179168909779911 -903754031274622289988005195444414282012187361745992642956581746628302955570299 -024324153181617210465832036786906117260158783520751516284225540265170483304226 -143974286933061690897968482590125458327168226458066526769958652682272807075781 -391858178889652208164348344825993266043367660176999612831860788386150279465955 -131156552036093988180612138558600301435694527224206344631797460594682573103790 -084024432438465657245014402821885252470935190620929023136493273497565513958720 -559654228749774011413346962715422845862377387538230483865688976461927383814900 -140767310446640259899490222221765904339901886018566526485061799702356193897017 -860040811889729918311021171229845901641921068884387121855646124960798722908519 -296819372388642614839657382291123125024186649353143970137428531926649875337218 -940694281434118520158014123344828015051399694290153483077644569099073152433278 -288269864602789864321139083506217095002597389863554277196742822248757586765752 -344220207573630569498825087968928162753848863396909959826280956121450994871701 -244516461260379029309120889086942028510640182154399457156805941872748998094254 -742173582401063677404595741785160829230135358081840096996372524230560855903700 -624271243416909004153690105933983835777939410970027753472000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000\1 - -

    Как посмотреть?

    - - -
    - - - - - - - - - - - - - - - - -
    -

    Релиз языка программрования NewLang 0.2

    - - -

    КДПВ

    - - -
    -

    Внимание!!!

    -

    Данная статья содержит описание синтаксиса NewLnag предыдущей версии.

    -

    Актуальную версию синтаксиса языка можно посмотреть тут.

    - -
    - -

    NewLang - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения.

    -

    Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка).

    -

    NewLang находится в процессе активного развития и это второй публичный релиз в котором добавлены существенные новые возможности и произошли некоторые изменения по сравнению с предыдущей версией.

    -

    Особенности языка:

    -
      -
    • Возможность работы как в режиме интерпретатора, так и компилятора*.
    • -
    • Динамическая и статическая типизация с возможностью указания типов в явном виде.
    • -
    • Статическая типизация является условно строгой (автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных, например, целое число может быть автоматически преобразовано в вещественное или рациональное, но не наоборот).
    • -
    • Автоматическое управление памятью.
    • -
    • ООП в виде явного наследования классов и «утиная» типизация.
    • -
    • На уровне синтаксиса поддержка нескольких типов функций (обычные и чистые функции без побочных эффектов).
    • -
    • Необязательные и именованные параметры функций.
    • -
    • Возможны вставки кода на языке реализации (С/С++)*.
    • -
    • Простая интеграция с уже существующими программными библиотеками (в том числе импорт нативных переменных и функций из С/С++).
    • -
    • Имеется REPL read-eval-print loop — «цикл: чтение — вычисление — вывод».
    • -
    -

    Новые глобальные фичи:

    -
      -
    • Добавлены макросы. Теперь можно делать собственные языковые диалекты и использовать более привычную запись алгоритмических конструкций с использование ключевых слов. -Например, цикл
    • -
    -
    [ cond ] <-> {
    -      тело цикла
    -}; 
    -

    можно записать в более привычный нотации

    -
    \while (cond) {
    -      тело цикла
    -};
    -
      -
    • Добавлены итераторы для перебора элементов словарей или для запросов к другим контейнерам (например, к базам данных). На уровне базового синтаксиса поддерживается фильтрация данный, включая функциональный аналог LINQ за счет применения функций обратного вызова в качестве условия фильтра.
    • -
    • Добавлен новый тип данных — рациональные числа с неограниченной точностью. Они записываются в виде обыкновенной дроби, у которой разделитель бекслеш, например единицу можно записать 1\1, а число 0.5 как 1\2.
    • -
    • Реализован оператор распаковки словаря (многоточие), который можно использовать чтобы передать несколько аргументов при вызове функции или для присвоения значения сразу нескольким переменным.
    • -
    • Теперь оператор присвоения поддерживает установку значений сразу нескольким переменным. С правой стороны от оператора присвоения может находится одно или несколько значений или оператор распаковки словаря. Причем словарь может быть указан и с левой стороны от оператора присвоения и таким образом можно записать самый простой способ перебора всех его элементов, когда в цикле первый элемент словаря сохраняется в переменную item, а из самого словаря удаляется:
    • -
    -
    [ dict ] <-> {  
    -      item, dict := ... dict; 
    -};
    -

    Изменения в синтаксисе:

    -
      -
    • Изменена запись циклов. Вместо двух разных типов с предусловием и постусловие, теперь используется единая форма записи, а тип цикла определяется взаимным расположением условия и его тела.
    • -
    • Изменены названия арифметических и некоторых других типов данных на более логичные. В именах арифметических типов теперь указан их размер (Int8, Int16 … Float32, Float64 и т.д.).
    • -
    • Многострочные комментарии стали вложенными
    • -
    -

    Подробная информация о языке:

    - -

    Примеры кода

    - -``` -#!../output/nlc --eval -

    Определение функции hello

    -

    hello(str) := {

    -
    # Импорт стандартной C функции
    -printf := :Pointer('printf(format:FmtChar, ...):Int32');
    -
    -# Вызов C функции с проверкой типов аргументов по строке формата
    -printf('%s', $str);  
    -
    -# Возврат значения из функции hello
    - $str;
    -
    -

    };

    -

    hello(‘Привет, мир!’); # Вызвать функцию

    -
    Вывод (первая строка выводится с помощью printf, а вторая - возвращаемое значение функции hello):
    -
    Привет, мир!
    -Привет, мир!
    -
    -
    
    -<spoiler title="Пример скрипта для вычисления факториала 1000">
    -

    #!../output/nlc –eval

    -

    @fact := 1\1; # Рациональное число без ограничения точности -@mult := 1000..1..-1?; # Сделать из диапазона итератор для множителей от 1000 до 2 -[mult ?!] <-> { # Цикл, пока не закончатся данные итератора -# Получить текущий множитель и перейти на следующий элемент итератора -fact *= mult !; -}; -fact # Вывести итоговый результат

    -
    Вывод:
    -

    402387260077093773543702433923003985719374864210714632543799910429938512398629 -020592044208486969404800479988610197196058631666872994808558901323829669944590 -997424504087073759918823627727188732519779505950995276120874975462497043601418 -278094646496291056393887437886487337119181045825783647849977012476632889835955 -735432513185323958463075557409114262417474349347553428646576611667797396668820 -291207379143853719588249808126867838374559731746136085379534524221586593201928 -090878297308431392844403281231558611036976801357304216168747609675871348312025 -478589320767169132448426236131412508780208000261683151027341827977704784635868 -170164365024153691398281264810213092761244896359928705114964975419909342221566 -832572080821333186116811553615836546984046708975602900950537616475847728421889 -679646244945160765353408198901385442487984959953319101723355556602139450399736 -280750137837615307127761926849034352625200015888535147331611702103968175921510 -907788019393178114194545257223865541461062892187960223838971476088506276862967 -146674697562911234082439208160153780889893964518263243671616762179168909779911 -903754031274622289988005195444414282012187361745992642956581746628302955570299 -024324153181617210465832036786906117260158783520751516284225540265170483304226 -143974286933061690897968482590125458327168226458066526769958652682272807075781 -391858178889652208164348344825993266043367660176999612831860788386150279465955 -131156552036093988180612138558600301435694527224206344631797460594682573103790 -084024432438465657245014402821885252470935190620929023136493273497565513958720 -559654228749774011413346962715422845862377387538230483865688976461927383814900 -140767310446640259899490222221765904339901886018566526485061799702356193897017 -860040811889729918311021171229845901641921068884387121855646124960798722908519 -296819372388642614839657382291123125024186649353143970137428531926649875337218 -940694281434118520158014123344828015051399694290153483077644569099073152433278 -288269864602789864321139083506217095002597389863554277196742822248757586765752 -344220207573630569498825087968928162753848863396909959826280956121450994871701 -244516461260379029309120889086942028510640182154399457156805941872748998094254 -742173582401063677404595741785160829230135358081840096996372524230560855903700 -624271243416909004153690105933983835777939410970027753472000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000\1

    -
    
    -## Как посмотреть?
    -- [Загрузить собранный REPL и тесты (пока только под Ubuntu)](https://github.com/rsashka/newlang/releases/download/v0.2.0/nlc_bin.tar.xz)
    -- Для запуска бинарных файлов потребуются разделяемые библиотеки libLLVM-13 и libtorch: [архив только с нужными библиотеками](https://github.com/rsashka/newlang/releases/download/v0.2.0/nlc_so.tar.xz).
    -- Так же все можно собрать напрямую из исходников по инструкции в [репозитории](https://github.com/rsashka/newlang)
    -
    -
    - - - - - - - - - - - - - - - - -
    -

    Релиз языка программрования NewLang

    - - -

    КДПВ

    - - -
    -

    Внимание!!!

    -

    Данная статья содержит описание синтаксиса NewLnag предыдущей версии.

    -

    Актуальную версию синтаксиса языка можно посмотреть тут.

    - -
    - -

    NewLang - это язык программирования высокого уровня, в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения.

    -

    Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка).

    -

    Новое по сравнению с прошлым выпуском:

    -
      -
    • Реализованы все основные алгоритмические конструкции: проверка условий, различные варианты циклов, сравнение по образцу, прерывание последовательности команд и возврат данных, обработка ошибок и т.д.
    • -
    • Переработан основной синтаксис для отдельных языковых конструкций.
    • -
    • Реализованы большинство операций с переменными, включая операторы раскрытие списков и тензоров.
    • -
    • Серьезно переработана система встроенных типов, реализованы функции для их преобразования и для определения данных (последнее можно назвать data comprehensions).
    • -
    • Добавлены новые тесты и пр.
    • -
    - -

    Зачем нужен NewLang?

    -

    У всех современных языков программирования происходит постоянное развитие (читай усложнение) синтаксиса по мере выхода новых версий. Это является своего рода, платой за появление новых возможностей и воспринимается пользователями как естественное явление.

    -

    Но одновременно является и серьезной проблемой, т.к. с выходом новых версий добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки и трудоемкости поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.

    -

    У NewLang сложность языковых конструкций естественно ограничена за счет разделения синтаксиса языка на две части, что упрощает его изучение и использование.

    -

    Основной синтаксис — для написания программ в объектно-ориентированном (императивном) и декларативном стилях, который основан не на зарезервированных ключевых словах, а на строгих грамматических правилах и Расширенный синтаксис — когда основного синтаксиса становится недостаточно, или требуется использовать языковую конструкцию языка реализации.

    -

    Еще одно неудобство современных мейнстримовых языков, большинство из них были созданы до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек, а не встроены в основной синтаксис языка и систему базовых типов.

    -

    У NewLang тензорные вычисления доступны «из коробки» (используется библиотека libtorch), а обычные числа являются скалярами (тензорами нулевой размерности).

    -

    Синтаксис NewLang

    -

    При разработке синтаксиса я старался придерживаться уже сложившихся в IT индустрии правил, чтобы не генерировать множественных смыслов, которые будут зависеть от контекста.

    -

    Основы

    -
      -
    • Операторы разделяются точкой с запятой «;».
    • -
    • Отступы и переводы строк игнорируются (очень хотелось иметь возможность автоматического форматирование кода).
    • -
    • Многострочные комментарии в исходном коде соответствуют стилю С/С++ и должны располагаться между символами /* и */. Вложенность многострочных комментариев не поддерживается.
    • -
    • Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash.
    • -
    • Последовательность команд, которая должна выполняться как единое целое, заключается в фигурные скобки «{}».
    • -
    • Программные вставки расширенного синтаксиса на языке реализации заключается в фигурные скобки со знаком процента %{ /* тут может быть любой код на C/C++*/ %}, как в лексерах lex и flex.
    • -
    -

    Создания объектов и присвоения новых значений

    -

    Для создания объектов и присвоения им новых значений в NewLang используется сразу три разных оператора:

    -
      -
    • ::= используется только для создания новых объектов, а если объект с таким именем уже существует, то генерируется ошибка.
    • -
    • := используется для тех же целей, но если объект с таким именем уже существует, то ошибки не происходит, а новое значение присваивается уже существующему объекту.
    • -
    • = применяется только для присвоения значения уже существующим объектам, и если объект с указанным именем отсутствует, то тоже происходит ошибка выполнения.
    • -
    -

    Использование трех разных операторов для создания/изменения объектов позволяет более гибко контролировать подобные операции и выявлять логические ошибки в коде на более раннем этапе.

    -
    var ::= 1.0; # Создать новую переменную var без указания типа
    -var = 100; # Присвоить новое значение уже существующей переменной
    -printf := @import('printf(format:Format, ...):Int'); /* Создать новый или переопределить объект printf, который будет результатом выполнения глобальной функции @import */
    -

    Идентификаторы объектов и модификаторы

    -

    В качестве идентификаторов можно использовать буквы, цифры и знаки подчеркивания в любых комбинациях, при условии, что первый символ идентификатора не является цифрой.

    -

    В NewLang существует возможность указания области видимости и времени жизни объекта с помощью модификатора — специального символа перед именем переменной. Это может показаться немного похожим на венгерскую нотацию, но в отличие от нее, модификатор не имеет отношения к типу объекта и не является частью имени идентификатора. К тому же в качестве модификаторов используется строго определённые символы, назначение которых определено заранее.

    -
      -
    • $ - в начале имени обозначает локальную переменную, время жизни которой ограничено текущей областью видимости и при её завершении локальная переменная уничтожается.
    • -
    • @ - обозначает глобальную переменную, а сам объект сохраняет свое состояние даже после выхода из текущей области видимости.
    • -
    • : - двоеточие вначале имени используется в качестве модификатора для указания типа.
    • -
    -

    Семантика обращения к аргументам функций очень похоже на работу с аргументами в bash скриптах, где $1 или $arg — порядковый номер или имя аргумента (происходит обращение к локальным переменным в текущей области видимости).

    -

    Использование модификаторов является обязательным только в двух случаях:

    -
      -
    • При создании нового типа данных, так как типы всегда создаются в глобальной области видимости, а их символьные имена должны быть уникальными.
    • -
    • При обращении к объектам NewLang внутри программных вставок кода на языке реализации, так как они используется как маркеры при поиске идентификаторов NewLang в коде С/С++.
    • -
    -

    В остальных случаях, для обращения к переменным указывать их модификаторы необязательно. И если при обращении к объекту модификатор не указан, то сперва ищется локальная переменная, а потом глобальная с таким же именем. Причем, локальная переменная будет перекрывать глобальную.

    -

    Так же следует иметь в виду, что компилятор может генерировать код для прямого обращения к локальным объектам уже на этапе компиляции, тогда как для обращения к глобальным объектам, или если модификатор области видимости отсутствует, компилятор вынужден каждый раз встраивать runtime вызов функции поиска объекта в глобальной таблице символов.

    -

    Система типов

    -

    Так как система типов языка динамическая, то явное указание типа не влияет на размер переменной и является только своего рода логическим ограничением на возможность присвоения переменной значения другого типа.

    -

    Информация о типах используется при проверке их совместимости, когда существующему объекту присваивается значение другого типа. Такая операция возможна только когда типы совместимы между собой и допускают автоматическое приведение. Это справедливо как во время парсинга/компиляции исходного теста, так и во время выполнения в режимах интерпретатора и/или скомпилированного файла.

    -

    Простые типы

    -

    Арифметические значения

    -

    Арифметические типы данных являются тензорами — массивами чисел одного типа с произвольным количеством измерений и одинаковым размером столбцов в каждом. Единичное число тоже тензор нулевого размера.

    -

    Поддерживаются только знаковые целые числа, т.к. в беззнаковых числах особая нужда отсутствует, а проблем с ними можно найти очень много на ровном месте.

    -

    Проблемы беззнаковых чисел (из интернета):

    -
    -

    Во-первых, вычитание двух беззнаковых чисел, например 3 и 5. 3 минус 5 равно 4294967294, т.к. -2 не может быть представлено как беззнаковое число. Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных значений со знаком и без знака. С++ может свободно преобразовывать числа со знаком и без знака, но не проверяет диапазон, чтобы убедиться, что вы не переполняете свой тип данных. -В C++ всё же есть несколько случаев, когда можно (или необходимо) использовать беззнаковые числа. Во-первых, числа без знака предпочтительнее при работе с битами. Во-вторых, использование беззнаковых чисел связанных с индексацией массивов.

    -
    -

    Но это не мой случай, так как индекс может быть отрицательным и даже не числом, а диапазоном или многоточием.

    -

    З.Ы. И даже зная об этом, все равно умудрился недавно словить баг с отрицательными индексами у словарей!

    -

    Имена встроенных арифметических типов говорят сами за себя: Char, Short, Int, Long, Float, Double, ComplexFloat, ComplexDouble. Отдельным типом идет логический тип Bool, который может принимать значения только 0 или 1 (false/true соответственно), и в зависимости от выполняемой операции может быть отнесен к целочисленным типам, так и не входить в их состав (данный подход интерпретации логического типа данных был взят из библиотеки Torch).

    -
    // Treat bool as a distinct "category," to be consistent with type promotion
    -// rules (e.g. `bool_tensor + 5 -> int64_tensor`). If `5` was in the same
    -// category as `bool_tensor`, we would not promote. Differing categories
    -// implies `bool_tensor += 5` is disallowed.
    -//
    -// NB: numpy distinguishes "unsigned" as a category to get the desired
    -// `bool_tensor + 5 -> int64_tensor` behavior. We don't, because:
    -// * We don't want the performance hit of checking the runtime sign of Scalars.
    -// * `uint8_tensor + 5 -> int64_tensor` would be undesirable.
    -

    В будущем планируется добавить классы чисел для длинной арифметики и дробей, для чего зарезервированы названия типов BigNum, Currency и Fraction.

    -

    Доступ к элементам тензора происходит по целочисленному индексу, который начинается с 0. Для многомерного тензора, индексы элемента перечисляются в квадратных скобках через запятую. Поддерживается доступ к элементам через отрицательный индекс, который обрабатывается точно так же, как в Python (-1 последний элемент, -2 предпоследний и т.д.).

    -

    Литерал тензор в тексте программы записывается в квадратных скобках с обязательной завершающей запятой, т.е. [1, 2,] — это литерал одномерный тензор из двух чисел. После закрывающей скобки тип тензора может быть указан в явном виде. Если тип не указан, то он выводится автоматически на основании указанных данных и выбирается минимально возможный байтовый размер, который позволяет сохранить все значения без потери точности.

    -

    Примеры:

    -
    $var_char := 123; # Тип Char выводится автоматически
    -$var_short := 1000; # Тип Short выводится автоматически
    -$var_bool := [0, 1, 0, 1,]; # Тензор из 4 элементов. Тип Bool выводится автоматически
    -$tensor[10,10]:Int := 1; # Тензор Int размером 2x2 инициализированный 1
    -$scalar := $tensor[5,5]; # Присвоить скаляру значение указанного элемента тензора
    -

    Строки

    -

    Поддерживаются два типа строк, StrWide — символьные (широкие) и StrChar — байтовые. Различия между ними заключается в типе единичного элемента. У символьных строк единичным элементом является широкий символ wchar_t, а у байтовой строки единичным элементом является один байт (точнее char, т.е. байт со знаком). Символьные строки литералы в исходном тексте записывается в «двойных кавычках», а байтовые строки в ‘одинарных кавычках’.

    -

    Количество элементов символьной строки возвращается в широких символах, а размер байтовой строки в байтах, поэтому и обращение к элементу строки по индексу происходит соответственно либо к символу, либо к байту.

    -

    Важный момент. К любой переменной можно обратиться так же, как к функции (записав после её имени круглые скобки). Результатом этой операции будет создание копии/клона объекта. Причем некоторые типы (словари, классы и символьные строки) можно использовать в качестве шаблона при создании копии объекта с модифицированными свойствами, если новые и/или изменяемые значения указать в скобках, как аргументы при вызовах функций. Так, если при создании копии в скобках указать набор новых данных, то результирующая копия будет содержать уже измененные данные.

    -

    Например:

    -
    $template := "${name} $1"; # Обычная строка
    -$result := $template("шаблон", name = "Строка"); # result = "Строка шаблон"
    -

    Системные

    -

    :Pointer - указатель на системную область памяти

    -

    Так как любой программе приходится взаимодействовать с внешним миром, то по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип Pointer. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. Но можно вывести его значение, например для отладки.

    -

    :Plain - указатель на представление данных в бинарном виде

    -

    Для взаимодействия с внешними библиотеками требуется еще и обмен данными. И для этих целей служит тип данных Plain - который также является указателем, но на двоичное представление данных в единой области памяти. Конечно, если их можно представить в виде единого фрагмента.

    -

    Составные типы данных:

    -

    Словарь

    -

    Словарь (:Dictionary) — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии (он похож и на tuple и на структуру одновременно). Словари от тензоров отличаются тем, что являются только одномерными массивами, но каждый элемент может содержать произвольное количество элементов любого типа, в том числе и другие словари.

    -

    Доступ к элементам словарей происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. Индекс также начинается с 0 и как у тензоров и тоже может быть отрицательным.

    -

    Литерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, т. е. (,) — пустой словарь, (1, 2= «2», name=3,).

    -

    Перечисление, структура и объединение

    -

    :Enum, :Struct и :Union — это такие же словари, только на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера.

    -

    Классы

    -

    Класс (реализован частично) — тип данных, с помощью которого реализуется один из принципов ООП — наследование. При создании экземпляра класса создается новая переменная, у которой сохраняется информацию о своем родителе и которая наследует от него свойства и методы. Тип данных :Class аналогичен словарю, но все свойства обязаны иметь имена (хотя доступ к свойствам класса по индексу так же возможен).

    -

    Функции

    -

    Синтаксис NewLang поддерживать несколько типов функций (а в будущем и методов классов): обычные функции, чистые функции и простые чистые функции.

    -

    Для всех типов функций поддерживаются аргументы по умолчанию. При создании функции, её аргументы указываются как в Python, т.е. вначале идут обязательные аргументы, потом аргументы со значениями по умолчанию, где имя аргумента отделяется от его значения по умолчанию знаком равно =. Если функция допускает обработку произвольного количества аргументов, то последним в списке параметров указывается многоточие (три точки подряд) .

    -

    Обычная функция

    -

    Обычная функция — такие функции являются именно обычными функциями в понимании С/С++. Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д.

    -

    Внутри обычной функции можно обращаться к локальным и глобальным объектам, и они могут содержаться вставки на языке реализации*, например, для вызова функций из внешних библиотек.

    -

    Вставки на языке реализации оформляются в виде %{ %} и могут содержать любой текст на С/С++, а прямо из него можно обращаться к локальным и глобальным объектам NewLang так же, как и в обычном синтаксисе, указывая первым символом имени соответствующий модификатор ($ для локальных объектов и @ для глобальных).

    -

    Технически, такая программная вставка просто переносится трансплайтером непосредственно в исходный текст генерируемого файла, а все идентификаторы NewLang специальным образом декорируются (добавляются специальные маркеры для их идентификации), после этого исходный текст подается на вход обычному компилятору С++. Для локальных объектов трансплайтер может генерировать код для прямого доступа к объекту на этапе компиляции, а для работы с глобальными объектами вынужден использовать runtime вызовы функции поиска в таблице символов.

    -
    -

    *) - Программные вставки на языке реализации обрабатываются только во время компиляции

    -

    Например:

    -
    print(str) := { 
    -    %{ 
    -        printf("%s", static_cast<const char *>($str)); /* Прямой вызов С функции */ 
    -    %} 
    -};
    -

    Чистые функции

    -

    Чистая функция — это тоже обычная функция, только в том смысле, какой в него вкладывает функциональное программирование. Создания чистой функции происходит с помощью оператора :-, а сам оператор заимствован из языка Пролог. У чистой функции отсутствует доступ к контексту и глобальным переменным, поэтому она может обрабатывать только те данные, которые были ей переданы в качестве аргументов.

    -

    Программные вставки на языке реализации внутри чистых функций не запрещены и могут использоваться, например, для отладки. Но делается это на страх и риск разработчика. Именно он отвечает за их «чистоту», например при вызове функций из внешних библиотек.

    -
    Sum(arg1, arg2) :- {$arg1+$arg2;}; # Вернуть сумму аргументов
    -

    Простые чистые функции

    -

    Простые чистые функции — отдельный класс чистых функций, которые предназначены только для вычисления логического результата (т.е. они являются предикатами) и их отличает упрощенная формой записи. Тело простой чистой функции состоит из последовательности операторов, которые разделяются запятыми и заканчиваются, как и любое выражение, точкой с запятой. Все операторы простой чистой функции всегда приводятся к булевому значению, а итоговый результат функции вычисляется по одной из возможных логических операций: И, ИЛИ и исключающее ИЛИ.

    -

    Например:

    -
    func_and(arg1, arg2) :&&= arg1==3, arg2 > 0;  # Простая чистая функция Логическое И
    -func_or(arg1, arg2) :||= arg1==3, arg2 > 0; # Простая чистая функция Логическое ИЛИ
    -func_xor(arg1, arg2) :^^= arg1==3, arg2 > 0;  # Простая чистая функция Исключающее ИЛИ
    -

    Специальные типы данных:

    -

    Пусто (:None)

    -

    :None (пусто) — не содержит значения (точнее имеет одно значение None) и совместим с любым другим типом данных. Указывается в тексте программы как один подчерк «_». None имеют не инициализированные переменные и при попытке чтения из такой переменной возникает ошибка.

    -

    Тип переменной может быть явно указан или выведен автоматически из присваиваемого значения. Присвоить новое значение уже инициализированной переменной можно только для совместимого типа, так как неявное преобразование типов не допускаются.

    -
    $var := _; # Создать не инициализированную переменную
    -$var2 := var; # Ошибка!!! Нельзя прочитать неинициализированную переменную var
    -$var = 1000; # У переменной будет тип Short (минимальный размер для хранения значения)
    -$var = 0,5; # Ошибка!!! Short ← Float не совместимы
    -$var = _; # Очистить значение переменной
    -$var = 0,5; # Теперь можно, т. к. None совместим с любым типом
    -

    Диапазон (:Range)

    -

    Диапазон — специальный тип данных, являющейся приблизительным аналогом типа «генератор» в Python. К диапазону можно обращаться как к итератору и он будет поочередно выдавать элементы в указанном интервале с заданным шагом. Диапазон в тексте программы указывается как два или три элемента через две точки, например 1..5 — диапазон от единицы до пяти с шагом по умолчанию 1. В качестве параметров диапазона можно указывать не только литералы, но и имена переменных. Например, 0,1..$stop..0,1 — диапазон от 0,1 до значения, указанного в переменной $stop с шагом 0,1.

    -

    Диапазон для целых чисел можно использовать в качестве индекса у тензоров (точнее, у любых объектов, которые допускают доступ к своим элементам по индексу, т.е. тензоры, словари и текстовые строки). Фактический, это поведение аналогично slice в языке Python и array[1:5] в Python означает тоже самое, что и array[1..5] в NewLang.

    -

    В качестве индекса у тензоров еще можно указать произвольное количество измерений с помощью многоточия, т.е.

    -
    $tensor[…, 0] = 0; # Обнулить все первые элементы в каждом измерении.
    -

    Преобразование типов

    -

    Явное приведение типов

    -

    Несмотря на динамическую типизацию языка, если тип переменной указан явно, то автоматическое приведение типов не выполняется, и чтобы присвоить переменой значение не совместимого типа, требуется явное преобразование.

    -

    Так как символьные названия типов относятся к деталям реализации, то явное преобразование в конкретный тип данных производится с помощью вызова функции с именем типа, т.е. :Bool(), :StrWide(), :Long() и т.д.

    -

    Для преобразования любого типа данных в строку ещё можно использовать оператор конкатенации строк, которой преобразует любой тип данных в строковое представление. Но, так как строковых типов два (байтовые и широкие строки), то тип строки определяется первым аргументом в операторе конкатенации/сцепления ++. Также преобразовать любое значение в строковое можно с помощью строки-шаблона.

    -
    "" ++ 123;   # "123" - Строка широких символов
    -'' ++ 123;   # '123' - Байтовая строка
    -
    -val := 12345;   # Число
    -"$1"(val);      # Будет строка "12345"
    -

    Так как тензоры могут иметь больше одного значения, то и в качестве аргументов могут принимать их произвольное количество, а итоговым результатом будет тензор, в котором все переданные данные преобразованы к требуемому типу автоматически.

    -

    Примеры:

    -
    > tstr := :Tensor("Тест");   # Создать тензор из строки широких символов
    -[1058, 1077, 1089, 1090,]:Int
    -
    -> t2 := :Tensor[2,2]("Тест"); # Тоже самое, но тензор указанной размерности
    -[
    -  [1058, 1077,], [1089, 1090,],
    -]:Int
    -
    -> :StrWide(tstr) # Создать символьную строку из тензора
    -Тест
    -
    -> :Double(t2)    # Изменить тип данных тезора без изменения размерности
    -[
    -  [1058, 1077,], [1089, 1090,],
    -]:Double
    -
    -> t3 := :Char[4]( t2 ) # Изменить размерность тензора и его тип (в данном случае с частичной потерей данных)
    -[34, 53, 65, 66,]:Char
    -
    -
    ->:Tensor( (1,2,3,) );  # Тензор из словаря
    -[1, 2, 3,]:Char
    -
    ->:Tensor( 'first second' )  # Байтовая строка в тензор
    -[102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char
    -
    ->:Tensor( (first='first', space=32, second='second',) )  # Получаем тензор из словаря с такими же данными
    -[102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char
    -
    ->:Double[10,2]( 0, ...)   # Тензор заданного формата с нулями, где многоточие повторяет последние указанные данные до получения тензора требуемого размера
    -[
    -  [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,],
    -]:Double
    -
    ->:Int[3,2]( ... rand() ...)  # Тензор со случайными данными, где между многоточиями указана функция, которую следует вызывать каждый раз при получении нового элемента тензора
    -# Пришлось придумывать новую конструкцию, т.к. многоточие перед именем, это оператор раскрытия словаря, а многоточие после имени, это повторение последнего значения до конца заданной размерности.
    -[
    -  [1804289383, 846930886,], [1681692777, 1714636915,], [1957747793, 424238335,],
    -]:Int
    -
    ->:Int[5,2]( 0..10 );  # Создание тензора из диапазона
    -[
    -  [0, 1,], [2, 3,], [4, 5,], [6, 7,], [8, 9,],
    -]:Int
    -
    ->:Tensor( 0..0.99..0.1 );  # Или даже так
    -[0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,]:Double
    -

    Операторы и управляющие конструкции

    -

    Операторы:

    -

    Все операторы имеют парный аналог с присвоением значения:

    -
      -
    • + и += - сложение арифметических типов данных;
    • -
    • - и -= - вычитание арифметических типов данных;
    • -
    • / и /= - деление (результат число с плавающей точкой);
    • -
    • // и //= - целочисленное деление с округлением к меньшему числу (как в Python);
    • -
    • * и *= - умножение;
    • -
    • ** и **= - возведение в степень (он же используется и для повторения текстовых строк);
    • -
    • ++ и ++= - конкатенация строк с автоматическим приведением аргументов к стоковому типу (символ инкремента специально используется вместо одиночного плюса для того, чтобы в явном виде разделить конкатенацию строк и операторы арифметического сложения).
    • -
    -

    Операторы сравнения:

    -
      -
    • <, >, <=, >= - классические для сравнения скаляров
    • -
    • == и != - операторы сравнения с автоматическим приведением совместимых типов для любых объектов
    • -
    • === и !== - оператор точного сравнения для любых объектов (автоматического приведения типов не выполняется)
    • -
    -

    Проверки типа (имени класса объекта):

    -

    Для оператора проверки имени класса объекта используется символ тильда ~. Он немного похож на оператор instanceof в Java. Левым операндом должен быть проверяемый объект, а правым — проверяемый тип, который можно указать строкой литералом, переменной строкового типа или именем проверяемого класса непосредственно. Результатом операции будет истина, если правый операнд содержит название класса проверяемого объекта или он присутствует в иерархии наследования.

    -
    name := "class";    # Строковая переменная с именем класса
    -var ~ name;         
    -var ~ :class;       # Имя типа
    -var ~ "class";      # Строка литерал с именем типа
    -

    Утиная типизация

    -

    Оператор утиной типизации, два символа тильны ~~ — приблизительный аналог функции isinstance() в Python, который для простых типов сравнивает непосредственную совместимость типа левого операнда по отношению к правому. А для словарей и классов в левом операнде проверяется наличие всех имен полей, присутствующих у правого операнда, т.е.:

    -
    (field1=«value», field2=2,) ~~ (); # Истина (т. е. левый операнд словарь)
    -(field1=«value», field2=2,) ~~ (field1=_); # Тоже истина (т. к. поле field1 присутствует у левого операнда)
    -(field1=«value», field2=2,) ~~ (not_found=_); # Ложь, т.к. поле not_found у левого операнда отсутствует
    -

    Строгая утиная типизация ~~~ — для простых типов сравнивается идентичности типов без учета совместимости, а для составных типов происходит сравнение всех свойств с помощью оператора строгого равенства. Для данной операции, пустой тип совместим только с другим пустим типом.

    -

    Управляющие конструкции

    -

    К управляющим конструкциям языка NewLang относятся условный оператор, два вида циклов, оператор оценки выражения, оператор прерывания последовательности выполнения команд и перехват прерывания. Операторы проверки условий всегда указываются в квадратных скобках, а последовательность команд для выполнения - в фигурных.

    -

    Условный оператор

    -

    В качестве оператора проверки условия используется синтаксическая конструкция, соответствующая по смыслу термину «следует», т.е. тире и угловая скобка -> или с двумя тире для большей наглядности –>. Такая запись условного оператора очень похожа на математическую и легко объединяется в последовательности для проверки множественных условий вида «else if».

    -

    В общем случае условный оператор имеет вид: [ условие ] -> действие; или [ условие ] -> {действие}; или [ условие1 || условие2 ] --> {действие}, [_] --> {действие иначе};

    -

    Для наглядности записанный с отступами:

    -
    [ условие1 ] -> { действие1 },
    -    [ условие2 ] -> действие2,
    -    [ условие3 ] -> действие3,
    -    [_] -> {действие_иначе};
    -

    Оценка выражения

    -

    Синтаксическая конструкция с помощью которой реализуется аналог оператора switch выглядит следующим образом:

    -
    [ $var ] ==> {
    -    [1] -> { code };     # Выполнится проверка условия $var == 1
    -    [1, 2] -> { code };  # Выполнится проверка условия ($var == 1 || $var == 2)
    -    [_] -> { code default };  # Ветка условия иначе
    -};
    -

    Причем в качестве оператора для оценки могут быть использован любые имеющиеся операторы сравнения на равенство:

    -
      -
    • ==> - проверка на равенство с приведением типов;
    • -
    • ===> - проверка на точное равенство;
    • -
    • ~> - проверка типа (имени класса);
    • -
    • ~~> - утиная типизация;
    • -
    • ~~~> - строгая утиная типизация.
    • -
    -

    И если в качестве оператора сравнения использовать оператор утиной типизации, то оценка выражения превращается в классический Pattern Matching:

    -
    $value := (f1=1, f2="2",);
    -[ $value ] ~~~> {
    -    [ (f1=_, ), (f1=_, f2=0, ) ] -> { code };     # Поле f2 отсутствует или число 
    -    [(f1=_, f2="",), (f1=_, f2='',)] -> { code }; # Поле f2 строка
    -    [_] -> { code default };                      # Код по умолчанию
    -};
    -

    Операторы циклов

    -

    Для указания операторов циклов используются управляющие или –» (с двумя стрелками по направлению от проверки условия к телу цикла). И в зависимости от расположения условия и тела цикла, он может быть с предусловием (while) или постусловием (do while). Хотя пока эти синтаксические конструкции не “отлежались” и их можно считать временными из-за того, что их легко перепутать с условным оператором, и, возможно, имеет смысл заменить разные операторы цикла одной единственной конструкцией вида: <–> или «-», которая сильнее отличается от оператора следования.

    -

    Но в настоящий момент циклы реализованы вот так:

    -
    [условие while] ->> {
    -  тело цикла while
    -};
    -
    -{
    -  тело цикла do while
    -} <<-- [условие do while];
    -

    Реализация цикла foreach на примере суммирования всех элементов словаря (или одномерного тензора):

    -
    summa := 0;
    -dict := (1,2,3,4,5,);
    -[ dict ] -->> {           # Условие цикла, пока есть данные
    -  item, dict := ... dict; # Результат оператора раскрытия словаря - первый его элемент перемещается в item
    -  summa += item;          # Вычисление суммы всех элементов словаря
    -};
    -

    Операторы прерывания (возврата)

    -

    В качестве оператора прерывания/возврата используется два символа минус . Оператор позволяет прервать выполнение последовательности команд и/или вернуть данные из текущей функции/блока кода и является самым близким аналогом оператора return и throw одновременно. Для того чтобы вернуть данные, их необходимо указать между двумя операторами прерывания, т.е. --100--; # Вернуть указанное значение. Если возвращаемое значение не указано явно, то будет возвращено значение None.

    -

    Следование (блок кода/лямбда функция)

    -

    Алгоритмическая конструкция, которая отвечает последовательное выполнение нескольких команд/операторов и возвращающая результат выполнения последнего из них. Также, результатом выполнения может быть значение, которое возвращается с помощью оператора прерывания (возврата). Это очень похоже на классическую лямбда функцию, только она выполняется сразу во время определения, а в переменную сохраняется уже результат её выполнения.

    -

    Следование без перехвата прерывания оформляется в виде последовательности обычных и фигурных скобок, т.е. (){ run code }; или тоже самое, но сохраняет результата выполнения в переменной: $result := (){ run(); code() };. Но если внутри такой функции будет выполнен оператор прерывания, то она никогда вернет управления и не сохранит возвращаемое значение в переменой $result!

    -

    Чтобы перехватывать прерывания, в том числе и возвращаемые значения, необходимо использовать конструкция следования с перехватом прерываний, которая оформляется в виде последовательности обычных и двойных фигурных скобок, т.е. $error := (){{ run(); error();code() }};. Такая конструкция перехватывает все возвраты и прерывания, если они возникают во время выполнения последовательности команд. В этом случае любой результат будет сохранен в переменной $error как при нормальном завершении, так и в случае возникновения ошибки.

    -

    Для более тонкой настройки перехвата прерываний следует использовать типизированную конструкцию, когда в явном виде указывается, какие типы прерываний следует перехватывать. $runtime := (){{ run(); error(); code() }}:ErrorRuntime;. Такая конструкция вернет результат только в случае успешного завершения (когда с помощью оператора прерывания возвращается не типизированное значение, например, --"Строка"--;), или при создании прерывания с указанием конкретного типа –:ErrorRuntime(“Описание ошибки”)–;. А вот при возникновении любого другого типизированного прерывания, значение перехвачено не будет и все отработает как самый первый вариант, т.е. без перехвата прерывания и без сохранения возвращаемого значения в переменную.

    -

    Стратегия обработки ошибок

    -

    Обработка ошибок состоит из комбинации двух элементов: оператора прерывания выполнения с указанием типа возвращаемого значения и алгоритмической конструкции следование с возможностью перехвата прерывания заданного типа.

    -

    Это немного отличается от классического варианта обработки исключений, который в обычных языках программирования обычно оформляется ключевыми словами try… catch… finally с различными вариациями. Ведь основная цель подобных синтаксических конструкций — выделить участок кода, где возможно возникновение ошибки, перехватить и обработать правильный тип данных (исключений), т.к. NewLang не делает различий между операторами возврата и генерации исключения.

    -

    Подход к обработке исключений следующий:

    -

    Программный код, который может привести к ошибке, заключается в двойные фигурные скобки, а результат выполнения такого блока кода присваивается переменной. После этого анализируется возвращенное значение, например, оператором сравнения по образцу:

    -
    $result := (){{     # начало аналога блока try
    -    $value := call_or_exception1();
    -    [условие1] -> { -- :Error -- };
    -    [условие2] -> { -- $value -- };
    -    $value := call_or_exception2();   
    -}};                 # конец аналога блока try
    -              
    -[$result] ~> {      # Для сравнения по образцу использовать оператор проверки типа (имени класса)
    -    [:ErrorParser] -> {Код обработки ошибок парсера};
    -    [:ErrorRunTime] -> {Код обработки ошибок времени выполнения};
    -    [:Error] -> { Код обработки остальных ошибок };
    -    [_] -> { Обработка нормальных данных $value без ошибок };
    -};
    -

    Сборка REPL из исходников (пока только под Linux)

    -

    Подготовка репозитория

    -
      -
    • Скачать исходники
    • -
    • Скачать и развернуть архив libtorch в каталоге contrib (PyTorch Build: Stable (1.10.*) -> Your OS: Linux -> Package: LibTorch -> Language: C++ / Java -> Compute Platform: CPU -> Download here (cxx11 ABI): -libtorch-cxx11-abi-shared-with-deps-1.10.2+cpu.zip)
    • -
    • Активировать и скачать исходники субмодулей (git submodule init && git submodule update)
    • -
    • В каталоге contrib запустить файл build.sh для сборки библиотеки libffi
    • -
    • В каталоге core запустить файл compile_syntax.sh для генерации файлов парсера и лексического анализатора. Также может потребоваться установка утилит flex и bison. Если что, у меня установлены flex 2.6.4 и bison (GNU Bison) 3.7.4
    • -
    -

    Собрать

    -
      -
    • Юнит-тесты (newlang_test): в каталоге core выполнить команду make CONF=UnitTest*
    • -
    • Интерпретатор (nlc): в каталоге core выполнить команду make CONF=Debug*
    • -
    -
    -

    *) - Сборка проекта выполняется обычной утилитой make, но сборочные файлы генерируются автоматически в давно устаревшей версии NetBeans 8.2, т.к. это единственная универсальная среда разработки с поддержкой Makefile “из коробки”, тогда как в текущей версии Apache NetBeans полноценная поддержка разработки на С/С++ вообще отсутствует. Начал постепенный переход на использование редактора VSCodium (аналога VSCode, в котором вычищена телеметрия от Microsoft) и генерацию скриптов сборки с помощью сmake, но этот процесс пока не завершен.

    -

    Планы на будущее

    -

    Текущая версия языка значительно обогатилась возможностями, но все еще является тестовой платформой для проверки декларируемых концепций и основного синтаксиса. Если говорить о планах, то в настоящий момент роадмап развития NewLang следующий:

    -
      -
    • Реализовать макросы для более привычного использования языка (за счет использования DSL);
    • -
    • Добавить в арифметические типы длинные числа и дроби;
    • -
    • Сделать какую-нибудь логическую игру (крестики нолики, судоку или что-то похожее) с алгоритмическим выбором следующего хода и его вычислением с помощью машинного обучения;
    • -
    • Написать еще больше разных примеров для оценки синтаксиса;
    • -
    • Зафиксировать синтаксис с учетом полученного опыта и обратной связи;
    • -
    • Восстановить работоспособность компилятора для генерации исполняемых файлов;
    • -
    • Сделать очередную большую чистку кода;
    • -
    • Переработать и задокументировать получившуюся семантику языка с учетом всех возможностей и выпустить первую полнофункциональную версию NewLang.
    • -
    - -
    - - - - - - - - - - - - - - - - -
    -

    Новый язык программирования

    - - -

    КДПВ

    - - -
    -

    Внимание!!!

    -

    Данная статья содержит описание синтаксиса NewLnag предыдущей версии.

    -

    Актуальную версию синтаксиса языка можно посмотреть тут.

    - -
    - -

    Более года назад я начал публикацию статей с описанием особенностей нового языка программирования. -С тех пор утекло много воды, было протестировано множество идей, в итоге несколько раз все поменялось кардинальным образом -и сейчас представляю на суд читателей описание предфинальной версии языка и его особенностей.

    -

    Данная статья предназначена в первую очередь для проверки основных концепций нового языка программирования, а также для получения обратной связи от читателей Хабра. -Ведь согласно наблюдению Хабр-ума палата, не замыленный взгляд со стороны очень сильно помогает в проработке новых идей.

    -

    Этот проект очень долго был без собственного названия и в публикациях назывался просто и абстрактно “новый язык”. -Но после нескольких статей, временное название “новый язык” постепенно превратилось в имя собственное NewLang, -которое я и решил в конечном итоге оставить (что еще раз подтверждает поговорку, что нет ничего более постоянного, чем что-то временное).

    -

    NewLang - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические конструкции -с декларативным программированием и тензорными вычислениями для задач машинного обучения.

    -

    Основной особенностью языка является легкий, логичный и непротиворечивый синтаксис, который основан не на использовании зарезервированных ключевых слов, -а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка). -Основные свойства и особенности языка:

    -
      -
    • Возможность работы как в режиме интерпретатора, так и компилятора.
    • -
    • Динамическая и статическая типизация с возможностью указания типов в явном виде.
    • -
    • Статическая типизация является условно строгой (автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных, например, целое число может быть автоматически преобразовано в вещественное, но не наоборот)
    • -
    • Автоматическое управление памятью.
    • -
    • ООП в виде явного наследования классов и утиная типизация.
    • -
    • На уровне синтаксиса поддержка нескольких типов функций (обычные и чистые функции без побочных эффектов).
    • -
    • Необязательные и именованные параметры функций.
    • -
    • Возможны вставки кода на языке реализации (С/С++).
    • -
    • Простая интеграция с уже существующими программными библиотеками (в том числе импорт нативных переменных и функций из С/С++).
    • -
    • Имеется REPL read-eval-print loop — «цикл: чтение — вычисление — вывод».
    • -
    -

    Зачем нужен NewLang?

    -

    У всех современных языков программирования происходит постоянное развитие (читай усложнение) синтаксиса по мере выхода новых версий. -Это является своего рода, платой за появление новых возможностей и воспринимается пользователями как естественное явление.

    -

    Но одновременно является и серьезной проблемой, т.к. с выходом новых версий добавляются новые ключевые слова и синтаксические конструкции, -что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки -и трудоемкости поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.

    -

    У NewLang сложность языковых конструкций естественно ограничена за счет разделения синтаксиса языка на две части, -что упрощает его изучение и использование. Основной синтаксис — для написания программ в объектно-ориентированном (императивном) -и декларативном стилях, который основан не на зарезервированных ключевых словах, а на строгих грамматических правилах -и Расширенный синтаксис — когда основного синтаксиса становится недостаточно, или требуется использовать языковую конструкцию языка реализации.

    -

    Еще одно неудобство современных мейнстримовых языков, большинство из них были созданы до начала эпохи машинного обучения, -поэтому тензорные вычисления у них выполнены в виде отдельных библиотек, а не встроены в основной синтаксис языка и систему базовых типов. -У NewLang тензорные вычисления доступны «из коробки» (используется библиотека libtorch), -а арифметические типы данных являются скалярами (тензорами нулевой размерности).

    -

    Основной синтаксис

    -

    Основной синтаксис NewLang - простой и логичный за счет того, что он построен исключительно на грамматических правилах -и не использует каких либо зарезервированных ключевых слов, а все буквенно-символьные последовательности рассматриваются как идентификаторы -в которых можно использовать любые не-ASCII символы.

    -
    -

    Идеализированная цель отказа от ключевых слов, приблизить чтение исходного текста программы к чтению обычного текста за счет использования знаков препинания при описании логики работы алгоритма.

    -
    -
    -

    Конечно запятая человек может вычленять ключевые управляющие слова языка и слеш или учитывать форматирование программы запятая -чтобы на их основе понимать синтаксические конструкции запятая хотя при обычном чтении мы привыкли опираться именно на семантику -знаков препинания точка мы конечно можем писать знаки препинания и обычным текстом точка но согласитесь запятая что тогда -открытая скобка например запятая вот такой вот текст закрытая скобка будет очень не удобно читать точка

    -
    -

    Названия встроенных типов или имена служебных функций системной библиотеки определяются конкретной реализацией языка, -поэтому не являются зарезервированными ключевыми словами и при необходимости могут быть переопределены, например, -для создания собственного, предметно-ориентированного диалекта (DSL - domain-specific language), если в этом возникнет необходимость. -Но сама структура программы и логика выполняемого алгоритма все равно останутся понятны всем, кто знаком с правилами основного синтаксиса NewLang.

    -

    Пример скрипта Hello world! на NewLang

    -
        #!./nlc --eval 
    -    # Определение функции hello
    -    hello(str) := { 
    -    printf := @import('printf(format:Format, ...):Int');  # Импорт стандартной C функции
    -    printf('%s\n', $str);  # Вызов C функции с проверкой типов аргументов по строке формата
    -    };
    -    hello('Привет, мир!'); # Вызвать функцию
    -

    Вывод: Привет, мир!

    -

    Расширенный синтаксис

    -

    Расширенный синтаксис — это возможность вставить в текст программы NewLang исходный код на языке реализации. -Сейчас это С/С++, что позволяет использовать любые возможности этого мощного языка программирования.

    -

    Обработка расширенного синтаксиса происходит на этапе компиляции приложения, а взаимодействие между основным и расширенным синтаксисами происходит за счет совместного использования идентификаторов, -которое полностью прозрачно для пользователя и подчиняется единым грамматическим правилам основного синтаксиса.

    -

    Еще немного примеров:

    -

    Любая последовательность вычислений возвращает результат выполнения последнего оператора. -Поэтому выполнение одной команды или последовательности команд всегда возвращает какой-либо результат, -а оператор возврата из функции необязателен, так как результатом будет значение последнего вычисленного выражения.

    -

    Создание переменных

    -
        scalar := 42
    -    42
    -
        tensor := [1,2,3,4,5,]  # Тип тензора выводится автоматически
    -    [1, 2, 3, 4, 5,]:Char
    -
        str := '$1 string'
    -    $1 string
    -

    Арифметические операции

    -
        tensor * 2
    -    [2, 4, 6, 8, 10,]:Short
    -
        tensor * 20
    -    [20, 40, 60, 80, 100,]:Short
    -
        tensor * 0.5
    -    [0.5, 1, 1.5, 2, 2.5,]:Double
    -
        tensor / 2 # Результат деления — число с плавающей точкой
    -    [0.5, 1, 1.5, 2, 2.5,]:Double
    -
        tensor // 2 # Целочисленное деление без остатка
    -    [0, 1, 1, 2, 2,]:Char</source>
    -
        tensor % 2 # Целочисленный остаток от деления
    -    [1, 0, 1, 0, 1,]:Char</source>
    -

    Строковые операции

    -
        str = 'сцепеление строк ' ++ str;
    -    сцепеление строк $1 string
    -
        str('строка как шаблон');
    -    сцепеление строк строка как шаблон string
    -

    Преобразование тензоров

    -

    В эпоху машинного обучения тензоры являются основными элементами вычислений, -поэтому для конвертирования данных в тензоры используется отдельная синтаксическая конструкция, -состоящая из двойных квадратных скобок [[ данные ]]. Подробнее про особенности преобразования типов можно прочитать далее.

    -
        tstr := [["Тест"]]   # Создать тензор из строки широких символов
    -    [1058, 1077, 1089, 1090,]:Int
    -
        t2 := [[ "Тест" ]]:Int[2,2] # Тоже самое, но тензор двухмерный
    -    [
    -        [1058, 1077,], [1089, 1090,],
    -    ]:Int</source>
    -
        StrWide(tstr) # Конвертировать тензор обратно в строку
    -    Тест
    -
        Double(t2)    # Изменить тип данных тезора
    -    [
    -        [1058, 1077,], [1089, 1090,],
    -    ]:Double
    -
        t3 := [[ t2 ]]:Char[4] # Преобразовать тип данных тензора и его размерность
    -    [34, 53, 65, 66,]:Char
    -

    Синтаксис NewLang:

    -

    При разработке синтаксиса я старался придерживаться уже сложившихся правил, чтобы не создавать множественных смыслов, -зависящих от контекста. И одновременно «объять необъятное»

    -

    Основы

    -
      -
    • Операторы разделяются точкой с запятой «;».
    • -
    • Отступы и переводы строк игнорируются (очень хотелось иметь возможность автоматического форматирование кода).
    • -
    • Многострочные комментарии в исходном коде соответствуют стилю С/С++ и должны располагаться между символами /* и */. Вложенность многострочных комментариев не поддерживается.
    • -
    • Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash.
    • -
    • Последовательность выполняемых команд, которая должна выполняться как единое целое, заключается в фигурные скобки «{}».
    • -
    • Программные вставки расширенного синтаксиса на языке реализации заключается в фигурные скобки со знаком процента %{ /* тут может быть любой код на C/C++*/ %}.
    • -
    -

    Создания объектов и присвоения новых значений

    -

    Для создания объектов и присвоения им новых значений в NewLang используется сразу три разных оператора.
    -Оператор «::=» используется только для создания новых объектов, а если объект с таким именем уже существует, то генерируется ошибка.
    -Оператор «:=» используется для тех же целей, но если объект с таким именем уже существует, то ошибки не происходит, -а новое значение присваивается уже существующему объекту.
    -И последний оператор «=» применяется только для присвоения значения уже существующим объектам, и если объект с указанным именем отсутствует, то тоже происходит ошибка.

    -

    Использование трех разных операторов для создания/изменения объектов позволяет более гибко контролировать подобные операции и выявлять логические ошибки в коде на более раннем этапе.

    -
        var ::= 1.0; # Создать новую переменную var без указания типа
    -    var = 100; # Присвоить новое значение уже существующей переменной
    -    printf := @import('printf(format:Format, ...):Int'); /* Создать новый или переопределить 
    -    объект printf, который будет результатом выполнения глобальной функции @import */
    -

    Идентификаторы объектов и модификаторы

    -

    В качестве идентификаторов можно использовать буквы, цифры и знаки подчеркивания в любых комбинациях, при условии, -что первый символ идентификатора не является цифрой.

    -

    В NewLang существует возможность указания области видимости и времени жизни объекта с помощью модификатора — специального символа перед -именем переменной. Это может показаться немного похожим на венгерскую нотацию, но в отличие от нее, -модификатор не имеет отношения к типу объекта и не является частью имени идентификатора. -К тому же в качестве модификаторов используется строго определённые символы, назначение которых определено заранее.

    -

    Так, символ «$» в начале имени обозначает локальную переменную, время жизни которой ограничено текущей областью видимости и при её завершении локальная переменная уничтожается. -Символ «@» обозначает глобальную переменную, а сам объект сохраняет свое состояние даже после выхода из текущей области видимости. -Так же обозначаются и имена типов данных, например, при создания новых типов, а в качестве модификатора используется символа двоеточия «:»

    -

    Семантика обращения к аргументам функций очень похоже на работу с аргументами в bash скриптах, где $1 или $arg — порядковый номер -или имя аргумента (происходит обращение к локальным переменным в текущей области видимости).

    -

    Использование модификаторов является обязательным только в двух случаях: -- При создании нового типа данных, так как типы всегда создаются в глобальной области видимости, а их символьные имена должны быть уникальными -- При обращении к объектам NewLang внутри программных вставок кода на языке реализации, так как они используется как маркеры при поиске идентификаторов NewLang в коде С/С++.

    -

    В остальных случаях, для обращения к переменным указывать их модификаторы не обязательно. -И если при обращении к объекту модификатор не указан, то сперва ищется локальная переменная, а потом глобальная с таким же именем. -Причем, локальная переменная будет перекрывать глобальную.

    -

    Так же следует иметь в виду, что компилятор может генерировать код для прямого обращения к локальным объектам уже на этапе компиляции, -тогда как для обращения к глобальным объектам, или если модификатор области видимости отсутствует, компилятор вынужден каждый раз встраивать runtime вызов функции поиска объекта в таблице символов.

    -

    Система типов

    -

    Так как система типов языка динамическая, то явное указание типа не влияет на размер переменной и является только своего рода логическим ограничением на возможность присвоения переменной значения другого типа.

    -

    Информация о типах используется при проверке их совместимости, когда существующему объекту присваивается значение другого типа. -Такая операция возможна только когда типы совместимы между собой и допускают автоматическое приведение. -Это справедливо как во время парсинга/компиляции исходного теста, так и во время выполнения в режимах интерпретатора и/или скомпилированного файла.

    -

    Арифметические типы:

    -

    Арифметические типы данных являются тензорами - массивами чисел одного типа с произвольным количеством измерений и одинаковым размером столбцов в каждом. -Единичное число тоже тензор нулевого размера.

    -

    Поддерживаются только знаковые целые числа, т.к. в беззнаковых числах особая нужда отсутствует, а проблем с ними можно найти очень много на ровном месте.

    -

    Проблемы беззнаковых чисел (из интернета)

    -
    -

    Во-первых, вычитание двух беззнаковых чисел, например 3 и 5. 3 минус 5 равно 4294967294, -т.к. -2 не может быть представлено как беззнаковое число. Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных -значений со знаком и без знака. С++ может свободно преобразовывать числа со знаком и без знака, -но не проверяет диапазон, чтобы убедиться, что вы не переполняете свой тип данных.

    -

    В C++ всё же есть несколько случаев, когда можно (или необходимо) использовать беззнаковые числа. -Во-первых, числа без знака предпочтительнее при работе с битами. Во-вторых, использование беззнаковых чисел связаных с индексацией массивов.

    -
    -

    Но это мой случай, так как индекс может быть отрицательным и даже не числом, а диапазоном или многоточием. -З.Ы. И даже зная об этом, все равно умудрился недавно словить баг с отрицательными индексами у словарей!

    -

    Имена встроенных арифметических типов говорят сами за себя: Char, Short, Int, Long, Float, Double, ComplexFloat, ComplexDouble. -Отдельным типом идет логический тип Bool, который может принимать значения только 0 или 1 (false/true соответственно), -и в зависимости от выполняемой операции может быть отнесен к целочисленным типам, так и не входить в их состав.

    -

    (данный подход интерпретации логического типа данных был взят из библиотеки Torch)

    -
    // Treat bool as a distinct "category," to be consistent with type promotion
    -// rules (e.g. `bool_tensor + 5 -> int64_tensor`). If `5` was in the same
    -// category as `bool_tensor`, we would not promote. Differing categories
    -// implies `bool_tensor += 5` is disallowed.
    -//
    -// NB: numpy distinguishes "unsigned" as a category to get the desired
    -// `bool_tensor + 5 -> int64_tensor` behavior. We don't, because:
    -// * We don't want the performance hit of checking the runtime sign of Scalars.
    -// * `uint8_tensor + 5 -> int64_tensor` would be undesirable.
    -

    В будущем планируется добавить классы чисел для длинной арифметики и дробей, для чего зарезервированы названия типов BigNum, Currency и Fraction.

    -

    Доступ к элементам тензора происходит по целочисленному индексу, который начинается с 0. -Для многомерного тензора, индексы элемента перечисляются в квадратных скобках через запятую. -Поддерживается доступ к элементам через отрицательный индекс, который обрабатывается точно так же, -как в Python (-1 последний элемент, -2 предпоследний и т.д.).

    -

    Литерал тензор в тексте программы записывается в квадратных скобках с обязательной завершающей запятой, т.е. [1, 2,] - это литерал одномерный тензор из двух чисел. -После закрывающей скобки тип тензора может быть указан в явном виде. Если тип не указан, то он выводится автоматически на основании указанных данных и выбирается минимально возможный байтовый размер, -который позволяет сохранить все значения без потери точности.

    -

    Примеры:

    -
        $var_char := 123; # Тип Char выводится автоматически
    -    $var_short := 1000; # Тип Short выводится автоматически
    -    $var_bool := [0, 1, 0, 1,]; # Тензор из 4 элементов. Тип Bool выводится автоматически
    -    $tensor[10,10]:Int := 1; # Тензор Int размером 2x2 инициализированный 1
    -    $scalar := $tensor[5,5]; # Присвоить скаляру значение указанного элемента тензора
    -

    Строковые типы данных:

    -

    Поддерживаются два типа строк, StrWide - символьные (широкие) и StrChar — байтовые. Различия между ними заключается в типе единичного элемента. -У символьных строк единичным элементом является широкий символ wchar_t, а у байтовой строки единичным элементом является один байт (точнее char, т. е. байт со знаком). -Символьные строки литералы в исходном тексте записывается в «двойных кавычках», а байтовые строки в ‘одинарных кавычках’.

    -

    Количество элементов символьной строки возвращается в широких символах, а размер байтовой строки в байтах, поэтому и обращение к элементу строки по индексу происходит соответственно либо к символу, либо к байту.

    -

    Важный момент. К любой переменной можно обратиться так же, как к функции (записав после её имени круглые скобки). -Результатом этой операции будет создание копии/клона объекта. Причем некоторые типы (словари, классы и символьные строки) можно использовать в качестве шаблона -при создании копии объекта с модифицированными свойствами, если новые и/или изменяемые значения указать в скобках, как аргументы при вызовах функций. -Так, если при создании копии в скобках указать набор новых данных, то результирующая копия будет содержать уже измененные данные.

    -

    Например:

    -
    $template := "${name} $1"; # Обычная строка
    -$result := $template("шаблон", name = "Строка"); # result = "Строка шаблон"
    -

    Составные типы данных:

    -

    Словарь

    -

    Словарь — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии -(он похож и на tuple и на структуру одновременно). Словари от тензоров отличаются тем, что являются только одномерными массивами, -но каждый элемент может содержать произвольное количество элементов любого типа, в том числе и другие словари.

    -

    Доступ к элементам словарей происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. -Индекс также начинается с 0 и как у тензоров, тоже может быть отрицательным.

    -

    Литерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, -т.е. (,) - пустой словарь, (1, 2= «2», name=3,).

    -

    Перечисление

    -

    Перечисление - это не отдельный тип данных, а обычный словарь, у которого все элементы имеют уникальные имена и целочисленные значение, -которое явно указывается при определении или вычисляется автоматически (на единицу больше предыдущего элемента). -У перечислений тип значения указывается сразу после закрывающей скобки через двоеточие (ONE=1, TWO=, THREE=): Int.

    -

    Классы

    -

    Класс (реализовано частично) - тип данных, с помощью которого реализуется один из принципов ООП - наследование. -При создании экземпляра класса создается новая переменная, у которой сохраняется информацию о своем родителе -и которая наследует от него свойства и методы. Тип данных «класс» аналогичен словарю, -но все свойства обязаны иметь имена (хотя доступ к свойствам класса по индексу так же возможен). -Литерал с типом «Класс» в тексте программы записывается в круглых скобках без завершающей запятой, т. е. () - пустой класс, (1, 2= «2», name=3).

    -

    Пока остальные детали классов до конца не реализованы, поэтому описывать их не буду, т. к. в итоговом варианте синтаксис классов и определения их методов могут поменяться.

    -

    Функции

    -

    Синтаксис NewLang поддерживать несколько типов функций (а в будущем и методов классов): обычные функции, чистые функции и простые чистые функции.

    -

    Для всех типов функций поддерживаются аргументы по умолчанию. При создании функции, её аргументы указываются как в Питоне, -т.е. вначале идут обязательные аргументы, потом аргументы со значениями по умолчанию, -где имя аргумента отделяется от его значения по умолчанию знаком равно «=». -Если функция допускает обработку произвольного количества аргументов, то последним в списке параметров указывается многоточие.

    -

    Обычная функция

    -

    Обычная функция — такие функции являются именно обычными функциями в понимании С/С++. -Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д.

    -

    Внутри обычной функции можно обращаться к локальным и глобальным объектам, и они могут содержаться вставки на языке реализации, например, для вызова функций из внешних библиотек.

    -

    Вставки на языке реализации оформляются в виде %{ %} и могут содержать любой текст на С/С++, -а прямо из него можно обращаться к локальным и глобальным объектам NewLang так же, как и в обычном синтаксисе, -указывая первым символом имени соответствующий модификатор ($ для локальных объектов и @ для глобальных).

    -

    Технически, такая программная вставка просто переносится трансплайтером непосредственно в исходный текст генерируемого файла, -а все идентификаторы NewLang специальным образом декорируются (добавляются специальные маркеры для их идентификации), -после этого исходный текст подается на вход обычному компилятору С++. -Для локальных объектов трансплайтер может генерировать код для прямого доступа к объекту на этапе компиляции, -а для работы с глобальными объектами вынужден использовать runtime вызовы функции поиска в таблице символов.

    -

    Например:

    -
    print(str) := { 
    -    %{ 
    -        printf("%s", static_cast<const char *>($str)); /* Прямой вызов С функции */ 
    -    %} 
    -};
    -

    Чистые функции

    -

    Чистая функция - это тоже обычная функция, только в том смысле, какой в него вкладывает функциональное программирование. -Создания чистой функции происходит с помощью оператора «:-». У чистой функции отсутствует доступ к контексту и глобальным объектам, -поэтому она может обрабатывать только те данные, которые были ей переданы в качестве аргументов.

    -

    Программные вставки на языке реализации внутри чистых функций не запрещены и могут использоваться, например, для отладки. -Но делается это на страх и риск разработчика. Именно он отвечает за их «чистоту», например при вызове функций из внешних библиотек.

    -
        Sum(arg1, arg2) :- {$arg1+$arg2;}; # Вернуть сумму аргументов
    -

    Так как в языке отсутствует оператор возврата данных из текущего блока выполнения (аналог оператора return <данные>), -то возвращаемым значением функции / блока кода всегда является результат выполнения последней операции.

    -

    Простые чистые функции

    -

    Простые чистые функции — отдельный класс чистых функций, которые предназначены только для вычисления логического результата -(т.е. они являются предикатами) и их отличает упрощенная формой записи. -Тело простой чистой функции состоит из последовательности операторов, которые разделяются запятыми и заканчиваются, -как и любое выражение, точкой с запятой. Все операторы простой чистой функции всегда приводятся к булевому значению, -а итоговый результат функции вычисляется по одной из возможных логических операций: И, ИЛИ и исключающее ИЛИ.

    -

    Например:

    -
        func_and(arg1, arg2) &&= arg1==3, arg2 > 0;  # Простая чистая функция Логическое И
    -    func_or(arg1, arg2) ||= arg1==3, arg2 > 0; # Простая чистая функция Логическое ИЛИ
    -    func_xor(arg1, arg2) ^^= arg1==3, arg2 > 0;  # Простая чистая функция Исключающее ИЛИ
    -

    Специальные типы данных:

    -

    None

    -

    None (пустой тип) — не содержит значения (точнее имеет одно значение None) и совместим с любым другим типом данных. -Указывается в тексте программы как один подчерк «_». Значение None имеют не инициализированные переменные -и при попытке чтения из такой переменной возникает ошибка.

    -

    Тип переменной может быть явно указан или выведен автоматически из присваиваемого значения. -Присвоить новое значение уже инициализированной переменной можно только для совместимого типа, так как неявное преобразование типов не допускаются.

    -
        $var := _; # Создать переменную со значением None
    -    $var2 := var; # Ошибка!!! Нельзя прочитать неинициализированную переменную var
    -    $var = 1000; # У переменной будет тип Short (минимальный размер для хранения значения)
    -    $var = 0,5; # Ошибка!!! Short ← Float не совместимы
    -    $var = _; # Очистить значение переменной
    -    $var = 0,5; # Теперь можно, т. к. None совместим с любым типом
    -

    Диапазон (Range)

    -

    Диапазон (реализовано частично) — специальный тип данных, являющейся приблизительным аналогом типа «генератор» в Python. -К диапазону можно обращаться как к итератору и он будет поочередно выдавать элементы в указанном интервале с заданным шагом. -Диапазон в тексте программы указывается как два или три элемента через две точки, например 1..5 — диапазон от единицы до пяти с шагом по умолчанию 1. -В качестве параметров диапазона можно указывать не только литералы, но и имена переменных. -Например, 0,1..$stop..0,1 — диапазон от значения 0,1 до значения, указанного в переменной $stop с шагом 0,1.

    -

    Диапазон для целых чисел можно использовать в качестве индекса у тензоров (точнее, у любых объектов, которые допускают доступ к своим элементам по индексу, -т.е. тензоры, словари и текстовые строки). Фактический, это поведение аналогично slice в языке Python и array[1:5] -в Python означает тоже самое, что и array[1..5] в NewLang.

    -

    В качестве индекса у тензоров еще можно указать произвольное количество измерений с помощью многоточия, т.е.

    -
        $tensor[…, 0] = 0; # Обнулить все первые элементы в каждом измерении.
    -

    Итераторы

    -

    Итераторы (в разработке) - самый сложный и неоднозначный тип данных для работы с элементами коллекций.
    -Для работы с итераторами зарезервированы символы “!” и “?”, но сами итераторы пока не реализованы.

    -

    Преобразование типов

    -

    Явное приведение типов

    -

    Несмотря на динамическую типизацию языка, если тип переменной указан явно, то автоматическое приведение типов не выполняется, -и чтобы присвоить переменой значение не совместимого типа, требуется явное преобразование.

    -

    Так как символьные названия типов относятся к деталям реализации, то явное преобразование в конкретный тип данных производится с помощью вызова функции с системным именем, -т. е. Bool(), StrWide(), Long и т. д. Причем у тензоров при таком преобразовании изменяется только тип данных, но размерность тензора не меняется.

    -

    Для преобразования любого типа данных в строку ещё можно использовать оператор конкатенации строк, которой преобразует любой тип данных в строковое представление. -Но так как строковых типов два (байтовые и широкие строки), то тип строки определяется первым аргументом в операторе конкатенации, т. е.

    -
        "" ++ 123 # "123" - Строка широких символов
    -    '' ++ 123 # '123' - Байтовая строка
    -
    Или преобразовать любое значение в строковое с помощью строки-шаблона:
    -
    -
        val := 12345;
    -    "$1"(val) # Будет строка "12345"
    -

    Tensor comprehensions

    -

    В эпоху машинного обучения тензоры являются основным элементом вычислений, поэтому для конвертирования данных в тензоры используется отдельная синтаксическая конструкция, -состоящая из двойных квадратных скобок [[ данные ]]. Фактически это оператор и функция времени выполнения в зависимости от указанных между двойные квадратными скобками выражения.

    -

    Чтобы преобразовать любую переменную в тензор (с учетом допустимости такого преобразования), её достаточно указать между двойными квадратными скобками. -Выражение [[ varibale ]] - преобразует переменную varibale в одномерный тензор с автоматическим выводом типа данных. -Для преобразования в одномерный тензор конкретного типа используется выражение [[ varibale ]]:Type, где _Type- - любой из арифметических типов.

    -

    Если требуется преобразовать переменную не в одномерный тензор, а в тензор конкретного типа и заданной размерности, -то это делается выражением [[ varibale ]]:Type[2,2], которая вернет тензор с размерностью 2х2 и типом Type у элементов.

    -

    Внутри двойных квадратных скобок может быть не только любое выражение, но и литерал или диапазон. -В этом случае, они также раскрываются в тензор по таким же правилам.
    -В будущем планирую добавить возможность указания сразу нескольких значений через запятую для их объединения в один тензор.

    -

    Примеры:

    -
    >[[(1,2,3)]]  # Тензор из словаря
    -[1, 2, 3,]:Char
    -
    ->[['first second']]  # Байтовая строка в тензор
    -[102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char
    -
    -> [[(first='first', space=32, second='second')]]  # Получаем тензор из словаря с такими же данными
    -[102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char
    -
    ->[[ 0 ... ]]:Double[10,2]   # Тензор заданного формата с нулями
    -[
    -  [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,],
    -]:Double
    -
    ->[[ rand() ... ]]: Int[3,2]  # Тензор со случайными данными
    -[
    -  [1804289383, 846930886,], [1681692777, 1714636915,], [1957747793, 424238335,],
    -]:Int
    -
    ->[[ 0..10 ]]: Int[5,2]  # Тензор из диапзона
    -[
    -  [0, 1,], [2, 3,], [4, 5,], [6, 7,], [8, 9,],
    -]:Int
    -
    ->[[ 0..0.99..0.1 ]]  # Или даже так
    -[0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,]:Double</source>
    -

    Операторы и управляющие конструкции

    -

    Операторы:

    -

    Все операторы имеют парный оператор с присвоением значения.

    -
      -
    • + и += сложение арифметических типов данных
    • -
    • -
        -
      • и -= вычитание арифметических типов данных
      • -
      -
    • -
    • / и /= деление (результат число с плавающей точкой)
    • -
    • // и //= целочисленное деление с округлением к меньшему числу (как в Python)
    • -
    • -
        -
      • и *= умножение
      • -
      -
    • -
    • ** и **= возведение в степень (он же используется и для повторения текстовых строк)
    • -
    • ++ и ++= конкатенация строк с автоматическим приведением аргументов к стоковому типу (символ инкремента специально используется вместо одиночного плюса для того, чтобы в явном виде разделить конкатенацию строк и операторы арифметического сложения)
    • -
    -

    Операторы сравнения:

    -
      -
    • <, >, <=, >= классические для сравнения скаляров
    • -
    • ==, != операторы сравнения с автоматическим приведением совместимых типов для любых объектов
    • -
    • ===, !== оператор точного сравнения для любых объектов (автоматического приведения типов не выполняется)s
    • -
    -

    Проверки типов (в разработке):

    -

    Проверка имени класса «~» - немного похож на оператор instanceof в Java. -Левым оператором должен быть проверяемый объект, а правым оператором - название типа, строка литерал или объект строкового типа с именем класса. -Результатом операции будет истина, если правый операнд содержит название класса проверяемого объекта или он присутствует в иерархии наследования у проверяемого класса.

    -
        name := "class"; # Строка с именем класса
    -    var ~ :class; 
    -    var ~ "class";
    -    var ~ name; 
    -
    -    (field1=«value», field2=2, field3=«33»,) ~~ (); # Истина (т. е. левый операнд словарь)
    -    (field1=«value», field2=2, field3=«33»,) ~~ (field1=_); # Тоже истина (т. к. поле field1 присутствует у левого операнда)
    -

    Утиная типизация «~~» - приблизительный аналог функции isinstance() в Python, который для простых типов сравнивает совместимость типа левого операнда по отношению к правому, а для словарей и классов в левом операнде проверяется наличие всех имен полей, присутствующих у правого операнда. т. е.

    -
        (field1=«value», field2=2, field3=«33»,) ~~ (); # Истина (т. е. левый операнд словарь)
    -    (field1=«value», field2=2, field3=«33»,) ~~ (field1=_); # Тоже истина (т. к. поле field1 присутствует у левого операнда)
    -

    Строгая утиная типизация «~~~» - для простых типов сравнивается идентичности типов без учета совместимости, -а для составных типов происходит строгое сравнение всех свойств. Для данной операции, пустой тип совместим только с другим пустим типом!

    -

    Управляющие конструкции (в разработке)

    -

    Условный оператор

    -

    В качестве оператора проверки условия используется синтаксическая конструкция, соответствующая по смыслу термину «следует», -т.е. тире и угловая скобка «->». Такая запись условного оператора очень похожа на математическую и легко объединяется в последовательности для проверки множественных условий вида «else if».

    -

    В общем случае условный оператор имеет вид:

    -
        условие -> действие;
    -    или  
    -    (условие) -> {действие};
    -    или  
    -    (условие1 || условие2) -> {действие} -> {действие иначе};
    -

    Или расширенный вариант «else if», для наглядности записанный с отступами:

    -
        (условие1) -> {действие1}
    -        (условие2) -> {действие2}
    -        (условие3) -> {действие3}
    -        -> {действие_иначе};
    -

    Операторы циклов (в планах)

    -

    Операторы циклов пока в разработке , т. к. плотно связаны с итераторами.

    -

    Пока планирую для циклов использовать конструкции: (условие) <–> {тело цикла};

    -

    Или так: (условие) {тело цикла};

    -

    И хотя синтаксис мне не очень нравится, но я решил пока не ломать над этим голову и планирую попробовать несколько вариантов оформления циклов.

    -

    Операторы прерывания потока выполнения команд (реализовано частично)

    -

    Оператором прерывания потока выполнения команд и возврата из текущей функции, т.е. самым близким аналогом оператора return
    -является оператор два символа минус «–». Но в отличие от классического return, оператор возврата не возвращает значения, -т.к. значение из любой функции или блока кода возвращается всегда и им является результат выполнения самой последней операции -(или None, если такая операция отсутствует).

    -

    Пока не придумал, как оформлять оператор прерывания потока выполнения в случае ошибки (при его выполнении будет происходить генерация исключения), -поэтому, если будут предложения, пишите в комментариях к статье (и про оформление циклов тоже).

    -

    Обработка ошибок (в планах)

    -

    В самом начале работ я ориентировался на классический вариант обработки исключений, -который в обычных языках программирования обычно оформляется ключевыми словами try .. catch .. finally с различными вариациями. -Но в условиях жестких ограничений на синтаксис языка, и невозможности использовать ключевые слова, -комбинировать символы для указания разных типов блоков при обработке исключений, было бы крайне сомнительной затеей. -Ведь основная цель разработки NewLang — простота и понятность кода, а тут с самого начала могут появиться комбинации скобочек, стрелочек, -палочек и других подобных символов.

    -

    И тут в голову пришла очень простая мысль. А ненужно повторять логику обработки ошибок из классических языков программирования! -Ведь основная цель подобных синтаксических конструкций - выделить участок кода где возможно возникновение ошибки, -перехватить и обработать правильный тип исключения. -Ведь классические языки программирования изначально были жестко привязаны к машинному представлению данных в оперативной памяти компьютера -и тип данных для них играл принципиально важное значение. -Но это не является ограничением для языков с динамической типизацией!

    -

    Поэтому, подход к обработке исключений планируется следующий: Программный код, который может привести к ошибке, заключается в двойные фигурные скобки -{{ любой код или вызов одиночной функции }}, -а результат выполнения такого блока кода присваивается переменной. После этого анализируется возвращенное значение и тип исключения может обрабатываться обычным условным оператором.

    -

    Наверно, это проще показать на примере:

    -
        $error := {{ # начало блока try
    -        call_or_exception1(); 
    -        call_or_exception2(); 
    -    }}; # конец блока try
    -    # Обычные условные операторы вместо типизированных блоков catch
    -    ($error ~ :type1)->{ код обработки ошибки 1}
    -    ($error ~ :type2)->{ код обработки ошибки 2};
    -

    Самое удивительное, что при таком подходе значительно упрощается и семантика блоков try finally, которые вообще становятся не нужны.

    -

    Исходный код на Java:

    -
        try {
    -        try {
    -            throw new Exception("a");
    -        } finally {
    -            throw new IOException("b");
    -        }
    -    } catch (IOException ex) {
    -        System.err.println(ex.getMessage());
    -    } catch (Exception ex) {
    -        System.err.println(ex.getMessage());
    -    }
    -

    Эквивалентный ему на NewLang:

    -
    $catch := {{  
    -    $finally := {{  
    -	Error1("1");  
    -    }};
    -    Error2("2"); 	# Строка выполнится даже при возникновении исключении Error1
    -    $finally;		# Error1 вернется, если не будет Error2
    -}}
    -($catch ~ :Error1) -> printf(«%s», $catch)
    -($catch ~ :Error2) -> printf(«%s», $catch);
    -

    Как все это попробовать?

    -

    Сейчас сборка проекта реализована только под Linux и если кроме текстового описания захочется в живую поэкспериментировать на своей машине, то придется собрать интерпретатор из исходников самостоятельно.

    -

    Так как текущий вариант предназначен первую очередь для отработки концепции, то часть из описанных возможностей пока не реализована (алгоритмические конструкции, наследование классов, итераторы, некоторые операции и т. д).

    -

    Но можно поиграться с созданием переменных, вызовом функций и выполнением арифметических операций над данными, чтобы оценить синтаксис, основанный на правилах, и может быть, предложить свои собственные мысли и доработки для его улучшения.

    -

    Сборка REPL из исходников (пока только под Linux)

    -

    Подготовка репозитория

    -
      -
    • Скачать исходники
    • -
    • Скачать и развернуть архив libtorch в каталоге contrib (PyTorch Build: Stable (1.10.*) -> Your OS: Linux -> Package: LibTorch -> Language: C++ / Java -> Compute Platform: CPU -> Download here (cxx11 ABI): libtorch-cxx11-abi-shared-with-deps-1.10.2+cpu.zip)
    • -
    • Активировать и скачать исходники субмодулей (git submodule init && git submodule update)
    • -
    • В каталоге contrib запустить файл build.sh для сборки библиотеки libffi
    • -
    • В каталоге core запустить файл compile_syntax.sh для генерации файлов парсера и лексического анализатора. Может потребоваться установка утилит flex и bison. Если что, у меня установлены flex 2.6.4 и bison (GNU Bison) 3.7.4
    • -
    -

    Собрать

    -
      -
    • Юнит-тесты (newlang_test): в каталоге core выполнить команду make CONF=UnitTest
    • -
    • Интерпретатор (nlc): в каталоге core выполнить команду make CONF=Debug
    • -
    -

    Утилита nlc (NewLangCompiler)

    -

    В текущее время nlc поддерживать работу только в режиме интерпретатора (несмотря на название). -Для тестирования и простой проверки компилятор не нужен, хотя на первых порах я делал именно его. -Но трудоемкость работ по постоянной переделке под новый синтаксис оказалась очень высокой, поэтому на время первичной отладки языковых конструкций было принято волевое решение ограничиться интерпретатором, -как более простым и быстрым способом проверки различных гипотез, а разработку настоящего компилятора (в виде трансплайтера на язык С++), -отложить до окончательной проработки синтаксиса.

    -

    Планы на будущее

    -

    Естественное, одна статья и несколько маленьких примеров не дают исчерпывающей информации о возможностях языка. -Да и сами возможности пока не раскрыты в полной мере. -Ведь текущая версия, это скорее тестовая платформа для проверки декларируемых концепций и основного синтаксиса.

    -

    Пока остаются не реализованными некоторые из заявленных возможностей и очень важных хотелок. -Но протестировать основной подход можно уже сейчас, и я буду благодарен за любую обратную связь и предложения.

    -

    Если говорить о планах (естественно, в будущих версиях что-то может добавиться или измениться порядок их реализации), но в настоящий момент роадмап развития NewLang мне видится следующим образом:

    -
      -
    • Доделать стандартные управляющие конструкции, обработку ошибок и итераторы.
    • -
    • Доработать систему типов с учетом множественного наследования классов.
    • -
    • Реализовать длинную арифметику и дроби.
    • -
    • Сделать какую нибудь логическую игру (крестики нолики, судоку или что-то похожее) с алгоритмическим выбором следующего хода и его вычислением с помощью машинного обучения.
    • -
    • Написать много разных примеров для оценки синтаксиса.
    • -
    • Доработать синтаксис с учетом полученного опыта и обратной связи.
    • -
    • Восстановить работоспособность компилятора для генерации исполняемых файлов.
    • -
    • Сделать очередную большую чистку кода.
    • -
    • Переработать и задокументировать получившуюся семантику языка с учетом всех возможностей и выпустить первую полнофункциональную версию NewLang.
    • -
    -

    Ссылка на первую публикаци

    - -
    - - - - - - - - - - - - - - - - -
    -

    Можно ли использовать декларативный и императивный стили написания программ одновременно?

    - - -

    КДПВ

    - - -
    -

    Внимание!!!

    -

    Данная статья содержит описание синтаксиса NewLnag предыдущей версии.

    -

    Актуальную версию синтаксиса языка можно посмотреть тут.

    - -
    - -

    При разработке своего собственного языка программирования автор должен определиться, какими свойствами его язык должен обладать, -ведь в конечном итоге именно это и будет определять назначение языка и особенности его использования. -Причем некоторые свойства настолько сильно влияют на итоговую концепцию языка и его синтаксис, -что впоследствии их изменение невозможно в принципе, либо новый синтаксис получается очень запутанным и непонятным. -Наверно из-за этого многие свойства языков программирования рассматриваются и изучаются как взаимоисключающие.

    -

    До недавнего времени я считал, что императивная и декларативная парадигмы написания программ являются антагонистами и взаимоисключающими понятиями. -Ведь выбор стиля написания кода, изначально определяется автором языка еще на стадии его проектирования и оказывает влияние на все последующие аспекты.

    -

    Но сейчас я думаю, что это не верно. Императивный и декларативный стили программирования не являются взаимоисключающими, -а писать программы только в одной из указанных парадигм подталкивают правила синтаксиса, реализованные в языке!

    -

    Другими словами, использовать только императивную или только декларативную парадигмы разработчик вынужден не потому, что он не умеет или не хочет писать код по другому, а из-за того, -что все более-менее мейнстримные языки программирования ориентированы на использование только одной парадигмы. -И выбор только одной парадигмы написания кода, это ограничение, которое навязано программистам создателями языка. -Ведь если они изначально ориентировались только на одну концепцию разработки кода, то и разрабатывали синтаксис языка в соответствии с этой парадигмой.

    -

    Данная статья — размышление о совместимости декларативной и императивной парадигм программирования и возможности их одновременного использования в рамках одного языка программирования одновременно.

    -

    Что такое “Декларативное программирование”?

    -

    Вначале мне захотелось разобраться, а существуют ли чисто декларативные языки программирования? -Такие, которые могут полностью обходятся без императивных конструкций?

    -

    Но чуть не споткнулся уже в самом начале, т.к. даже само определение «декларативное программировании», в вики описывается следующим образом:

    -
    -

    Декларати́вное программи́рование — парадигма программирования, в которой задаётся спецификация решения задачи, то есть описывается, что представляет собой проблема и ожидаемый результат. Противоположностью декларативного является императивное программирование, описывающее на том или ином уровне детализации, как решить задачу и представить результат.

    -
    -

    Уже в изначальном определении закладывается противопоставление парадигм, а дальше идут рассуждения о «направлении» программирования. -И хоть вики сама и не является авторитетным источником информации, но даже такая заготовка статьи смогла показать направление поиска ответов на первый поставленный вопрос.

    -

    И заставил задуматься один абзац в конце статьи следующего содержания:

    -
    -

    «Чисто декларативные» компьютерные языки зачастую неполны по Тьюрингу — так как теоретически не всегда возможно порождение исполняемого кода по декларативному описанию. -Это иногда приводит к спорам о корректности термина «декларативное программирование» (менее спорным является «декларативное описание решения» или, что то же самое, «декларативное описание задачи»).

    -
    -

    Судя по наличию такой оговорки, ставится под сомнение наличие «чисто декларативных» языков. -И как только пришлось задуматься над это мыслью, то сразу стало очевидным, что какой бы декларативный язык программирования не существовал, -то в нем должна быть как минимум одна императивная конструкция, которая будет запускать поиск решения! -Ведь любой синоним слова «выполнить» или «запустить» по определению будет императивом!

    -

    Например в языке Prolog, который обычно и приводят в качестве примера декларативного языка программирования, “замаскированным” императивным оператором является знак вопроса. -Он кажется естественным и логичным, как же без него? Но по своей сути, это императивная конструкция!

    -

    Тоже самое касается и языка SQL. Он тоже как бы декларативный, но неожиданно все его команды являются императивными по сути. SELECT, CREATE, ALTER, DROP, INSERT, UPDATE, DELETE и т. д., а декларативными являются только описания условий их выполнения!

    -

    В результате, у меня так и не получилось найти чисто-декларативный язык программирования без императивных операторов (может быть, Вики права и такого языка программирования и вовсе не существует?).

    -

    А что отличает декларативные языки программирования от императивных?

    -

    Согласно определению, декларативными языками программирования их называют из-за возможности записать некие условия в декларативном стиле. -Но кроме этого, в декларативных языках как правило присутствует и некий внутренний механизм поиска решений. -Подобный “вычислитель” есть и в SQL и Prolog и во многих других декларативных языках.

    -

    Интересно, а является ли внутренняя система поиска решений обязательным признаком декларативного стиля программирования или это только особенность конкретного языка программирования, которая не зависит от декларативного стиля написания кода?

    -

    Чтобы проверить данные предположения, можно было попробовать написать классическую декларативную программу на императивном языке, у которого отсутствует внутренний механизм поиска решений.

    -

    А заодно, таким образом можно будет и изучить вопрос, получится ли написать программу в декларативном стиле используя обычный императивный язык программирования?

    -

    Для примера, решил попробовать повторить уже классическую программу в декларативном стиле на Прологе.

    -
        parent("Tom","Jake").
    -    parent("Janna","Jake").
    -    parent("Tom","Tim").
    -    male("Tom").
    -    male("Tim").
    -    male("Jake").
    -    female("Janna").
    -
    -    brother(X,Y):-parent(Z,X),parent(Z,Y),male(X),male(Y),X\=Y.
    -    ? brother
    -

    Получилась вот такая функционально - эквивалентная программа на С++, которая максимально приближена по стилю к декларативному прототипу:

    -
        enum sex_ {
    -        male,
    -        female
    -    };
    -
    -    struct human;
    -    typedef std::vector<human *> parent_;
    -
    -    struct human {
    -        const char *name;
    -        sex_ sex;
    -        parent_ parent;
    -    };
    -
    -    human Tom{"Tom", male,{}};
    -    human Janna{"Janna", female,{}};
    -    human Jake{"Jake", male,{&Tom, &Janna}};
    -    human Tim{"Tim", male,{&Tom}};
    -
    -    std::vector<human *> humans{&Tom, &Janna, &Jake, &Tim};
    -
    -
    -    auto brothers = [](human * a, human * b) {
    -
    -        auto intersec = [](parent_ &a, parent_ & b) {
    -            for (auto elem_a : a) {
    -                for (auto elem_b : b) {
    -                    if(elem_a && elem_b && elem_a == elem_b) {
    -                        return true;
    -                    }
    -                }
    -            }
    -            return false;
    -        };
    -
    -        return a && b && a != b && a->sex == male && b->sex == male && (intersec(a->parent, b->parent));
    -    };
    -
    -    for (auto a : humans) {
    -        for (auto b : humans) {
    -            if(brothers(a, b)) {
    -                std::cout << a->name << " and " << b->name << "\n";
    -            }
    -        }
    -    }
    -

    Конечно, текст на С++ получается значительно многословней, чем вариант на Прологе, но по сути, это почти дословное повторение декларативного стиля написания кода. -Тем более, не стоит забывать про рассуждения в начале статьи об изначальном выборе концепции при создании языка -и “принуждении” программистов пользоваться только одной, изначально выбранной парадигмой разработки.

    -

    Таким образом, можно с высокой долей уверенности утверждать, что теоретически можно писать код одновременно в разных стилях.

    -

    Но что тогда мешает в рамках одного языка программирования писать с использованием императивного и декларативного стиля? -Неужели только убежденность создателей языков в том, что императивный и декларативный стили программирования являются взаимоисключающими? -И только из-за этого получаются языки программирования, синтаксис которых подходит для использования одной единственной парадигмы?

    -

    Но если это так, то что мешает попробовать разработать синтаксис языка программирования, в котором можно было бы использовать сразу императивный и декларативный стили программирования одновременно?

    -

    Что мешает совместить императивный и декларативный стили написания в рамках одной программы?

    -

    В любой компьютерной программе всегда существует разделение кода на описание данных и на языковые конструкции для их обработки, т.е. фактически это разделение на данные и на функции. -Мне кажется, что основная сложность, которая не дает использовать разные стили программирования в рамках одного языка, это необходимость разделять описываемые сущности на «данные» и «управляющие конструкции». -Ведь это свойство (необходимость разделения сущностей на “данные” и “функции”), является неотъемлемой частью любого языка программирования.

    -

    Это не удивительно, ведь на заре становления ИТ индустрии, создатели первых языков программирования ориентировались исключительно на императивный стиль, потому что назначением любого компилятора было - преобразовать исходный текст программы в машинные инструкции. И на примерах модульного, структурного и объекто-ориентированного подходах показана и доказана необходимость оформления исполняемого кода в выделенные процедуры с последующей их группировкой в модули и классы.

    -

    А декларативный стиль написания программ стал появляться только после создания высокоуровневых языков программирования. -И основная цель создания данных языков сместилась на поиск решения конечного пользователя, а не на упрощение генерации бинарных файлов с машинными инструкциями. -Если внимательно посмотреть на приведенные выше примеры кода, то можно заметить, что в них определения данных и операторы для их обработки идут вперемешку, (для примера на С++ это определение лямбд функции), что кардинально отличается от императивного подхода.

    -

    Так может быть, основная особенность декларативного стиля как раз и заключается в том, что в нем не разделяются «данные» и «действия над данными»? -Или как вариант, можно не указывать выполняемые действия над данными вовсе (как в некоторых SQL конструкциях)?

    -

    Может быть как раз именно эта особенность (возможность последовательной записи программного кода в соответствии с собственными логическими рассуждениями, -в которых могут перемежаться «данные» и «функции», как это происходит при человеческом мыслительном процессе), -не дает в полной мере реализовать возможность совмещения императивных и декларативных стилей программирования?

    -

    И если это так, тогда можно попробовать разработать такой синтаксис, который будет поддерживать определение как данных, так и декларацию функций в рамках единого потока языковых конструкций!

    -

    Проверка гипотезы в новом языке программирования

    -

    Для поверки данного предположения, я решил добавить в свой новый язык программирования -(синтаксис которого допускает определение функций в одном потоке с описанием обрабатываемых данных), недостающие алгоритмические конструкции, которые позволяли бы реализовать императивный стиль программирования, -несмотря на изначальную ориентацию только на декларативную парадигму.

    -

    Правда с учетом изначальных ограничений синтаксиса нового языка (запрет на применение операторов в виде зарезервированных ключевых слов), -в качестве оператора проверки условия была выбрана синтаксическая конструкция, соответствующая по смыслу термину «следует», -т.е. тире и угловая скобка «->».

    -

    В результате, условный оператор получился практически математический, который легко объединяется в последовательности для реализации проверки множественных условий вида «else if». -А для объединения сразу нескольких логического операторов между собой и для отделения их от последующего действия, операторы проверки условия можно заключать в круглые скобки.

    -

    В общем случае условный оператор в новом языке программирования имеет вид:

    -
        условие -> действие;
    -    или  
    -    (условие) -> {действие};
    -    или  
    -    (условие1 || условие2) -> {действие} -> {действие иначе};
    -

    Или расширенный вариант, для наглядности записанный с отступами:

    -
        (условие1) -> {действие1}
    -    (условие2) -> {действие2}
    -    (условие3) -> {действие3}
    -    -> {действие_иначе};
    -

    Тогда и операторы циклов можно будет записать практически аналогично, только выбрав в качестве оператора, не оператор следования, -а следование с возвратом (раз уж нужно указывать циклическое действие).

    -

    Цикл пока:

    -
        (условие) <-> {тело цикла};
    -

    счетный цикл для работы с итератором:

    -
        (счетчик_или_данные!)? <-> {тело цикла};
    -

    В этом случае, решение тестового примера декларативной программы на Прологе можно будет легко оформить, как в императивном, так и в декларативном стилях одновременно!

    -
        м := "муж.";
    -    ж := "жен.";
    -    human @= term(пол=, parent=[,]);
    -    Tom @= human(пол=м);
    -    Janna @= human(пол=ж);
    -    Jake @= human(м, [&Tom, &Janna,]);
    -    Tim @= human(пол=м, parent=[&Tom,]);
    -
    -
    -    brother(h1, h2) &&= $h1!=$h2, $h1.пол==м, $h2.пол==м, $h1.parent & $h2.parent; 
    -    // Оператор «&» побитовое «И» для чисел или операция пересечения для множеств
    -
    -
    -    // Запись алгоритма поиска решения в императивном стиле 
    -    (h1=human!, h2=human!)? <-> {
    -        (brother(h1, h2)) -> {
    -            @print($h1, $h2, «\n»);
    -        }
    -    };
    -
    -    // Краткая запись алгоритма поиска решения в императивном стиле 
    -    (h1=human!, h2=human!)? <-> 
    -        brother($h1, $h2) -> @print($h1, $h2, «\n»);
    -
    -    // Запись поиска решения в декларативном стиле
    -    brother(human!, human!)?;
    -

    Примерно это и требовалось показать!

    -

    З.Ы.

    -

    Я почти закончил эксперименты с синтаксисом языка. -И теперь, после добавления в него недостающих алгоритмический конструкций (ветвления и циклов), планирую, -что следующая статья о новом языке программирования будет посвящена описанию его полного синтаксиса и публикации исходников прототипа компилятора для возможности поиграться на реальных примерах.

    -

    З.З.Ы

    -

    В комментариях @gbg привел очень простой ответ на один из поднятых вопросов. -Причем в более элегантном виде и без написания кода!

    -
    -

    Ну и пять копеечек про ООП. Как ни странно:

    -
      -
    1. В нем таки есть декларативная часть, все эти pubic, private, virtual, etc
    2. -
    3. Эта декларативная часть, внезапно, элегантно позволяет реализовывать декомпозицию и управление сложностью.
    4. -
    5. При наличии перегрузок, можно поиграть в алгебраическое мышление, рассматривая взаимодействие двух объектов как бинарную операцию.
    6. -
    -

    Ух ты, ООП - это обкатанная практикой технология, которая совмещает декларатив с императивом и вроде позволяет освоившим ее вкусно кушать и мягко спать!

    -
    -

    Ссылка на первую публикаци

    - -
    - - - - - - - - - - - - - - - - -
    -

    Необычная концепция синтаксиса языка программирования

    - - -

    КДПВ

    - - -
    -

    Внимание!!!

    -

    Данная статья содержит описание синтаксиса NewLnag предыдущей версии.

    -

    Актуальную версию синтаксиса языка можно посмотреть тут.

    - -
    - -

    Хочу представить на обсуждение читателей немного необычный концепт языка программирования, в котором отсутствует проблема, -присущая практически всем промышленным языкам - постоянное увеличение сложности синтаксиса языка из-за его естественного развития по мере выхода новых версий и добавления новых фич. -Эта проблема описана в статье “Простое сложное программирование” и Какая “идеальная” цель развития у языков программирования?

    -

    После нескольких экспериментов с синтаксисом, хочется проверить выработанную идею на широкой аудитории Хабра, которая как нельзя лучше подходит для этих целей.

    -

    Особенности языка:

    -
      -
    • Низкий порог входа и естественное ограничение уровня сложности в течение длительного времени даже при условии постоянного развития самого языка.
    • -
    • Возможность писать код программы как в декларативной, так и в императивной парадигме с использованием процедурного, модульного и объектно-ориентированного подхода.
    • -
    -

    Ну и в соответствии с собственным наблюдением Хабр — ума палата, буду рад любым комментариям и предложениям, которые помогут протестировать или улучшить предлагаемое решение.

    -

    Введение

    -

    Первой необычной особенностью языка является полное отсутствие зарезервированных ключевых слов. -Точнее, планируется использовать только одно единственное ключевое слово (название языка), которое может быть как главной точкой входа в приложение, -так и способом доступа к настройкам языка под конкретную предметную область, например при необходимости реализации DSL парадигмы.

    -

    В настоящий момент название языка не выбрано, поэтому для примеров используется просто слово lang, которое в будущем будет изменено.

    -

    Данная особенность (отсутствие зарезервированных ключевых слов) реализуется за счет того, грамматика языка основана на использовании общеупотребительных символов и классических знаков препинания, -а все остальные букво-символьные последовательности при парсинге программы рассматриваются как “токены”.

    -

    Компилятор языка реализуется как transpiler - преобразование исходного кода программы, -написанной на одном языке программирования, в эквивалентный исходный код на другом языке. -Первые эксперименты с синтаксисом я начинал на Python, но после осознания необходимости разработки не только интерпретатора, -но и компилятора непосредственно в исполняемый код, решил остановиться на C++. Хотя в принципе, язык реализации может быть любым.

    -

    Использование транспиляции при реализации компилятора решает сразу множество очевидных и не очень задач. -Сразу отпадает необходимость разрабатывать низкоуровневый компилятор в исполняемый процессорный код, -а в моем случае основным бонусом такого подхода становится возможность использования императивной парадигмы программирования за счет вставок кода непосредственно в исходный код приложения на языке реализации.

    -

    И именно этот момент позволяет естественно разделить декларативный и императивный способ написания программы. -В этом случае в декларативной парадигме реализуется только одна из трех базовых управляющих конструкций, -необходимых и достаточных при реализации любого алгоритмаследование.

    -

    Другими словами, в декларативном стиле описывается только последовательность операций, которые следуют одна за другой, -но отсутствует возможность запрограммировать циклы или ветвление (переходы) по условию. -Из-за этого в декларативном стиле можно записать только следующие типы языковых конструкций:

    -
      -
    • комментарий
    • -
    • определение переменной и присвоение ей значения
    • -
    • создание объекта и назначение его свойствам значений по умолчанию
    • -
    • создание функции (метода для всего класса объектов)
    • -
    • вызов функции или итератора
    • -
    • непосредственная вставка кода на языке реализации
    • -
    -

    Так как цель текущей публикации - протестировать общую концепцию, то начну сразу с примеров без длинного описания подробностей, а некоторые нюансы буду комментировать по ходу дела. -Тем более, самая главная цель “низкий порог входа” само собой подразумевает возможность самостоятельно разобраться в синтаксисе. -Тем не менее, совсем без знаний языка реализации не обойтись и начальные знания в программировании на С/С++ все равно необходимы.

    -

    “Привет, мир!” в императивной парадигме

    -

    Определение обычной функции выполняется с помощью оператора присвоения “:=”, а программный код на языке реализации (в данном случае на C++) -заключается в фигурные скобки. Простой пример вывода строки на экран выглядит примерно так:

    -
        print(str="") := { printf("%s", static_cast<char *>($str)); }
    -

    Функция print с аргументом по умолчанию в виде пустой строки внутри себя вызывает обычный printf из стандартной библиотеки.

    -

    Соответственно “Привет, мир!” в императивной парадигме программирования будет выглядеть тривиально:

    -
        #!/bin/lang
    -    print(str="") := { printf("%s", static_cast<char *>($str)); };
    -    @print("Привет, мир!\n");
    -

    Из примера видно, что обращение к аргументам внутри С++ кода происходит с использованием символа $, который указывается вначале именованного аргумента. -Кроме этого, для доступа к аргументам функции можно обращаться по их порядковым номерам начиная с первого ($1, $2, $3 и т. д.). -Зарезервированный аргумент $0 содержит сам объект, метод которого вызывается или nullptr, если функция не принадлежит объекту.

    -

    Обычные функции являются именно обычными функциями в понимании С/С++. -Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д. -Технически, код такой функции парсится на предмет замены использованных аргументов, -специальным образом декорируется её имя и добавляются специальные маркеры для идентификации содержимого. -После этого исходный текст готов для сборки обычным С++ компилятором для превращения в динамическую библиотеку -и после её загрузки функцию можно будет вызвать в любой момент (для вызова функции перед её именем необходимо указать символ "@").

    -

    Непосредственное выполнение файла в режиме интерпретатора происходит в два этапа. На первом этапе из текста программы генерируется временный С++ файл с исходным кодом всех функций, этот файл компилируется gcc и собирается динамическая библиотека.

    -

    На втором этапе, собранная динамическая библиотека загружается средой выполнения, а исходный текст программы начинает последовательно выполнятся интерпретатором (все строки, за исключением определений функций).

    -

    Есть еще вариант, когда вместо интерпретации кода программы, генерируется С++ файл не только для функций, но и для основной части приложения. -Тогда на выходе компилятора будет уже обычный бинарный файл, хотя в том случае оперативно поправить текст программы уже не получится.

    -

    Логическое программирование в декларативной парадигме

    -

    Так как самым известным языком логического программирования в декларативном стиле считается Prolog, -поэтому приведу простой пример программы Brother (поиска братьев) на Прологе и эквивалентный ему код на новом языке.

    -

    Prolog:

    -
        male("Tom").
    -    male("Tim").
    -    male("Jake").
    -    female("Janna").
    -    parent("Tom","Jake").
    -    parent("Janna","Jake").
    -    parent("Tom","Tim").
    -
    -    brother(X,Y):- parent(Z,X),parent(Z,Y),male(X),male(Y),X\=Y.
    -

    Вывод: (Jake, Tim) (Tim, Jake)

    -

    Тот же самый пример:

    -
        #!/bin/lang
    -    human:=@term(sex=,parent=);
    -    Tom:=@human(male);
    -    Janna:=@human(female);
    -    Jake:=@human(male, (Tom, Janna,));
    -    Tim:=@human(sex=male, parent=(Tom,));
    -
    -    human::brother(test=human!) &&= $0!=$test, $0.sex==male, @intersec($0.parent, $test.parent);
    -
    -    human.brother?
    -

    Вывод: [Tim.brother(Jake), Jake.brother(Tim),]

    -

    Надеюсь, что синтаксис интуитивно понятен, особенно при наличии эквивалентного кода на Прологе, но на всякий случай поясню отдельные моменты.

    -
        human:=@term(sex=,parent=);
    -

    В этой строке создается объект с именем “human” и двумя свойствами “sex” и “parent”, -значения которых по умолчанию не определены, а родителем является системный объект “term”. -Использование символа "@" в начале термина обозначает вызов существующей функции с параметрами, указанными в скобках. -В данном случае вызывается конструктор системного объекта “term”, а возвращаемым результатом является новый термин “human”, -который можно воспринимать как один экземпляр класса, так и как имя целого класса, если он будет выступать в качестве родителя для других объектов.

    -
        Tom:=@human(male);
    -    Janna:=@human(female);
    -    Jake:=@human(male, (Tom, Janna,));
    -    Tim:=@human(parent=(Tom,), sex=male);
    -

    Первые две строки создают объекты “Tom” и “Janna”, у которых свойство “sex” установлено в значения “male” и “female” соответственно. -А в последней строке при создании объекта Tim значения свойств задается с указанием их имени.

    -

    Конструкции (Tom, Janna,) и (Tom,), это определение константного литерала с типом словарь, которые присваиваются указанным свойствам.

    -

    Чтобы определение словаря не путать с указанием аргументов при вызове функции, в нем содержится обязательная финальная запятая перед закрывающей скобкой. -Это правило (финальная запятая перед закрывающей скобкой) действует и при определении литерала массива, только для записи которого используются скобки не круглые, а квадратные (например [,] - пустой массив). -Основным отличием словаря от массива, заключаются в способах доступа к их элементам. -Для доступа к элементу массива используется целочисленный индекс, а в словаре может быть использован как индекс, так и имя элемента при его наличии. -Между словарем и массивом есть еще отличия, но сейчас они не принципиальны.

    -

    И предпоследняя строка в примере:

    -

    human::brother(test=human !) &&= $0 != $test, $0.sex==male, @intersec($0.parent, $test.parent);

    -

    это определение простой чистой функции “brother” для всех объектов, производных от “human”. -Данная функция принимает один именованный аргумент “test”, значением по умолчанию которого является итератор объектов класса “human”.

    -

    Оператор &&= означает определение простой чистой функции, т. е. функции без внешних зависимостей, -которая не имеет доступа к глобальному контексту, а результат выполнения которой является логическое значение, -которое вычисляется по схеме логическое И для всех условий, указанных в теле функции через запятую.

    -

    Выполнение и вывод результата выполнения программы происходит в строке -human.brother?

    -

    Восклицательный и вопросительный знаки обозначают итератор. Итератор “!” возвращает один текущий элемент из коллекции и передвигает указатель на следующий, -а итератор “?” возвращает сразу всю коллекцию объектов целиком.

    -

    Другими словами при выполнении строки программы human.brother ? происходит последовательный перебор всей коллекции объектов типа “human”, -где у каждого объекта выполняется функция “brother” с аргументами по умолчанию. -А так как в качестве аргумента по умолчанию указан итератор human !, то в качестве аргумента последовательно предается каждый из элементов указанного класса. -По сути, при выполнении этой строки происходит полный перебор всех возможных комбинаций объектов класса “human” каждый с каждым.

    -
    -

    Более подробное описание работы итератора и причина выбора такого синтаксиса опубликовано в отдельной статье Лаконичный итератор для декларативного синтаксиса

    -
    -

    Результат выполнения будет состоять из тех пар объектов, для которых функция “brother” вернет истину, т.е. результат выполнения будет массив из двух пар объектов [Tim.brother(Jake), Jake.brother(Tim),].

    -

    Формулировка проверяемой концепции

    -

    Тестируемая концепция заключается в следующем. Синтаксис языка программирования состоит как бы из двух частей, -каждая из которых является относительно независимой и в тоже время они связаны между собой.

    -

    Первая часть сложная — предназначена для описания алгоритмов в императивном стиле на обычном языке программирования, -поэтому внутри функций разработчику доступны все возможности языка реализации.

    -

    Вторая часть простая (по сравнению с первой) — предназначена только для логического описания задачи в декларативном стиле. -Именно эта часть используется для начального уровня использования, а естественное ограничение только на последовательное выполнение операторов -(т.е. отсутствие циклов и ветвлений) не доставляет чрезмерных сложностей в понимании исходного текста программы даже в будущем по мере развития языка.

    -

    Связь между двумя вариантами синтаксиса прозрачна и реализуется за счет совместного использования переменных и функций, -декларация и обращение к которым происходит в едином стиле в обоих случаях за счет унификации синтаксиса на уровне использования знаков препинания.

    -

    Сейчас я специально не привожу полного синтаксиса и подробного описания остальных возможностей языка, т.к. компилятор пока не готов для публичной презентации. -Но буду крайне благодарен за любой отклик или дельные предложения в отношении предложенной концепции.

    -

    Особенно это касается возможных конфликтов по синтаксису в представленных примерах.

    - -
    - - - - - - - - - - - - - - - - -
    -

    Простое сложное программирование

    - - -

    КДПВ

    -

    В очередной раз увидел на Хабре статью про сложное дело под названием «программирование». -И то, что программирование действительно является делом не простым воспринимается как факт и обычно не требует какого либо подтверждения.

    -

    Но понятие «сложность» сродни термину «куча». -Для кого-то и пять кокосов это не куча, а кого-то съел один и «больше не хочется» - значит для него и единственного кокоса будет много.

    -

    Так и со сложностью ПО. Вроде бы увеличение сложности является для всех очевидным и наблюдается во всех сферах применения IT технологий, -да и сами языки программирования по мере своего развития становятся все сложнее, -а вот оценивать «сложность» с помощью численных метрик — дело заведомо неблагодарное, но и «нельзя управлять тем, что невозможно измерить …».

    -

    Обычно разговоры о «сложности» включают в себя только оценочные суждения без какой либо численной оценки. -А так как лично меня интересует вопрос сложности языков программирования, -то я решил посчитать сложность реализации компилятора gcc в каких нибудь условных попугаях. -Вдруг можно будет увидеть какие нибудь закономерности?

    -

    Выбор «попугаев» для измерения

    -

    Я не стал придумывать свои или вычислять эмпирические метрики программного кода, -и в качестве «попугая» решил взять самую простую метрику SLOC (англ. Source Lines of Code) — количество строк исходного текста компилятора, -которая очень легко вычисляется.

    -

    Правда, с её помощью можно будет оценивать сложность языка только при следующем допущении — сложность языка должна находиться в прямой зависимости от сложности его реализации, -если для простых синтаксических конструкций будет требовать меньше кода, чем для более сложных.

    -

    Конечно, использование метрики «количество строк исходного кода» имеет и свои недостатки, -т.к. она сильно зависит от используемого языка программирования, стиля оформления исходного кода и в общем случае не позволяет сравнивать несколько разных проектов между собой.

    -

    Но для численной оценки сложности кода в рамках одного проекта, метрика SLOC подходит хорошо.

    -

    Методика подсчета SLOC

    -

    Изначально попробовал использовать простой bash скрипт с поиском по маске и подсчетом числа строк в файлах исходника через wc -l. -Но через некоторое время стало понятно, что приходится изобретать очередной велосипед.

    -

    Ну вы поняли

    -

    Поэтому решил взять уже готовый. После быстрого поиска остановился на утилите SLOCCount, -которая умеет анализировать почти три десятка типов исходников.

    -

    Список типов файлов для автоматического анализа

    -
        1. Ada (.ada, .ads, .adb) 
    -    2. Assembly (.s, .S, .asm) 
    -    3. awk (.awk) 
    -    4. Bourne shell and variants (.sh) 
    -    5. C (.c) 
    -    6. C++ (.C, .cpp, .cxx, .cc) 
    -    7. C shell (.csh) 
    -    8. COBOL (.cob, .cbl) as of version 2.10 
    -    9. C# (.cs) as of version 2.11 
    -    10. Expect (.exp) 
    -    11. Fortran (.f) 
    -    12. Haskell (.hs) as of version 2.11 
    -    13. Java (.java) 
    -    14. lex/flex (.l) 
    -    15. LISP/Scheme (.el, .scm, .lsp, .jl) 
    -    16. Makefile (makefile) — not normally shown. 
    -    17. Modula-3 (.m3, .i3) as of version 2.07 
    -    18. Objective-C (.m) 
    -    19. Pascal (.p, .pas) 
    -    20. Perl (.pl, .pm, .perl) 
    -    21. PHP (.php, .php[3456], .inc) as of version 2.05 
    -    22. Python (.py) 
    -    23. Ruby (.rb) as of version 2.09 
    -    24. sed (.sed) 
    -    25. SQL (.sql) — not normally shown. 
    -    26. TCL (.tcl, .tk, .itk) 
    -    27. Yacc/Bison (.y) </code>
    -

    Причем, считает не просто количество строк исходного текста, но и умеет игнорировать комментарии, -исключает из подсчета дубли файлов (сравнивает их хеш суммы), а также выводит расчетную трудоемкость, -примерную оценку стоимости разработки анализируемого проекта и другие характеристики.

    -

    Меня изначально интересовал объем исходников на С/С++ и может быть еще на Ассемблере, если таких файлов окажется достаточно много. -Но после начала работы очень обрадовался, что не стал изобретать велосипед, а взял готовую тулзу, -т.к. она отдельно считала статистику исходных файлов синтаксического анализатора Yacc/Bison (.y), -который и определяет фактическую сложность парсера (читай сложность синтаксиса языка программирования).

    -

    Старые исходники gcc брал с https://gcc.gnu.org/mirrors.html, но перед запуском анализатора удалил каталоги других компиляторов (ada, fortran, java и т.д.), -чтобы они не попадали в итоговую статистику.

    -

    Результаты в попугаях

    -

    -

    Итоговая статистика

    -

    -

    Объем кода синтаксического анализатора Yacc/Bison

    -

    -

    Объем общей которой базы GCC (только для языков C и C++)

    -

    Выводы

    -

    К сожалению, синтаксический анализатор Yacc/Bison использовался только до 3 версии, а после его использование свелось на нет. -Поэтому оценить сложность синтаксиса С/С++ с помощью объема кода парсера можно лишь примерно до 1996-98 года, -после чего его стали постепенно выпиливать, т.е. чуть менее, чем за десять лет. -Но даже за этот период объем кодовой базы синтаксического анализатора вырос двукратно, что примерно соответствует по времени реализации стандарта C99.

    -

    Но даже если не учитывать код синтаксического анализатора, то объем общей кодовой базы так же коррелирует с внедрением новых стандартов C++: C99, С11 и C14.

    -

    На графике не видно выраженного пика для С+17 и следующих версий, но предполагаю, -что при текущем объеме кодой базы (более 4 миллионов строк только С и С++ кода), несколько тысяч строк, -необходимых для поддержки синтаксических конструкций новых стандартов просто незаметно.

    -

    Вывод первый - очевидный. Рост сложности инструментов разработки

    -

    Фактически на примере проекта GCC можно видеть постоянный и неотвратимый рост сложности рабочих инструментов программистов.

    -

    И как бы не говорили о деградации разработки в статье “Хорошие времена рождают слабаков”, -о системном кризисе программного обеспечения, который носит поколенческом характер, но мне кажется тут дело немного в другом.

    -

    Обновление персонала и как следствие — необходимость обучения новых сотрудников старым наработкам, -тут дело не сколько в передаче знаний, сколько в возможности эти знания усваивать.

    -

    Причем возможность усвоения знаний для разных поколений будет разная, но не из-за того, что предыдущее поколение было умнее, а у нового поколения не хватает толку в этом разобрать. -Просто изменяется окружение и усложняются рабочие инструменты, по сравнению с теми, которые были в ходу у предыдущего поколения.

    -

    Вывод второй — порог входа

    -

    Представьте, что нужно «сделать свой сайт». Естественно нужно определить, какую CMS для него использовать и какой брать хостинг. -И если с хостингом вопрос решается очень просто, конечно же в TimeWeb, да еще и с бонусом по ссылке, то при выборе CMS приходится подумать.

    -

    И если для простых сайтов существуют и простые решения, то для тех, кто не ищет легких путей существует CMS Drupal, -который примечателен тем, что имеет фантастически высокий порог входа для начала использования.

    -

    Сложность внедрения Drupal

    -

    Это я к чему? При использовании любого инструмента, как и языка программирования, существует некий минимальный уровень комфортного использования. -Причем этот уровень прямо пропорционально связан с размером той целевой аудитории, для которой он предназначен. -Точнее, размер возможной аудитории определяется в том числе и требованиями к уровню начальных знаний и квалификации потенциального пользователя.

    -

    Итоговый вывод — не утешительный

    -

    Если рассматривать увеличение сложности только самого ПО, то это одно дело. Вот к примеру:

    -

    Статистика ядра Linux с вики

    -
    17 сентября 1991: Linux версии 0.01 (10 239 строк кода).
    -14 марта 1994: Linux версии 1.0.0 (176 250 строк кода).
    -Март 1995: Linux версии 1.2.0 (310 950 строк кода).
    -9 июня 1996: Linux версии 2.0.0 (777 956 строк кода).
    -25 января 1999: Linux версии 2.2.0, изначально довольно недоработанный (1 800 847 строк кода).
    -4 января 2001: Linux версии 2.4.0 (3 377 902 строки кода).
    -18 декабря 2003: Linux версии 2.6.0 (5 929 913 строк кода).
    -23 марта 2009: Linux версии 2.6.29, временный символ Linux — тасманский дьявол Tuz (11 010 647 строк кода).
    -22 июля 2011: релиз Linux 3.0 (14,6 млн строк кода).
    -24 октября 2011: релиз Linux 3.1.
    -15 января 2012: релиз Linux 3.3 преодолел отметку в 15 млн строк кода.
    -23 февраля 2015: первый релиз-кандидат Linux 4.0 (более 19 млн строк кода).
    -7 января 2019: первый релиз-кандидат Linux 5.0 (более 26 млн строк кода).
    -

    А что делать, если сложность программного обеспечения накладывается на тенденцию постоянного усложнения самих рабочих инструментов? -Ведь постоянное развитие языков программирования неизбежно повышает порог входа для всех начинающих и только усугубляет проблему сложности разработки ПО.

    -

    Другими словами, не зависимо от того, как хорошо документирован код и как полно он покрыт тестами, -через некоторое время устаревают используемые инструменты, завершаются жизненные циклы внешних зависимостей, -и самое главное, приходят новые люди взамен тех, кто разработал или сумел разобраться в системе.

    -

    И у новых людей возникает необходимость разбираться в системе с самого начала, но в других начальных условиях. -И из-за этого, сложность изучения системы для всех новых людей будет выше просто по факту того, -что изменились внешние условия и усложнились рабочие инструменты, которыми приходится использовать новым сотрудникам.

    -

    Понятно, что чем дальше, тем проще уже не будет. Ведь область IT , это среда с самой высокой конкуренцией. -И как уж тут не вспомнить Льюиса Кэррола, что его крылатое выражение

    -
    -

    Нужно бежать со всех ног, чтобы только оставаться на месте, а чтобы куда-то попасть, надо бежать как минимум вдвое быстрее!

    -
    -

    Ведь это относится не только к Алисе в стране чудес, но и ко всем информационным технологиям в целом!

    -

    Первоначальная публикация

    - -
    - - - - - - - - - - - - - - - - -
    -

    Какая «идеальная» цель развития у языков программирования?

    - - -

    КДПВ

    -

    С постоянной периодичностью появляется информация о выходе новой версии того или иного языка программирования. -И с каждой новой версией расширяются его возможности, добавляются новые синтаксические конструкции или иные улучшения.

    -

    И это очень сильно напоминает развитие технологий, как и в любой другой области техники. -Когда с очередным этапом совершенствуются создаваемые творения. -Быстрее, выше, сильнее … и одновременно значительно сложнее.

    -

    Об этой проблеме меня заставила задуматься первоапрельская статья «Доказательное программирование».

    -

    Понятно, что дата публикации статьи говорит сама за себя. -Тем не менее, новые стандарты С++, постоянно выходящие спецификации Java или новый синтаксис у PHP 8, -невольно заставляют задуматься, а в нужную ли сторону идет развитие языков программирования? -Ведь большинство нововведений добавляют сложность в основной рабочий инструмент и решая одни проблемы, неявно добавляя множество других.

    -

    А что должно быть в конце прогресса у развития такой дисциплины как программирование? -Или хотя бы у одного конкретного языка? Ради достижения какой конечной «идеальной» цели разрабатываются новые стандарты языков программирования?

    -

    Если фантазировать об идеальной конечной цели развития, например транспорта, -то это будет мгновенное перемещение на любое расстояние с произвольной полезной нагрузкой и нулевым потреблением энергии.

    -

    Или, например, какая может быть идеальная цель у медицины? Бедные не болели, а богатые не выздоравливали, вероятно, лечение любых болезней и биологическое бессмертие.

    -

    Конечно, «идеальная» цель это очень упрощенное понятие. Фактически, «идеальная» это синоним «недостижимая», -т.к. она всегда будет упираться необходимость соблюдать компромисс между различными взаимно-исключающими граничными условиями.

    -

    Но сравнивать разработку средств программирования с процессом развития в других технических дисциплинах напрямую нельзя. -Ведь при создание конечного продукта в любой технической области, все сложные производственные операции, -которые требуют непосредственного участия человека, практически всегда можно разделить на отдельные, более простые части или этапы.

    -

    Это делается, в том числе и для того, чтобы сложность одной выполняемой операции не была запредельной для исполнителя. -Но как это можно сделать при разработке программного обеспечения?

    -

    В данном случае, я имею ввиду конечную ограниченность возможностей одного конкретного человека в противовес возможностям разделения технологических процессов на отдельные этапы, -каждый из которых может выполняться совершенно разными людьми (как пример, это обычный конвеер с его разделением труда на элементарные операции -или узкая специализация врачей-специалистов в одной конкретной области).

    -

    Ведь даже сложно себе представить фантастическую организацию труда программистов в виде конвеера:

    -
      -
    • Первый разработчик пишет только интерфейсы функций и их вызовы, после чего передает код второму сотруднику.
    • -
    • Второй пишет в тексте программы только условия проверки и безусловные переходы и передает текст третьему.
    • -
    • Третий отвечает за написание циклов и общее форматирование кода и т.д. -и результате ожидаемо получится полный бред.
    • -
    -

    Из-за этого индустрия разработки ПО вынуждена идти по экстенсивному пути развития (т.е. за счет увеличения используемых в производстве ресурсов). -Современные промышленные языки программирования имеют очень богатые возможности по разделению кода приложения на отдельные функции/модули/компоненты, -что позволяет вести разработку сложного программного продукта сразу множеству сотрудников одновременно.

    -

    Но и такое развитие имеет естественное ограничение. И этим ограничением является сам человек, -так как каждый разработчик должен знать и уметь пользоваться своим рабочим инструментом, т.е. языком программирования.

    -

    Если взять приведенную выше аналогию с конвеером, то в ней каждый рабочий должен был бы досконально знать большую часть используемых станков -и инструментов на всем заводе, независимо от того, какую одну конкретную операцию он выполняет на своем рабочем месте.

    -

    Ведь парадокс развития языков программирования заключается в том, что добавляя новые возможности и синтаксические конструкции, -мы усложняем рабочий инструмент, предназначенный как для совместного, так и для индивидуального использования!

    -

    И получается, что одновременно с процессом постоянного наращивания возможностей средств разработки идет -и обратный процесс — увеличение сложности разработки кода отдельно взятым разработчиком. -Фактически, это и есть то самое взаимоисключающее непреодолимое противоречие.

    -

    Может быть именно поэтому невозможно найти «серебряную пулю», которая бы повышала производительность труда одного программиста? -Ведь внимание и возможности человека не безграничны. -И любые новшества и улучшения рабочего инструмента программиста вынужденно толкают всю IT индустрию на экстенсивный путь развития.

    -

    Возможно следует разрабатывать принципиально новые подходы, а не гнаться за синтаксическим сахаром в языках программирования из прошлого века? -Или и вовсе не париться, продолжать пользоваться тем, что есть, а теория дедушки Дарвина все сама расставит по своим местам?

    -

    Первоначальная публикация

    - -
    - - - - - - - - - - - - - - - - -
    -

    Проблема логических языков программирования

    - - -

    КДПВ

    -

    Некоторое время назад я писал про «Интернациональное программирование на естественных языках», -в которой попытался представить достойную цель для абстрактного языка программирования, -попробовав примерить на него роль связующего звена между миром программистов с компьютерами и не программистов.

    -

    Но в результате оказалось, что это не нужно в принципе, т.к. «не программистам» просто не требуется учиться писать программы. -А если иногда такое желание и возникает, то вполне хватает обычных формализованных языков программирования, -которых уже сейчас насчитывается наверно более десяти тысяч.

    -

    А пользователи, как программисты, так и не программисты, просто хотят решать возникающие перед ними задачи. -И хотя задачи бывают совершенно разные, но если способ (алгоритм) её решения известен, то выбрать язык для её решения не составит никакого труда.

    -

    За исключением одного класса задач. Задач, решение которых нельзя описать в виде алгоритма. -Но можно указать некие критерии, которым должно удовлетворять искомое решение.
    -Я имею ввиду логические языки программирования и Пролог, как самый яркий представитель этого класса.

    -

    Еще помню воспоминание из юности, когда удалось достать дискету с этим языком. -Ух, с каким задором горели мои глаза, когда мне казалось, ну вот, еще чуть-чуть и будет создана система с базой знаний, -у которой и можно будет получить заветный ответ 42 на любой вопрос.

    -

    Так почему этого так и не случилось? В чем проблема Пролога, да и любой системы / языка программирования, -назначение которых анализировать факты и искать ответы на вопросы?

    -

    Эта проблема называется «Комбинаторный взрыв» - экспоненциальная (или более) зависимость времени работы алгоритма от количества входных данных. -И есть как минимум два решения этой проблемы.

    -

    Подходы к написанию программ

    -

    Прежде чем переходить к частностям, следует сказать пару слов про парадигмы программирования. -Обычно противопоставляют между собой два разных стиля в написании программ: императивный и декларативный.

    -

    Императивный — это классический вариант написания программы, при котором программист сам задает шаги алгоритма для получения конечного результата. -А сам текст программы состоит из последовательности команд, которые читают, сохраняют и обрабатывают данные или вызывают другие команды.

    -

    Декларативный — в этом стиле программист описывает условия задачи и правила для получения требуемого результата, -но не требуется детально описывать все шаги работы алгоритма, оставляя их на усмотрения компьютера.

    -

    Именно к декларативному стилю относится язык Пролог, да и все остальные логические языки программирования. -К декларативному стилю написания программ следует относить и язык структурированных запросов (SQL).

    -

    И проблема под называнием «комбинаторный взрыв» сильнее всего оказывает негативное влияние как раз на подобные языки. -Ведь в императивном подходе программист сам отвечает за последовательность выполняемых команд, и если он запрограммировал алгоритм полного перебора всех возможных вариантов решений, то он сам себе злобный Буратино.

    -

    Другое дело, программирование в декларативном стиле. Разработчик хоть и может указать ограничения, которые следует применять при поиске решения, -но это возможно только в том случае, когда известен алгоритм решения задачи. -Но если алгоритм решения известен, то проще использовать императивный стиль, как раз и реализуя этот алгоритм!

    -

    Поэтому основное применения языков программирования в декларативном стиле — отказаться от необходимости описания четкого алгоритма поиска решения, -отдав это компьютеру на откуп. Для которого самое простое решение «в лоб» - полный перебор возможных вариантов.

    -

    Именно в этом случае и начинается экспоненциальный рост времени выполнения алгоритма. -И начиная с определенного порога, время ожидания ответа становится неприемлемым для реального использования. -Это и означает «Комбинаторный взрыв», резкий («взрывной») рост времени выполнения алгоритма при увеличении размера входных данных.

    -

    Проблема поиска решений

    -

    В языке Пролог эта проблема решалась за счет использования механизма отката и отсечений. -Иногда еще уточняли про «красное» и «зеленое» отсечение решений. -Но в любом случае, это были алгоритмические механизмы для ограничения количества размера дерева возможных решений, -а необходимость их применения все равно остается на программисте.

    -

    Но чтобы их правильно реализовывать, нужно знать алгоритм решения, что опять возвращает нас к утверждению о том, -что если известен алгоритм, то и программировать его удобнее в императивном стиле.

    -

    А если полный алгоритм решения задачи не известен (или не подходит, например из-за большого времени для его работы), -то в результате остается либо увеличивать производительность системы, чтобы сократить время выполнения алгоритма, -либо искать другое решение, в том числе, сокращая вычислительную сложность поиска решений, например, исключая заведомо не подходящие данные, -чтобы уменьшить возможные комбинации их перебора.

    -

    Масштабирование производительности

    -

    Увеличение производительности тоже бывает разным и работает не во всех случаях. -Вертикальное масштабирование производительности одного узла вычислительной среды имеет свой естественный предел. -И даже многократное увеличение скорости работы компьютера может лишь отдалить порог терпения пользователя при ожидании получения результата, -но не в состоянии принципиально решить саму проблему.

    -

    Другое дело горизонтальное масштабирование, при котором выполнение алгоритма запускается на отдельных узлах, которые параллельно решают одну и ту же задачу. -Такой способ масштабирования позволяет уже значительно сократить время получения итогового результата для сложных вычислительных задач. -И хотя это способ является решением «в лоб», но успехи в области data science доказывают успешность такого подхода.

    -

    Конечно, у горизонтального масштабирования тоже есть подводные камни. -В первую очередь, сам алгоритм должен допускать возможность параллельного выполнения независимо от других узлов. -Также требуется автоматизация управления заданиями, самими вычислительными узлами, да и всей системой в целом.

    -

    Тут частично может помочь парадигма функционального программирования, которая ограничивает результат вычисления функций только входными параметрами -и результатом выполнения других функций, но сам результат не зависит от состояния системы или иных внешних данных.

    -

    Поиск обобщенного решения

    -

    Вторым способом решения решения проблемы комбинаторного взрыва является уменьшение вычислительной сложности решения. -Тут имеется ввиду не выбор другого алгоритма или решение задачи в символьном виде. -Если такое возможно, то все опять сразу сведется к императивному стилю программированию.

    -

    Я имею ввиду возможность поиска самого алгоритма решения. -Точнее не совсем алгоритма, а возможность применения к входным данным различные методы отбора, чтобы исключить необходимость их полного перебора. -По сути, это сводится к применению различных методов и механизмов обработки входных данных с учетом различных закономерностей.

    -

    Это возможно как алгоритмическими методами (откат и отсечение в Прологе), так и с применением машинного обучения, -которое очень хорошо справляется с поиском различных закономерностей.

    -

    Естественно, такой способ подходит не для всех классов задач. Он не подходит для выявления ВСЕХ возможных решений. -Но там где это не требуется, подобные способы уменьшения вычислительной сложности имеют право на существование.

    -

    Например, не требуется искать все возможные лекарства от конкретной болезни, достаточно одного, с учетом определенных ограничений, которое гарантированно подействует.

    -

    К тому же, даже при нахождении частных решений, всегда существует шанс, что с их помощью получится увидеть не очевидные на первый взгляд закономерности, -которые помогут показать новые пути алгоритмического уменьшения вычислительной сложности основной задачи.

    -

    Область не решаемых задач

    -
    -

    Как вы считает, а реально ли создать язык логического программирования, который бы сам умел автоматизировать поиск решений для задач подобных классов? Или хотя бы имел в своем арсенале встроенные механизмы для автоматизации подобной деятельности?

    -
    -

    Результаты опроса из оригинальной публикации

    -
    - 57.47%    Ха-ха! То, что хочет автор и называется искусственным интеллектом (50 голосов)
    -- 27.59%    Поиск решений нельзя автоматизировать (24 голоса)
    -- 19.54%    Это уже есть и все давно придумано (17 голосов)
    -- 9.2%      Такой язык не нужен, т.к. нейросети могут всё (8 голосов)
    -- 3.45%     Свой вариант написал в комменатрии (3 голоса)
    -

    Проголосовали 87 пользователей. Воздержались 62 пользователя.

    - -
    - - - - - - - - - - - - - - - - -
    -

    Интернациональное программирование на естественных языках

    - - -

    КДПВ

    - - -
    -

    Внимание!!!

    -

    Данная статья содержит описание синтаксиса NewLnag предыдущей версии.

    -

    Актуальную версию синтаксиса языка можно посмотреть тут.

    - -
    - -

    В последнее время часто попадаются на глаза статьи о новых языках программирования, -а так же различные рейтинги и прогнозы, связанные с популярностью компьютерных языков.

    -

    Заявляют о себе и новые инструментальные средства, -которые в своей работе используют собственные форматы описания конфигурационных файлов или последовательности выполняемых команд, -которые так же очень сильно приближает их к понятию «язык программирования».

    -

    Цель написания данной статьи — формулировка ожиданий и возможной реализации абстрактного языка программирования, -который может стать универсальным инструментом для общения между компьютером и человеком.

    -

    О программистах

    -

    Если начинать с самого начала, то когда-то давно я слышал перефразированное высказывание, -«каждый программист должен написать свою базу данных, текстовый редактор и язык программирования». -И если первые две вещи я уже давным давно написал, то с языком программирования пока не сложилось.

    -

    Ведь как обычно создаются языки программирования?

    -

    У каждого программиста всегда есть какой-то своей предыдущий опыт:

    -
      -
    • знания одного или нескольких языков программирования (как же без этого)
    • -
    • негативный опыт от их использования (в противном случае, если все устраивает, то зачем придумывать что-то новое?)
    • -
    • желания получить новые возможности (когда в существующих языках чего-то не хватает)
    • -
    -

    А перед тем, как описывать синтаксис, выбирать ключевые слова и начинать основную работу: -лексер, парсер, базовые библиотеки, нужно дать ответ на основные вопросы:

    -
      -
    • Компилятор/интерпретатор/транспилятор(transpiler)?
    • -
    • Статическая или динамическая типизация?
    • -
    • Ручное управление памятью или автоматическое со сборщиком мусора?
    • -
    • Модель программирования: ООП, функциональное, структурное или что-то новое?
    • -
    • Разрешены ли вставки из других языков программирования и т. д.?
    • -
    -

    У меня, наверно, как и у большинства читателей, присутствует опыт использования нескольких языков программирования. -Поэтому давно сложилось практика, что для решения задачи лучше взять известный язык или даже выучить новый, вместо того, -чтобы начинать писать собственный.

    -

    Тем более, что не хочется придумывать еще один язык просто ради галочки или ради самого языка. -Я считаю, что цель его создания должна быть за пределами потребностей самого разработчика.

    -

    И мне кажется, что удалось определить область, для которой разработка языка программирования может быть востребованной, -а потраченные на него усилия могут принести реальную пользу.

    -

    О не программистах

    -

    Эта область — программирование для «не программистов» на «естественном» языке. -Я специально взял слова «не программистов» и «естественном» в кавычки, т.к. эти термины являются очень условными.

    -

    Ведь если не программист начинает программировать, то сам того не осознавая, он автоматически становится программистом ;-). -А «естественным» язык программирования быть не может по определению. -Точнее для компьютеров скорее всего «естественным» будет язык Assembler или набор машинных команд.

    -
    -

    Поэтому, цель максимум — приблизить язык программирования к естественному человеческому языку.

    -
    -

    Это не только сделает чтение текста программы более понятным для не профессионалов, -но и позволит начинать составлять программы просто освоив письменную речь, используя самый минимум основных правил.

    -

    Но в подобной формулировке кроется очень большая проблема!

    -
    -

    Любой язык программирования является интернациональным, т.к. его синтаксис не зависит от естественного языка, на котором общается программист.

    -
    -

    А если текст программы будет на “естественном” языке, то она станет понятной только для знающих этот язык, -одновременно становясь непонятной для всех остальных.

    -

    В качестве иллюстрации: раз или два. -Если пофантазировать насчет хотелок к такому языку, то видятся следующие требования и ограничения:

    -
      -
    • Так как каждый пользователь является носителем своего родного естественного языка (или даже нескольких), то жестко задавать ключевые слова невозможно, из чего следует, что основой такого языка должны стать только правила пунктуации, но никак не лексика или грамматика.
    • -
    • Компилятор/транслятор должен уметь преобразовывать исходный текст программы не только в машинный код для компьютера, но в другой вариант “естественного” языка, чтобы пользователь мог работать с исходным текстом на известном ему “естественном” языке.
    • -
    • Очень хочется видеть в новом языке толерантность терпимость к очепяткам. Подобная «фича» присутствует в письме на естественном языке, и несмотря на наличие опечаток, практически всегда сохраняется смысл. Естественно, в данном случае не стоит доходить до фанатизма. Компилятор не читает мысли и не может в действительности «понять», что имел ввиду пользователь, и все же довольно часто можно игнорировать опечатки в тексте программы исходя из контекста (пусть и с выводом предупреждающих сообщений).
    • -
    -

    Тем не менее, такой язык должен оставаться именно языком программирования со всеми возможностями создания программ любого уровня сложности, -включая функциональное и объектно-ориентированное программирование и однозначное понимание написанного.

    -

    О гипотетическом языке

    -

    Если взять за основу правила письменной речи, то основные соглашения и пунктуация для нового языка могут выглядеть примерно так:

    -
      -
    • Любой текст состоит из предложений и комментариев. Предложения обрабатываются, а комментарии игнорируются.
    • -
    • Предложение состоит из последовательности терминов, литералов и символов, разделенных пробелами и знаками препинания и завершается символом конца предложения.
    • -
    • Термин — слитно написанная последовательность букв, цифр и символов “:” и “_”.
    • -
    • Литерал — константы, включаемые непосредственно в текст программы, тип которой определяется однозначно. Это символьные строки в кавычках, целые и вещественные числа, и некоторые специальные форматы (время, дата).
    • -
    • Символы — все остальное символы, которые не относятся к знакам препинания, пробельным символам, цифрам и буквам.
    • -
    • Знаки препинания — символы пунктуации, имеющие специальное значение при разборе текста программы: -
        -
      • «.»,«;»,«!»,«?»,«…» — конец предложения.
      • -
      • «=» — присвоение значения.
      • -
      • "" (кавычки) — определение символьной строки.
      • -
      • «()» - передача параметров/аргументов или группировка операторов для определения приоритета выполнения операций.
      • -
      • «[]» - массив или обращение к элементу массива.
      • -
      • «{}» - включение в текст исходного кода программы на обычном языке программирования.
      • -
      • «$» — системная переменная.
      • -
      • «@» — системная функция.
      • -
      • «,» (запятая) — перечисление.
      • -
      • «:» (двоеточие) — список или логическая связь.
      • -
      -
    • -
    -

    Если с символом присвоения, кавычками, круглыми и квадратными скобками все должно быть более-менее понятно, -т.к. их назначение соответствует аналогичному в подавляющем большинстве языков программирования, -то про назначение остальных символов (фигурных скобок, двоеточия, запятой и системных функций/переменной), следует немного пояснить.

    -

    Раз цель гипотетического языка программирования все же написание программ, -то необходимо предусмотреть возможность делать вставки обычного программного кода без учета всех возможностей и неоднозначностей, -которые присущи любому естественному языку.

    -

    Так же эта возможность требуется для реализации низкоуровневых функций и для взаимодействия с внешними библиотеками.

    -

    При создании подобных вставок и могут использоваться фигурные скобки, весь текст между которыми будет вставляться в итоговый файл практически без обработки.

    -

    Для похожих целей служат и символы «$» — системная переменная и «@» — системная функция. Если такой символ поставить в начале слова, -тогда он станет обозначать объект с соответствующим назначением. Например «@exit» — будет означать функцию, -а «$var» — переменную с соответствующими именами, а сами объекты станут доступны как в обычном коде, -так и в программных вставках внутри фигурных скобок.

    -

    Аналогичным образом организуется и доступ к отдельным полям/методам объектов: -«объект@метод» или «объект$поле».

    -

    Символ запятая «,» применяется для указание последовательности равноправных логических блоков в одном предложении или для создания списков.

    -

    Символ двоеточия «:» используется для создания списков и для обозначения логической связи между двумя частями слова/текста, в том числе для указания полного пути модуля.

    -

    Например, создание списка:

    -

    В_строку: элемент 1, элемент 2, последний элемент.

    -
    Форматированный_список:
    -- элемент 1;
    -- элемент 2;
    -- последний элемент.
    -

    Логическое следствие/указание связи:

    -
    module:calc //термин «calc», который находится в модуле «module»
    -super:module:example$var //переменная «$var» которая находится в указанной иерархии.
    -

    Как можно заметить, использование знаков препинания взято из их прямого назначения, принятого в письменной речи, -что должно обеспечить определенный компромисс между синтаксисом в стандартных языках программирования и письмом на естественном языке.

    -

    О компьютерах

    -

    Так как речь идет все же о языке программирования, то не обойтись без стандартных алгоритмических конструкций: следования, ветвления и циклов.

    -

    Следование легко описывается обычными правилам письма на естественном языке. -В случае последовательного выполнения в одном предложении, операции и вызовы функций записываются последовательно через запятую. -Если они располагаются в разных предложениях, то они записываются так же друг за другом. -Причем форматирование по абзацам служит только для лучшего восприятия текста и логического разделения отдельных фрагментов.

    -

    При создании условных и циклических управляющих конструкций уже потребуются ключевые слова. -Но так как согласно исходным пожеланиям к языку, резервировать обычные термины для записи алгоритмических конструкций нельзя, -то перед ключевыми словами достаточно указывать символ системной функции, что позволит отличить обычный термин от ключевого (управляющего) слова.

    -

    Естественно, при программировании, данными терминами хоть и можно будет пользоваться, но делать это совсем не обязательно. -Так как при настройке под конкретный естественный язык, системным функциям и ключевым словам нужно обязательно присвоить конкретные термины и пользоваться уже ими, например:

    -
    перейти = @goto,
    -метка = @label,
    -продолжить = @continue,
    -прервать=@break и т.д.
    -

    И последняя по очереди, но наверно самая важная по сути конструкция: передача параметров при вызовах функций. -Если стремиться к полностью естественному синтаксису, тогда мы получим тот самый естественный язык, который очень сложно анализировать.

    -

    Тем не менее, мне кажется, что можно скомбинировать оба два подхода, если отказаться от обязательного использования круглых скобок, -там, где это допустимо по синтаксису.

    -
    Компьютерный: функция(параметр1, функция2(), параметр3=значение).
    -Естественный: функция параметр1 функция2 параметр3=значение.
    -

    Но:

    -
    Компьютерный: функция( функция2(параметр) ).
    -Естественный: функция функция2(параметр).
    -Или так: функция (функция2 параметр).
    -

    Другими словами, для естественного порядка указания аргументов, скобки для функций и запятые между параметрами могут быть опущены. -Хотя их использование должно определяться в первую очередь целевым естественным языком, а не синтаксисом.

    -

    О возражениях

    -

    Предвижу обоснованные возражения против использования подобного языка со стороны программистов. -Программа на нем по любому получится значительно многословнее, чем с использованием строгого формального синтаксиса обычных компьютерных языков.

    -

    Поэтому напомню про его обязательное свойство - умение преобразовывать текст программы с одного языка на другой. -Это позволяет писать программы как с использованием строго формального синтаксиса без использования переопеределенных терминов на естественном языке, -так и преобразовывать исходный текст в “естественный” язык для “не программиста”.

    -

    Ссылка на первую публикаци

    - -
    - - - - - - - - diff --git a/docs/blog/complex-prog/bag.jpeg b/docs/blog/complex-prog/bag.jpeg deleted file mode 100644 index c80334a26fe0bac80ae39a117bc853eb03db5094..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 204893 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

    7O zF119iW?W9`ZGs>1!7CG2;Ykq_0RVkzMxI;qyOMpi;V7TCa+DrQ50e-X1?DSXqldqcYiz&0@@pMWXEOtAZefmXO{gWaZKglnmmF%QpFQNY}~WyQ2?aGrYQABMgjU zEIuatKAx%bV+Z!=ZzC(_G1F;T+v>8~+y*i0lu-vBI{UNZQ#VA79IB(1vStvaNQU>9YW#o0Vh5FepV zlYY{mjDJ0f(q3(Ft5FIZfJEhyeNlC_OWb!d;Do<${kL3Y`WkbV$CdcBpHBi%Lg~6= z)L`>}T9$d=j#9m4T=fiJGv>c?d;M)U16%_0Kr z9@aP290E;YnU5iJ!gjkZFH5>wS8V=5*Y$^<2d9%ukw9eiJ&a#(V%9pDz_~_cYNeI3 zSdiqDh6$s-;kxEwtJG8tu0OZ>tImFR%N&k?$(NhtB>w1;0rPWixGe`Brq;up{MzMX zwOAi8Ku-3+7dgo4U)w5@uF>zdJVj9!k6*M#G2?~S!QQ3t&INA%`MaW3FD!ZF5L3;VU|z~=O36=riyBmf zaLuOHFnoj5MWx%&`Apx$l!N)@Eb*I8;;gdDDA6gVX+@l7K1eNoFCjLuVEkhzh$*#QK&zbzj(AA>7;4BK$tPRJ2 z#C#2d$!;Wz*Pk-CTyaMc?-3)qG{;jRvo@Z#usp6g{EIa#J#Z24XnK1>TVEM+I*$tp zIlH^z9SVQh>Vf)0G4~70HoS>D%g3bcM>iv{k-1$_!!F?#z|j4KrX^*W$9L_ z!tU9$W4X+o7_pvvLAt}%XHBnNf4xquL~425M&^q#Ju?p>i1^~h}5eY}mDXXPuOxkKii_sDQVeWI2=ziB25kj+jGYMD% z=ZoKi;!$IksyF7WyKYqBVeF{X@6fL~0qN2iZY=6!Qq)_quPLzbVCT=#`<4ll*6LeS zRh>Zj!uw@rHl)A4WahyYO#Rzx*ZD;P`j*UmM;f~6V>>J}-njqRIY$1>rcv$(9O%vc zwKs9pL1R0huZATQu8mM8d@_s(bT)}s%Ckid45;t1ILpub8dFZQZ3XJF+B$9X*uv3K zot`ao_}2v1^B;Y;=Ti^$(8(sIPikkpLo|mvzHk2Da!CvCQlI{mNm7+Z1Ci6P0&YKTRGZ!?xemFjcVX=?z2zOCHdnZPn0eJeBC3uAwZedW=%ME36c+LkT zb`j_9KO~XQS?>0@zmFKsU#~I#dHYE>j^TJiaNB-6-(i~*XrmGQ{XA0GWq4d3wD|m& zBsGrLp2@F8(8)tcrh$&0^F$Jm)2iDXs9SjuRvG+mXg}1~yg17(miK*8@X_}udwhhr zS`FuM&)xME&LUM${Xdv7?aqZI7a_EgkdSIRXm*}S1Y(<)h~*NB0O2APSpQnqaIP4@ zsWhYS>dT^^KLI)D0TSOW1NR@Oo0LNjJ<@U)6Hw18wa?f!wSEsEq}CcI?}U!l%tf&d zZgMOVYBK77&ZT0^8&!FSuXiP&nrw%UisEx~G5}SnZ#vk`&wEObw0>H;YoVo5b*Na^ zceCRON;Hg@QOj&N9)MDy>u>byE1Qoi44ys73e$94eHpbxvnEm-%Dz!jj)AD{hg;~+ z(+_0q%Q25!OSAdXF^_%bHeu}+4joK*zK~S{sz>LaGfv!ZY200@k8*oJ{|-g*`lZp` zkSH!Sd&O*9;XD$i`qV6+1ZIjD?zzULvYM`v4IuGGP}s(FQzCaxJG!cjTIlH!1lN

    igY>5&r{;vP0S{2osjhybP8%;OIS&(DN)>^&dIkXz zrs0vI5gWpIU+Y)KPLO>MLRl8zPJ{EXUCNE>|JXm65?_%T+bkaCT*tJMDYa?ioD5tV z$>(^yO>=Ho(Gix(N~rEV(xN$KrZzP-9ca@yjzJXuO$w?jIawz`<_yI|&{0AHn1|ZZ zmzS3{_vGbOuss?*Wzl24zPAl;^8V)7njSf<*3P?obl5NmWys)s)abFi3}q8xWzp{b z5*a3!px|DBFmdD8m=+TyJ2UDuT8wVB{$t81PKrTs`rGZY5aoua!BTc*QL?(*oKl4! zrJ59Dd$+O=24=Kb90e9*64(Uh?-jJ&3B%i{!4q^YUiFO1N&eHTo@GnJVp~S_=H04S z|918N;p?n|;*6qnOM(Xv9^BpC-D%w2-QC^YU4l#F?gV!T?hvFQjk`lGGk0ccp62O) z>N?e@>r|hA?{BZg+#p5&lhNFICT`(oODapne;KLs1=_C-aSR8ffLCaRs}p=D@b!^NXt08v|!N)@EX znF1z072P-Yo{!cOhf4DPZ3eAuPt+e}5026Mj&B2NLmxe)>o}ox?Hc^F*h+N{bq1}0 z1mbaeL7)jr@4Ty6OibOj>(bXE6p@Q;Eqb^xN8&NumpuLKhxgl^ z6Fk1uX4ohz+C#_KzV~%2&F#pDrrb_o8L;QqJ=Lrubew%sW0szNV3^KO*niHCV~(Yk z$r}|`3<)>r7eGA7_jhbMBn+6?py6`cN!V5aXphp^kaOTyUC9~O~&Ha^9U3!=Y|Db(o$2rRJE=s`F%|dJ@G}g;#16wq; zHl=7r9Qan3mXuQlSY&92&59D1#88`Nfnfg_abthgg4NLjM)){^-F1r!;1zUUlPoMx zHYqxB>zs!)rYV{*2enw)qN09mI{bq$OG#^FubHG=C*`t)*G-Hx63GlCf4>!EEHBqN zsjde9lJr?e7DL_r;z~t|wVR7JWpVbh)~<45y_b;l%|=Uql2!>Wc&bGnshP)jZsi|D znObOu`tX0gL;YWajye@!vQ%@D-fp5;^FZpJ{BrCgFp$}D^ z4g()S4r;?^qWb%<)qtk&L~=~k`^7`0`huA>uLye7J85UCO2@=JBWxNyUgE*3iOJz4 zAxio2&ls}gT;r}&O2WTw^X(PRM}OqR1>{Sbzi5_$@=w?u67vghmaafIAq4#<4Hb*O zLO2=oUx8wVos*j`oH6t>J#S&SW{8$?4&vW~{K_TNJNQvi*2K5&9MZYy7~-PZhoJ(d z!=~mo3b+t@_i_`ZKR42bMF}CjSc!lXJj5?)jWPM>$qF>HuRa;t=04uc$)ivdfS>eT z39b?XzgXm&*>%Rl!i&S8seBjvNA#0#pNC)H%F(`n-0w#!aLY<+Ve1v@^<&SPP-a?& zVgq1??rwH>i5qoK=OjEppK;_IjAj>UYe59w+OCKr`0#zny9>zmKf}tnH`zR4Gw@#m z#6O(uo(4K$iavMinEn4>L&B~v+FK)isafMzQ>?eOjZ##wo`0GbKABv%{9-lIr3}aX z?DB`|4#A|YpzF8$$qY_3a6WqdSKS)A_J}C2Sa!M?Z5mKaG320+2|DB*p7VD#S+qI) zq-g?rbcEo<8k9+~+nAuu6~Ru^*aV3o@07YcEQwJ~x(vc;j88(P^n)gE=sob^@6+*D zL-=p6O)pIQ+oa~-4OpFH(=@p8D-Mrs>MQy-imOvNnX9l9yxvGnHsuK_hUJ`@_r>Xr zcWCiDmFLX6WFYXO7n3Fw0;s+o#l4dCy`mB^u{A#Fdxrlg-UpX1)fUGScVw)dRbiI! z#Sz|@e6}K(h+saMkq=E4gtYWuzacxsn%YKFneA}P8}g6cOHKIzIRh$qkT`U7Je60# zC!Ip*waH=dPkU@1qK0mkQCTPv>qZjm`r#*8jv1fxTg+T}3!%wRE^&d3_&z)6-&tPl z1j^!Y%1Oe?ztF^xs$%>iHpwbklQkmxEi87(L(loj`EDbiD@L$xuY99!I)5>H-KIH) zZ6yz^*A}QGFYdTxSX$Pe#>=$NbZAn!=PJ`a^gC1y(__yF%}YttZtANRH$yM+KUA40ig`PoSqR%qQi~K6zY{>p-V?LBL+gyY?UM?E@GZ_lUjU;EfeZpG+_}z9(KEX^zp29c1H?jm{L% zH<7`zk8*OTW3g>V=_re5cyX#8R#hIF4 zx639J9`>x2Wib}%Ngw;i$~(m)lNuMv6O@vJxgQx6yHLK<8g-G^|NRqw$OkI_tJa3_ zxyxQVmny2VJ6YC{9)7*bIl|+<4-T`mIyXWN-(qL>{~D)mT90xU&NIlIonPMxYrQ#k z1tHF9Hk}cwM6BA_?n%xxueW2K^&Lr-@*-GLB5DSYeEt1I!`pTq!DD~YcS2m$vvpqE zN@0v>P-N$P4_f1I3$!{b%FtDHB*E=(@y>nV?FM}_?{n02cF-vsRG4q{%WG@Z{^?>K zK7hMb*lj?Z$Tmd*bh(H-w~%2FbMvUC!;hgYz*@>2XZL7da8rYEXU_>J=iO*LpLAJ{ z6rDe#=W%0SM~8G3k~!_ltkKYR4~SdlQ2&E*&l{2>i-XYcg@Em@)Hg%xZkZ3+e3ILz zri6`o=b$MrCUsfYR?nJ`4I3%GZmn+}nu^8I+r*i;C)j%0x?!q<_2MbDN~Y3knM}z| z+pCj|faoi=1o}O+`e?>6zWbfK3HzcX!&oloxrccBcDoZn)0T|4=(<&HldJ|XzDc&a zOFL?x7&Me7=1Gb#OEpYE;^&bjRo|ovwyTxDbNb7beVV<7q`kXS&-v*davxbh!Wmg- z8O7D$iFfz8d$$HAzS6W%;^^O6{(XRD(a`%HCKpnpwVYt!q5VyajOtuyh1U}70aVepDSfI2M$8(zMpI(rDI=448F$P4T4)4-kFSZTFQAy=ZQ?B3H zR8^E_9*el66Qt`kWkOol2gW5vC%GwXYRd4EYqMAa=7hy6{sZ2ie0mtQ554=yR9!8w z5Y@4F3S+{tza!7l7(D{D73r2AAKL8BgcRfCtwT>e1E8+BIV_)|ZR(1@)3gwtcFywh zO!OQKyICs%3UOep(k*BPRMHHs>=n+)R6SvgiG+M@AQ$2G3Ju>1p)RL<^Vbx=oFTBg zn*Y7LtnQ$sGHMZ!IhJeuIDL)w7^Nv8htbNRwsiN3xR?v!Q__!8DMrQQrb#K3KJLPH z?;AP+vbkNjp2gAJJ9Qz4v&t@=L|?qZx^Am0(Z$98h4zQTsJd1g(+XS4$}A5*=JqQC zmlx0$u;O!*aO#5|lSWgD21iSRRauZwV-s7HcS6IfS{{}_?HQpFi|(=Wwh^-~N3pVw ziH_Mdy+W|mivKgP?vTE!(%(;7~g2J{;_mmGt;E;sQ?8VZrK=hsk- zNQQ8DNLu`EBdFfX5LoU@5vs-rBsU@EdENsG=H>G>))^vS=QQ4&!%VkMXZyUsj|ru9gTGH z#@{N+GDl8J!e5b>UG^y$*m<&t{aG%_lZkSJV~^VF-EJZS>nh6He~XoZCE*g9iW~SZ zq%BA}X{|OXV~X{&5Dh4Yzlwn43q$vxQ+2y|z;-R=!Y8i1p1l|AFq3GTz0RvWkx2|R ztObgzIyNv0Qw%9bc206#J}UVG<@M@Vry-I5Ae!RLgYph+?#Jzp3rBFEau$2K7q<{BqXGSYj0SJd9I;Qh19!)>Aw21eX7|7&?hC7%z z{H51zN>nuA?*>=tSr)sY+el}At7I!y=`@vvb`vMyW?O5f5APjVUI0qSiN%U$M|Cu>+P&cqE z%VaHZ?wUHxn@V=*RQLxW__K=1xqsdKJcDa@T3KyDN5_6+%2x$fU4&fLNalO)04Zu= zqF_Bx|0>q^;9PsXr)>hBUbW79mvW4UngICb8`T6opBjSKkv7g-tC^Rqk{J97FHbDU zPddeFka%H%Q`9=i6RPIHgmqAnViqBKn$$2WTE2=v-#pjO8ShRbWZ;lW72E$I=eELX z;Z!9a|E>&)9j1Dj*q3`^Kr*V12wY~WEa>|yt-H4|%`(Dvvviy}TJ88HBrXe7CJ4RF0pJ|U+Y;^{AsB^)v|L7#~> z8jZp{j2gkwehE`IMWJ`W7~yK?2_zx?Q$z3@#ktAi8RU;Sp342HubecBk+UmFzr}9} z?Z)CZj{^l~Eq~Hgl>jMiOJx$59^-W^CQGD;De3&S9mfo^5?hzN;%;a)6Lj(R{$9@G zAWB(8x3p>7X@v{{N7_QOEi_9RtwLriQF@7Q#Wvbu6F7a}s#VjxBqs6J?_Q63Eryf2 zX==1ru`la7wd$62*!`zqLKJEN6s*t*tYxCgHfM;3TW)uL>2(3!s40!;j;pWn!P&^u zQT3;&vCjKUWqg&rqb=b>9D1!&S|oAvunJmc(=j(bGXxjHkpNt*I~*G7h?pR}#!2s{ ztVpJy%&Dp2Sn3{ss_yZ0=b2O}%U-}*X?9S$l}+u#fPS`1dvu(}Gyy;Z37Ix)gc-Ig z(}JiUyxWL@sC8%RM7v2wQgM@Wn*JHJXs0ecMHXHm*f>8H8MgHvgkR4(z*<8YI~&U+33i) zdQqyE=hsY&Habo=w=+Hbpy1X!6`ua7j+-;GBzv82KTG_9t!2KVmrI7BwcN6Hg2^cd z%t4; zn6Z5sazbmoU8Ye#HHV%yk&nOqN}X%3J*S1~d@&ICJk&$Vx1TqFKfa%75V&q2-vW~Q zQl6_mhI~#3(9Gk2@S79_WQ$0|k~s*?!5HF+nkC6`^X^UFz&qyf67~~D4ew!Nk=4H~ zYSK$&Z;?CEmzm~0iBs(Om=a9m|6+1H+3H%Ek25AcF?be1(eA5+#vIJlwHTkI?ykxl z1wp@G`G?QrOfcwk-kGYGT6c|_r?Z47@@(8-*CvcZ$v6PG-A|30xk7ZKR1pBl170q% z$@^#oP8yt?0(YlIe9k8?Rn$pP-vu~|Xu$1LM>L2&FwD!i~HY-L>c0UQS8B7cPO&&cdBJ`XemIM~2s zBGvbQ5JY0ukvju+j>6b)VoHqV_Vw)yZ<0b+1FEsPppyT(is>rC9_fB`AMu;#JL@g9 zzC}knEN_BDl|m{@(`FoGdSW#esL87Y_mKafvRTd`JIWkzCH$ySEp8kq*DyJ~1yq{H z9u>H2eDw5f$^z5bUeE8 zsVu=-4HFVhYtl_JdAUgbB57(|TAS$6FYx%DyOvvff&}6tS)jc``&T*y@l{g_^Oo4y zb^z+lqs!zj7PsKc>a5)U8o*`phijorK&6Gd{)FMxVXBGPR(_Lqs^3gRMY@-rMBcuD z1O{N8@@H1%tXn1HVPo6m)}d{x zXn5~knhc@agx^0_Lg?!=oZuYMAQDtXCQ(0A%1rZ45oMd6SOeP~Xbk0{T>=S*FDf+; zEnDMdt=ZiN7;~vJBHd<#QlnPT*CxkU0i<)M;C4yhh^lvqwNqFH@s1`Vd3HGm(1Gvt z2DwYvD0X$bTLe?4&*cDnymjz&vznHSYF7NOCZ~#I2?z^tQ0pnvhQb!Q*r z%T$hInj)GA2!qA`16cTe$ID>40gA1J?zd>-Ef_+$+gh#(&0|=xr1MF3^48>%oLMo- zOamByCGa{!kemK)t~5ydlM_n)3su#TwVap=^Wy4iDyM6%C_X=$E8+Igv?!ksv}D&p zJ#7r0*XJST9~&F?E6S`$lkUq5^gx(DnKG?7NNCjec2GJL6n9#sU2t#Y`$obUmf<<0 zA*zQFEy87XCz!~<_vyjT^JPexoA5{39z+=i_6_%o1wh+3s&R)Y#D+64F)3l z=DGMN;=Pp4*4i3}FB((sQO>BogS}Q4uP}(myoq7)+hSg)RVDpE9{U0mH=2}nWO0i- z!s2>C(Pj>aY<#;84TaeKYVA4EgOJA+{ZUw_uX)ztKmlb!1W!_5&y3OaWdF$}lCZXe z&2y>5nzLQ-BEYoqI6i5-nTL#Q9hx15jMOYwVnB?8w<4iN?GG+$+{to8U)RodEV;69 zHMjP_q$gd6wn44SRQ}Wd5Gm2aG%0F~Wsn&DQblk$kP~Qd!PYsL*9^(TnVe_q1ATs9 zH9qj=O-ALj0-2-}R=Lx@r|e+8#kl_i*vYJowI zsUBZGBq8bbouwoKF}FpZTuHi&IGI?2U6~oyCAlhkPVbbqvINh+F7F3ii9;sLS(vB* zCc9R9m`L>IVa%;YLPgr!2Utasd>J~ze1pveY{B1q;PL&jNvmIB#?rL2SM;7w&kmJF zyD>*Y`#gFL&N6OeQdDrTgCIn4LzAH~HYl{KHI-S>)JtOA2`Zg-3ibULG}*5YrPD4v z07rxVZKq7~KZsD2vUk;_uz-;47IU%*LuG@5j^7a^AM^$FJp-8=dUzeYoyIE!@$0=D zlkpZ=8R1C`92>)TC2Hdzj#yfU>jO{GP1I&so{=e zgrEWJ{opjIspdv!eojjK;IaH{eWD6vnMJ`S0aoj6p5`-cy7f7&h82dfhZi%q1Mav? z4fiNIXADIBPTplp7;|lEOIlW=J*t_FyoMB4l&TC1hc#YSRj2%mDW7>wuzhQs8yB9p zr6RM#5IYa*h^m4w8@>wME%H`<9xDPLYL&{ISBp(IyCyB^kFIZf8(MQ&`>7UWA;zb; zUv`7Na&bi-DBZR67Z!TjOSLmpH9T?zhVSh56Y98ixs>O1vWar&T8)XDXS5VVFflk; z)_ycOYKK?1<(w4IXa>2>(8*_699kezR9Chl(WhZc>rr7t=5Q+(XHmr7XwsSWIxVZ- zUtLV%;(%wQcvBVCb!fk~?UJ$kqKdmD${++k{G}VJwz2N!-=Q~;g%8a!cyU@g;v}np z`Q_F!F@7jUma zVc!BYGXtK~OkdBX@u}}es;IASmm`FEj)8yHM_@%1G(deNWsZUl!3~A6$*~~V%VqrC zk^11ncwh@`TvXOIp+#?L7vsQh!dO(v%`Si?NyeWi6u(kXY-v1ScP6os2KgzbI2lNF znBWh{7LIu{2D9(?JC$$X&=7FI(r&^1B;A92gwCyA*SNsr7N6wwSYBYMCncG2Fw>y&5_v(9E%)LJhCcW00%bMPuks$=In! z8;)|>Km$w@(_8m~3dD9Bg%7UBwI5uJT`neYq_ek!w{zD@Z>Y*(0gP!KkNo$ES>$yq zrwoo?5A-T3w3z6Iim1Wqm-KORI-hadr1}sIZ5mwwkYH>jUs^mSy@kPr$t+7KJvK2- z>h$Ka`<^LJe?7a&MHxOxur#2CQ)U9C<%pjl%qU&Hvhk;hAG~^ULRAZ~7YQz&?F8Li zPdbL~i*@=yip{rg=1TEN#4i-f`F7>gSEGY`PaVnrgqJp(;ZQ7BSv#VSUT_}^A03P} z;Q4#xme8_uJ8W&c$Sltvf(O_MGGW)}f!YoCG2vVYS`5j{8BI4OazJtB#J=uAgRVdN zTHF4OgQ(MaKhJYp@RQaXm%cQ2c1w!AyVTHB$;0PxdPDUVmI;q3=g)Px(`@mLZkzK; zxD>aP;v@5o;H;Ay9}i*e)B09vrjPT;k&umJ0jH|8JF94{*)W6?DASAy%}i14mhrWZ z!9=K3s6@U0AQbPx+HQB}IGxhdl7Q=je-IoK%edutdcpBGv9jhi+gvd&f&vrsnCmTg z%;pxZ33W+asFl6h5*_u}1oUw~lBa01gU}V^rgwvprktg(Wyuwu9H;AM(B;rV+2HM` zhF+f1*IeiHc2Zh9^=^B0uFdDXcRe38HA*-p+UoTFuJT?8jnNlJfw$!BN_Q3&P2sh} zMF+@E0o;y40+&gEJz`y=3uJX&lbd1s%UnLLA{!mt=rtWK?8ivp%SU%QJ_$+g;HrtO z%~zC7$x#lY_Ud&GogQ^|SxpB4VA`+%gQ%WB!nl#*VTDwP8OSRVl) z1@p)GvHeJ(ZB+`;Ygs$mfnKalll*6IIFoU~II+5pR-q=5ly32`p4sL|q#I)dig1EH z#qtV*gdU)z%{}ZG^wLLlpP??m9A~F8Izr;(GwhF$Qw>x+(5B*yW3z4B174GDlOVW` zc-nd}XC@}GeuJ_NC%3veo3;Q8VkiWX<_U)jIillbm{z3`#U+SdPSaj5irT$O4$6;2 zb0M31b_R6#^BcRrKPq{}jTtAM6#0Qy^%hfX-So9JHOJ}K^^!hqOZSu|Ipb~h%ZpQO zT;FHUkPqcBJ{n;O!7z&CaI@^M^kWXGltYXC=Q;sVH-8%fQa_J;X35Km`t#7cAMeCo z6{U;xMb*us$91G9kj*D0Iv{X_WghEH-u!x9;5%KJCM)>5?7|FXdrp)9i(6mU+ z{_EI4FVI8{so{X`;^U;?Bb^|?oRf~vf_WRsdBIQN64fTbdcDg-W-uLyfpl|VKOC(& z;{z1#>g!EXqcAYt#Ef4p4Q=o;u`~?P4Mu+MMh2UqJDYEwi`P4 z&{7pUIve3HX1R7@Y{bIan(mF`pF49jd1rU@yt-7V%gdEpa&@4C9mj)Tf;73YMf4Bf z5{l9|XkktFtlzJoQ-Tw60C9TNvC(X~+_<{RaX8}B&P##O7*hI`|lX zo?6zx0rogCTt)Hxr-2-@eb~fFko$5z|DVeq2LPCmzKv4&#mxQeQ45g#(;ayfQz0Ea z3)H6M-{6fkrs?Wa&*?|okxo@QKQd3f0 zCQK{nbU!rVvc`F&!jwY?{{w*e->JU;3itibgC_mOuhz2CJ!(OlNpGBr%%fLr`I_)o z6{A)lsk(}YV&QnXEA#HbyRTEsFI|sy8d`;?F%Ic4DLi+|4J?oZ$%W+Z@a^x_IaHbe zG)OvgWkm?&UkDJNwp{)xVC0M+P>t^&#C}fJhhRo>yWHhOOoO+8vD`Mt)ZZ>x^<9Y^#;K&w$vv>+qs)Xm$gp5UUT8JdBbL7= z4COstyx%)0jjtxscD!IWErjxwrzy_21d^f%!^;)>rr2(0Yo%Y92nyJ(o}N>z81%_1 z$$W1jx_k~u>*|oRJZ%iv2(sc zPwx-IM|)4f$2(u6zluA>AKNC%U2|At$U7~amWp7mp+NhIQ8&xUclrlGe|hQ5T(Y$t z*7q}QlnFF3dkP>}nAZiM3__dn3`KhsqUGQl?l=?Gig`>%+k4u`l!It_8d3xJS*goj z`RDG`?|n-4v@U?}Ecc$(f=!F61v5``C}T&hwCcknpz6oq3y!u0K9YL+1rd{f5Z||f zx7V;~^=xXh3RrqhEpFDI4ue1Y_=}IBjr!IXIQ&U$s0v6cPKEZ7yI+l&A0s!)d`DUs z)6nO6n5Vk&DfPvO?|FPnXZHh6tE0xGC8wpNL>8l~`tl zxS7+0g?Tb1G#Q|k)Wylj5`>+JP;=1jC_^-^rI`6b6MHkQG#K=$HH4L<&55v>(|8nc zA(~^XVh5db;TwHfuIWflGnIYqPfHypY{qu7<}QwyN7VHJ%UjXTDX~%{=F@0xTrnU0 z`@m4`Vl?c9PRgYF+pJTd1-O#RH`@4IakiT6e2FUmt!R_xt#D4)1)HbkU~$G!gsh!K z7&m}{$yH5NF`mA5|A_`K!$MUfx~5Pk9;tWDv=8HIenpb;6>+Tn0L^?_?H=_~71u%6 zHCRx&Z~nDAR{elA9UIEDffnacpCz9TQDr0QL83+9f{+u2eK7Dh#;cl|7o+j>Elr$* z*P?XXg7Ow)tHZInTY(H>REf3KF|b z&+gCm$feQUa!&mDL#{tAC#x8t`9~lKG`p!q1YrL$$t>M zmvPw?&mrWJQN|0_x}k~i+^f3kkUFi~ z(uTymzVrSetUY-loC1|s7z(U+2{v2L&j{R>4u^&h8@d=v$+FP~nnYUT22NcrC1%Gk z8qI7;RbD&~9!|8hD$XQ7RTSP>vO{#MoB$Fuz1Y*pkzSuPHVjh{Dq0nr<~C_WQ&+jl z6P~=*o5j|wkb(-Tp{L$5(O*l&zB~fb%?aWIVvfqbP5+KmvvXkC*>lV>lNDP9Bl)^l z+?H4z&|=1>lo4`RXW2-;(8(&Z1RR_|9Yhku5`l&ab1x2S@mkY!Vo5$mzmTCaEpG9V z=`!)!Z&FP~tMig0A-m&6PNsDvmr1*YJi)@O zQSW%uj$I`xgaN;`gU4E1W>GBG8b{VwEVWZ^pD^|Yvtmv1yt;a<1gRh)t1zHOQfI=M zWDGU2B$4vmtz2O8+s&BIM6HiaUQ>q3kL>mC=O~(zEyFQN%h-D(l%1a`KGvWN4+H<3 za;F;$ktvWmI(%GF9&K@-$nN1cQ~a^>*Kec9Zd^Z(JN0OR`t7%&heR4Ad+7cVj-{tx zL!xW%*jr3j74ScmPLkxMs~>$HmvIEr z^6RUM0%w>FjaV18F~eC{!VB>E5;0=369NToWv@GIeiX&86}QK#viQsq;S%)jBu|}P zlB?t2=fE@*!I?8{F(D@#CJKh~VhU+c}6B2%N-Dh-dd zZ|Dw0pKKP@D*ck3)W8#i+o4G%tyFg?kw45M5=K$RBjqziaAZp`NZUY|QXnr{EZCQV z9boL}$LE|`Cm7;h=-MvjR>ErZ$+ei(_fX=Vn}a!ofzQ#UTJIE-G?rc`-DvajeL~B{@V1YRxRM-{ndQR>qR2G_ zZvs-fye9iZ$=bH!ui%Q~*s|h=<;TZyi+BO;S=R!;_PCS)_}BonfX*E&yUOMvfwJoUXb>?y7s^DirGzcO#IfOI%Y*A>)!X|%|bN-meRKx#S z>ar^>t16`m&nXMj8=@}=`9mx@htXRtn@oxp;6y(>pv6UO;A7?PA2!gmEq_zMIlq1R z>#_>eb9kk~iGc19@h!q*U&Y+dU5JZvgyzRvoS$D(^~7RQqiMD`_B4hy$&X@Mp^#RE zj7~6KsIs1OK~AZTj!k8(k546jCq>l9S&&wqWd}~|mC8!~61z@L^hqU7Nx^roYMQu! zA2}AM3BqrG?2~XzjKt@3st}*WuijrtM230f zXph?NOVP>je9g)Z^)!J^G3kfidqo0UOr=s67@BdwtlqUL>sMfXQ3&hz9ILhL zU8CJg!ATr)gL?Yk^YyYR^D&&-$;IP^<-ex4i9LWE7}6x`=$y*puh_#7^ zt0edoZ+;<0`KaImZ}DhK24uXQ9*oZntbdf<5RMmq;87rL9zv@}DZLB*4o5p)iGQ8& z0}I50IHG^QB{#bSY)`wVag8~iqoI5*!$mvL%h+e}5n&iLCzBMJ?9X%(|3ks_5jvNT=h!Vc+t(7_Ham4f5ggoy zL6;_VcSeILjI#Ke%KR44-!5qM@#)OoiPV1J(SWyg)osZYH`{aag~va9tAlfLu+~xe zx)X{>enVYnO&`mqX;(~4DuEXQQbSf8%db!UOB$(^{?XvlZuR0_=L+v34}SQ;?Qa-S z$Bm=?vL5?eE@@>UZ$+e8rBF)0nwGR(^5duC=aA3Y-^#(y%1ToGS5=ZtMo@Vn*`aRy zi%GP2#ArIKXY^Rg`QJNf*G{jUU}2jE%vRZ?yy3Lwv~@NKRCR023=j7ewPP*};Q5$qVt1=10b2IBIa1Q8{t~^+*uwRS+8-qz{g`R)8GSpK=zc z3XInb`9S|WmE9ayLDSi zci1&KYzSCgLx#kY&5Q<}#V<|-Y{ z8MEimtjAPj_6T8fR}>p!zINk4(e(~e1R0zHE}hV70_jA*(-7S)pyhYF1yAS33w zhyzLUVK@q|J)#sRLaYM$iKvGgnmleNQXz=1j;P1EJ(VcA-jc1$d?t&kO8x6(@vBAr zx&3)o2;n?VUN&@ir>JR~i+6t%Di@VCryhzFaIIDk~DsUCol01D_(+C>aC345y z;k`~dgFwP?Ev!qGuv5X_V+|%MHlhv?NTZ2;*9+&+bqmm7gxXe>gMaUmRE5d(d&^R4 zz8AqCc%YT>^LjQ;d-3*}Sd}OEm}>OeFoO`3hjv?4wB*ZzK-hdvK0&$1J9rH=Rn(Dq zT)a!{S4&6wxE9r^aqe64o&VIpIjgMZ|2S6t?>*PB{4^@?+sjqf0uAk<>`7!d1p+2; zw%`4)yO}c!D%ljtSYYA3JzO9G^=6a>g(oHoL=BH9XisOevvW&-izYV{^Y-E*)2^y7 zGF|>bKw8N6hT+rhv5_9enBb>d6pvvJN};jZzUN?(A3+A_uiU&p^H|4}R5fgz5E*AM z|D7Vz!6qi^ATD~Bk!LojV?jR0FIzzV2XP7|-}hP|7;fJevMu89#8!p{()>dbn6Lyc z%+<26e7bM^ymMAR zDXqit#Qh~PAGD0CR9f1|P~%1h+U1rZjaZ~**|ljuLyf%yId+zATI08bRYNruzkd*^ zOhtPWQrP78LyTkKSAAQnOn5SWjbP!4Ze2RYY6;fl2bwhsrwg7alfS;chOXQX zK7f5vK}Ph-R-PzRQnA#TKo9`vH#TuzA~6U_p;6lLJjCOQuQY_m{)^zxVxd%lKo2Zq znZV~_QF)z{rvA`wO`dWY=zXE{IH zgOH8aF9uDAt*P2o@_%58mgdRZ*HJLvY2v0^XThib)Y@-M8vkA=v%AFAk)QwQ87Ld3 z-DY1HGeZ09FQ1$8_*!NDvy6;CKCoT=YSTU3V7kGgJ3|r4IHPuvck(MTC^M>AdzBRC zF5!Ts(!`VIoAb?ax?GhFk~u+6j(nBf^peQTM`Y}cKp9w(vaP5QOx3l7 z%(i_~BWOSd2M^8cA3^pH!Zu~kA#07NVBMX3wX1A>K)uSios;2iTFRvn-C?f{zcAJ~ zdjA;H`7JocH{brMsTwnIM9rD6`00UWNmBjy%HEHvlPugnZNu!>c1)Wr#-PpN`GkKE z=NOi?7ch5eciUul_cv){H($m(UI|4lUI>@J5~#P6%syZC4WIcis_W#Nbk^#O0Mgh( zk~1iZh~veGaN;$&-U~o?h;rVVP-X3qmvLLiPx=_2saUGW@Mif_&h-Krvc#~@$u1`v2(I=j`Mv`#todc4t{Np{W9yOkIju(zV3V98zLvo2TghW|Wbdu}m}ef6v-V zVB{FEZC}|^bR0f#wd-^dtc(QXvL;ho%XYP8gz0~R8#yhnO$bT?ixE#`UydH;^&!F0 z^B)XgB-`>jH%*GYS0G-D$>VeKs64lbC>_v$a~Kqpt2sIv@?^%@Gs5(EpO90_f1 zjyxU(NMcp}ni!2~cSpO#KwquQ7}EGm2o&w=z8#6^%?UP(^Zt>0t;edm=F^qyQ~7?~ z8TfFmCAzdGCf=x1HD5?sfbmx8L@w(#+dj*0bK3daKV@!;sz%L1v5(*7R=T`-INEML;T-uum}fG*PDE{*E8)xequ z2wZ$hEjI`{G4D42)u}JiMr;`la@aWjouO(~XpN zDS+8_%IcS-)Fm3o%2SpgZ0NMMt;#6Ny8NMY_~cfBsL#+QNj2pJ7s@?Vtvtqtwgp@E z6>?qo)cH5v{Yf<2A|&#$fZr%4TXWa6{!M`Ocw09{VKdXW62KY1?HKrJ}(ZVm6~_JA50OhHaQx3# z)aPc2Cl!KKk@(amqxj~eZq?J zNlpgm&r3H?*D%G7g^QUR1)8T8M1_wUbSncx*ffG9Oe-h)fr&4^mk%0tsav+Cc$Th- zYNg+WB3J$DHrPj$s5^Vp$ zJAZvqh2=FLEn#`>lOIm=Td^)H9oX*V?5&LK%rTTC?D$zl%F4LA7;>|}5|ulCH(Bf- z1T~JY>wyG<7r{s7TQaEnf)e!(aMpS{ zHjc377utamumvos_&EP)H{`YHzZ^T`x;89HEJLV{p@9642nLEE(l)t=!d-AT24ApW z-s!F}I?6AhFoP` zd6cz4wP@>+dC&#PW_zW{=W8E-MRDX(VCz2!3SEHuE_eU$e-Jspv6(8GYwQWgxKkH^ zHT%%$i5dKpIorunzYw;dYH`ih9%KB{-a|LP3@aEWZWj7b6Zz+b!&H9?6>KF8GH~8NC<{JZ?i_Uc^7wFCEzhpvd8ut51g8u@f{TUREH)3Ejmrt|V z??k2;AOR)yaG^x>Ry3C=M|O{sv9t6>0<)Qf^Ja8v1*KL>Na@lcITbgm*#F+>wPF{3 zaMW@6Et_igkN}cHjmFf#JeS;t(1?g}t;QBP8K+Yi|Evz4JxpmESC>|P!&GnSf zXXN;q6!!0?%cq_6dDn$Z=E||o;o^_|1o^vwj9)NVaD98ZdRko)RKy2!KrZV_XOw_N z>~jTWl*Dm8P8wnU$an9N9@a!HKE@i0ux@mCe+uxJ9Q9@gmpT_9hUAnBTDIE!a*eOt z1joOr7=obR_+$TO9+I!`t*#y(l?&NId&(28M?ChYBl*(D{1Xo{5v7dq$70Y&Pt)1i zE1%sdNq&C2L)mMPUs|By?(op&RQsGUp`W38R6u?uV;nM-i~nZj_Ud;jdvO?vSWcwc zbAklY+K}SLW(#JQt5rR(*4im8+^ss_Men<^XweQ}wZh z<8*!Z>}|=PvGDHtzTqX7bMz0gXez|9VkPAT< zT&eO!))$r=Gc?q<>8wviyMg!Wl(;@t@gj%VSZNuj<5GHV%$52t&9chx;HfwOf-_XfPGwRS`uG`6nA-My}J78+?@}08`4-A9JZe! zK13@5M!1{~3xCq$R5D`d3hghp6uu6O-Hw*z+ako9Lu=@^ii_g~hIwFh~V`c>hYm$LXFD=b7H3*vhn|Q`Ky=KqW26Q)SGl9p&XkQ*W*w zqPG3!F!Ki2{ytNuMW#W;fG;O@^Eve^(X2_{N&=xa)e&h8m5M~VAEi+Lxcd_oU zR>>~f+0&S=V?V}uesFunK70$-+UFlL!mupPEPntUTvT7zfBq8Z*7I4ntEMSsi2R<1 zx{~k|{L;6}?El@XypvT5|L%Skzf|Ew=K+(8Jh2+(RRp=5bjWls6RTG{X#!smXq9YK zP5Re^IOHP{mUow#k$d2_2E?ii?Y_MA9c>}b%MxaOI$?m|_v_pIEyH?tUpo2bN@e3@kl7eaEmrAblL2NaXY`^*d zG)xG}ODfpoVmTwL^({vyk}htzMS$ev4U^8H^GE1!qUF#|;!saj=@iHJusLM2WhKWO zQ+qRRtIC4y5u1YS*$)5Q(OA=-eQiD_n05`KFX-su2Fsl=D#&;9&j&`lr1Z%Had`czE)}h+x^H~fF zq}-Gnb17|PhTO2^_f8DGjYzDwR3Hwa+xMUkJ`>4_!L7huQI?sD@dO?051Qg$zwa`z zt@tzpzf+tv7w+HF0TM{sNUhM~MpFGB#Y!Ay*@FEV#=hFvU6xk{LBb&jR`7dWlJpzLQ(=g+qYQ8b-@s>hcaU2Sp{;3MFjIt`1#Cz&yK1*9C*Hx9}50frDFvT(6 zkbrb_^c_IbpP+BRdq(^)0heXp1Z}uBU&tz6Ij zQ_QV@cX;t+;?TrK=!7(lQlpoP$pZ39^TJm#XiCCkWZSY4^?yVNMs zMwwI$!XBh)0F3z}cf$G%y8D`^HS-$b;pN$@F?3hvjmWY|V22#L0F}w+RGi~=U8cgG z8Z$1{*_rJvUCZJrdd9`1wx#IPoQu8MmuZ5UQ+tT=yru@w-K=L}I#ZBv)A{JarwbPb z7X;^@o5mF=rFPP7S0~USF3YAaG|l0CvpAB;k{0AoK8zG;kh&k1;8;Y|Z-=;E3n6Rv z`ZSTMq*q?dlq(3h*6^P+Wzs2*lypTnN(GUebVYE&O;ymMh@wd0>N!|6_j}ju9-mrz zWik%`T-PEy5g8(35$G_3BUSy{-Ji27g+3<(L~D^soT0$uTE)wlVG@*Jnv%N$Sj87g z$&Cmbl6j)9j*BX^C~$rs9>4;?FsKv4g^k+&aFJQi5K(pyjg=kMHzPhH z6d-nMZGP>)<@c1y^D&4Ei>+-f{K4_1cv$qM|{u zH*_O4`n20UkJ;nlncn;OYo)nlTl`@8Nac#cQB@%a)xr=JC6y}8J9Ret^xUF5i`ZM! zn}iP|Ka?$wFI(B>E)b5qeUX@cX;9Ej?=T>zJbNeQnq_tPyQr3*!I9YZHpDE5@3vOV zdb|lK{Od^7;olJhyzBD9u{HnjXpJmi{o^DBI~?GFeY*Z!i4(EPcf0t|plnV*HgM;m zynWhin)O@$0<6eqmorqB@K-uFrIREgtx}3@BJ62Tz}_-WL!xz%igx|8>6w~EkJuu_ zeKm_mNO>0F79fDZMb5yMgeHt?zA6&~Ot9!)Z@5D1pL^yJU=7hU?UgH*?5Z0hdus`g z2c)^dJXWp_^HE&0@|NnQPk8QBDb+^QVdqk}A=6bdn6Ol+4tle3n#XN^#*`G@=5sv` zheln*y+M1E*d#l&Bi7xnxlhZN5rnK}l=I|C&}Wh_#Jv7ON2Bw=iI)|5dc20Ze(UuH zlu|#ZK)$wCde{@Jbh4ETL(rEeEXlcvlZm!BJJ3kro;{hz;M>#-RxT)3lBev;12Z5{ zBLAS=rhL%X(->ack)i+ifvoL(}bs*$}OOcNyze3NFrHl<%6&> z3HuTNQ6OmQwePl0yz6xd64wqCKQvFsT`_)GjE?&P?Nth&@UQ(rjD z-qKwXF-(gLn6~M3x%8>FFl1OC{>g^`^4bL%SRxtw~{aZi^!Z9BEWoBIIv z+DrZ$$U&c^o5sCe6)MLoHku+-RW7f;MmL<22>l+0=6?GfH73Mdt=CHI>7iC-h_;RV z()mW!iinDJ(*KPx!FrsvbFko2ch|#<*f=Ys_*d$*w9bN*V%8!RqD4xkhWm$1zWojx zx0EHoI4e&Kdd4SD1ZIVuF<6M54adp5XJslFFH!Ay_lp-BM1+8xIhE`qVVv#HmhDnv zrgueo&YP%jrQO!vEo{oYt{jw|AUXVcT{^-yL8cZ`djc~CGknd-rSR{I8dJ(o?{bT& zzJGSnjiLZBgd-Bzr;xl7*aLg_<~yLSBD}+o{WadI8@`jiy^L<18)lD8{&I4kiwLjE zh{zfh1xBAHZnQ*)&{QGE4F0$X3i1yx%OMv zB1}{ri~j_SX~doEkB{clT|(neuY~YaEUsIm&odn(O3+R~hoL#pGnc+kzu=eqG*uT+ zT|)W5SkH829ocd-ra2^{DR=9%wNzA`*=NA?(T0{{XA#{rE{Y8U;-m9;_%){YfVh2lV`NVMD}BgLL(TMATg_)9@;`-K|-B_XlX-6DWWBVJ%WkP zvE%1*s~{0I@1Be|Op8T2&-B%RTaq{I0Ol=#vgJqp$=0Cg@gdQIZ$J$l%E&eJdotQb z1?Fk!l z%F2t1sm!JizcunYfVU5D_kMG+RDQ9LxPV*uH!hRR2Z7F#-uu_KMreE-oE6_>i{%WG z$&X)Zga>x$e3Es)C^pE%4#T>F(;x%qx?P_o#nByd8_w?N@@~q+{=ZbX)bInAmpInD za0=;cOnMAy;n*bid~#&2m8qpfJ6~ugRZt(8;RlXax|zPsc%TuGi=(UG6PF#*^>^|T z#7IAF`A%nNVXO6^{5c1knMGaG_?K(+4s`a02y{txJT<9Lui19?-?0TQaX;aubSwfl zF47j{9xP%cq~u=vl02@e9h=SNTLLQgUY&J`4(4hz<1RAjN;KkBCG!~Cf{Q1MRms!}hkMUkKToOZ!%jq$mzN7!nK%x}IGojM8A^y_V@7ugc(6x( z@d})+7RET1e@k&G&?XGstMrmEeN{QSBy? zqh^SWg>%MU?IM+Tl6Ysm0+PDiRM>Olj_T?P$aP*PnlKkm{l<Q+C5@wKd(jcB0 zScFMuGr3xg3uY|1HbVPUeNBTrx`d8)wT4mt@i8-hCM0VVY^2mbr=XNMk0A9RpZUG6 z_)~|O2-@z=)UnyF8P_{AY>%KkVA6NqmN4S0=87L`*0bLl=s}z@Vb!mz)|8-OA%Iv+y z+kd|760cgv{VIJ1-J#Z5?5IYx#k#$z-#jBw5Tdp&y+mQ3kvy4hHD}2xQA+NrtsN`D ztC*5XL*@FN9N`O{s#t-+E2moJiqg5?@)^`GDRIkVclW*5RD5OL%VfmEH-yN@jhlFT9e>QY7-LxQzQ{NMrU%K~G zqZV>Y0&qH#o?P4`Ls441hf`#8meUyU*ju5pMiU$&f$Dy?B+>t%I22~_kN;NpYZ^Ft z!1e_eSEt-E%}{_j$^q+xj8AckF}@q>`HUHf8`dEOeDv5fC@||F^jH=g$ZWIFQ{~zC zYNna<*X}33wK|{Nn9((=Hq}~#BJwFm0Nw<3SE(mf)ujwfy>?@A+QOFSVTZ4@{?T&H4C6GCS~-~OD6w$HzFr!{_HRAGZwvo}qV3kc zW*~e<@VIz zJr*kCE~g0XkuEnV$<4COTZbW23nD*ZM!Svgi2;d~Zd4XFv)Q(}RgbRnxJIL-ei!jT za_uapq{B@!yK4Q~&`R%6^V)nDR*?dWM0f0joxg(U;<<~s`HMIAA}#`QtE9mJ0{(Kn z%MTei-OHb|TFDQ8`*$3GAEIxCOHyxzDj2S%O$t4BDyWe8Tsp}s+EJ^1>uQm20?*fW z>@{*ukOD5de)(oXJS0935rPJ_^68^y{ZwL{-}$Vmis;^`KdjuMq;Oq z49rZ4$6q>HNr|e%y8Fm=wHW8WbZZfM8|^tzS@tgY7DNvrm};*HkYv-IQZT9dQ@Onq zFQ*E)C4=fR!;B$0V_aw6c>?F~CcODWJ{UcLwoL#m_Dm_Etz*0wKKGbEZ*fsVoTb0C z5E}kJr~y|))0-$m-y}W3=B(9|x`*rV0@Ll|7JFe2IbtQd;%B=B zvl=D!C?#OzN7P6$2fea6vgzm~BdHdgv!+~~U=YbmjnTCqnfzo-wBsLnlE1QI>EsB1 z49pByklu8lS;eJV(FdBDRD)7gEsbR4a%>Zh?eBhkw2lxX2hlvX1fUHE##Zd`ruQkL z`~GH81xJoB62QVB;jC$;s@|$zp(n=0C0d5adnx4!Imb$ui(q~S1P80Z z|BXG?%gm|mgKLA)>$X1WjWSr5I}4^*4cA|3nmRLf!kE*k?-;$jcrHBX{IWm zyEMgs_>snVG;wRExnP{?O6n3j@L4+y@c~9<+7UMV(Q3!Iy7?c^6eG(rX?7C4FThH|}8q@tw(88)Yzhuv@mbQo8#2ws=u5Us-KK;`Q=hx2S zxxw?iyy&tW^u}}4aXuG6@zo_|tZDr}DC={+x@}!*dvPN0Z5$Xo3=5u{mRB-m9wXfk z<}+-hVzAPZ&GDAD^pHS=6HZ)0=!uS1k6NFg2f_6ff?3eSEW*7-sPR#(h!=*{T}$*N z7bqQjdq=^oLw*S>U14Yi#&MG^O5aUPKULC{f3!B&+pOIywwQBm%vsS6Bx1dgfAR?MRwJ~RwTVJdvd47E#% z;o1Wz5~#sV(oN9*CB}^XZ7X?l(O_po#M{s!E=DmM!!o6}C_KDaq>}dNrGEio+M<2@ z#w_xzwwFy6H}BqJXxIE;Hb#}^)N_Eu!4aT|uoRJvOcwFOPQ!;6GDAjX^lHL)TG?Ff zMa>F~>H?92I1(i+-z?2vvNKy_HVd~Y2Rxy7@$OuZ>|svBT%(g3_0X|3gwSOks9}kUWxwgM?*?((Qe*uTcLe7#{a+WMH8Ryx z&GB%m!V;q^FcP;$3xHyVGgf|;+?{uLFK~iwG}Bv}4sh?C-|-}Tqs)p#{ZQ%sBu-)p z>UAW8WKWt_59(A`vu7qLN73N37tw6(8H7XmQNg@z&J#M}X9?@^os=Y7KqVV_rgUg; z?uzna1G$~)V#pdFu@p811Qba`-b=iwPo9&Q;4IRcEhm)GrtwHG1{uZ-_~5IHZRe&q_cmWJ0*IUH!n2x}RW z4Q_C&E>2KO>+tMd{8I6?#j$PUWY%kzkkvZpe3JT`_7~IMU_?Q58o;j+UMkV6cb8_! zrOOI>kMycy)2-Vgz9mjccgpMrM981f{1IQt zjE?=)&h0SuduOrPvQ5T^24-`Bf+f)6fEnD6OaC?0bAN7mO4u>?J%ZWiTQ1Vp{rCG5 z8&c*bm48sWp}P7#v4-n^R{_a;kq6U!U@Xef8b zLch!&8z0Ez{Z@X`YH)0@^L|yH25jFc%E`Nb9MJIqUj98j6J_UqcE5%=B`F{eHf|+$ zc24RcL1*rtrf>2mGq@H>^>dHHf1~^M4@#s~%Tn?JCeX52B)|0L(rnKF+e-$2(QMSF z?%OVAXoa4gd1-9w1m)*c?8!vnH*Y>i(~1H$ltf*xcM$TFOvqX(?z#$PU9b9tns;nB z&*+Yxx)ZFF_~e4xDBL`N1tL@Ms|hbH!81YeNHHWSE7uo>74XFpb3v;P z>%UEjJOGE8u2XXBdFBcw>NaUiO(SI|PJD|*W42Rh$bzmF0qM?wX^4d#8x=Zg;h}es z^KJE<+MRDC{PTJ-{>FJ^P9!}EE_3?pK$yr?gSwn( zhe(o}bcCMv@aLmI=hWdkxKx15BM7WQ6Lb(UzgH zajN1%#noq@65Lb1>u*5%4BU>U45~#@?w6bv@1zKi|Ft& zoZyHBTAs5@Mi&`Z)OKZ=LMVTaT#n#kQa#QZKNEk8<}5QIyz`t(*_j?I&)jDJL-3kB z-e1^~Aj+<(+iBJN3)m7U>Wjf0-;>PvM7Dk*OahRDoey{mm9N9(iS96!Qbk1n9PF7m#@`sn}5H6-^rSW8ws-60f zMplj<6(h2Wb+HH(Wy&Bt%q0E(((;B) zsb_=Ozbgai-)BuUBJr8MY(kwWV?KqpF`Q>4IWe0@seht8Y7C^2X?Zgz9HrH8R z;QZN4rs~h@MxRP`k0ICGm+lx|V)me1KNaW$in|pKI=NEQt$O(IxdUfnIAf=KYH*^4 z^&%?P(PrB~n9jbmp>RzLYqEM(C!T75Ksj4*U)1HEv(?bbUK0ixAGTgl|KI%wYir-FY4NaW6EPHY6w8(!J--APiA<255&a(W$9sXcF4A5 z=8~0x2O^LiAX=WIl;)K3nO5?_FOGPgN2iDYw2&qWI6p^2k$DheLGeG{lEo8Nm|E_X zSOt~szJLr|sJ^Kt1+w?Rtus00S}^*i<$4hpzpv0Wb4(yR6jU53Pri`qS$n=nJ(mX$j{HsDdN09T17sU z8>*bhdGXn9^{}WDbS*5~E8yP{Q(a+cIQMMdfuD7As$J`wmJg0TD|E%1{iL(*ZplG2 zL5yWvEk&`8W5wYg(?9(t48gXp)fh};7nbf(wJKj2^MRhCFcbI(RsMoDN}5egcYnHD zSREekdVN)l(X55-*%t`bPqhWN3}H*_w5tG{4DPnJrL7X>6i%0@W+*pc?u7LSC3om} z&6ut|HpT>-AM6o|Qu)&h4hUkBjECm8B)*{DD3UuNHCJL0E^oOHY)LA&YhFLPxpMY3 zes(KnW@yKsUB#K^(;yy9RTwgDNNJtCc@_xZOpG~liTKq;< z*Fe&-&1lxg0M59>B(^0#V|ON(dYS5>&|*{JnI!xl5oA!RIlc2fu+(&5qFcWh|Uw`0V$6)Wmi#=(@-_uTY? zfpOF^0kZN~B8OT>%OhE-Mtlvxo{7!bcdW9VM4X$Xl_CWtGEp&469(&iZo-Qhw*O;4 zGgzSTq*+z(0=as7**O8lTs~ zI%+|W`KH=yRn|99>0GK#dK54_ouzRR@F_jH2O?^p;88EX{K+--ykq|H5`wl&u!KatS(lTFBexg z53YDO%I*$W-zXvUT5r(S3}F6sUvYJZ+<_mMtL9fD-cj&DY`>q}ZE?@tZUjGg;R3`6 zd_}4Qs*`h{TITigy9p>;W)uJFf;Vf-3TjD7K55N)zr{|hG?ilhyd}CMZ#w6+iFxsa z#`^~q4E2a&;*?4HH;yAZ%6b%A&-|Ldm3OnbP7=?Lo}VoS;gpvb?k>#KLXAH{7?8nc zKLI}cbF9fQwU&wg_hox0wGNn@Dakz6+o$>dL3*on2`T{PRzc6WPM0Bq>PgM-@kn1k z)aF|hT5_S-RbBD*??uSNRjAb-OxU1B*9x^^Wcj}m(x&Ld9PbD`X_y|(mBI4TNG;^1 zHMXz#sT%^%B(WGBL5abjbk}OAoH831<5bVj86wCep%Gd3TWV-n?{br?~5&W zHKzd`>s!sbq@hSHyt>>9CZ4&3S`6O22;Re0D(bH-9^bYSy7c3Nq$GMcpr|Dr~OeFv#85~M)!fs^g6wK%AAAXn0T-ZXgO2>D5kXif4pbrkSwtw zbl@T!$f^@Y#E7L+OlrW(E!dfo{P1E6UYQn0997F)W(#LR|Buk@f5q+nKcleLRb(=M zAIfupD|~Ho5o+vhfuMiaaDjxiylU)wR=vx+Ds5Gq+ATC1%_m{u`R~O^3@NN9cx7I% z2_D=#2q7}tGL#?5XA;w+zH~{Q&N<=n+154t_CwH~Z9UF2Rm!We;wN2_<1_J&l@$EG@$k6I!ftJBLxsy1XJ>wOLrW|FZmmcMn0XM_hb8MDSipaz> zmHhNcR@TGSCb8e$?kuRio!gooy(u+$T`!4*kZ^*Qlv%EbI^>XA`yL9nx+1y7;dM|o zI;w5-l+H91z&mO>4;)c2DVc7ftH^LFp>+-TVHs3fY@niy%{|$RL|Tp(bpmz!cI5I* zm+613CG0+`bSiYo%2WZI-M@?CPh%#Ant2z5vhp0H#^=xy2qCzSaG|V$k zKqFz+>v2_06ZI6hL+dh^0a*B=R+5=Hei4AIydT1V$(Ofp|(L_G99!J@g@+6+R zfpkff%WyXycYL7ogtDc=4XoA>6ss8f*Ng4pPMWaVD!01hf^V)R$^e&9Z-X=bOP|Kk zPVCP!o+5zSfcYtJ-Bd}+AX2vbHbZjd+(x${f!r2vHpejvU@d=k0G_|-)I9-LS82iyereBhhWI7Gh>I)#gN0nz*(p3|P6GY*GK3wZMbHFM^lh%dsu?0X$L;w-T94Smgwy7e#Q z>nT%ob>||T;03$wwv_^x$b#^d%Lq$P(+j;ppjO^|Q?08X-?oxhdI!4$Ey(?4l2YHPy4Y0Qhmogs%yrsA zY`a9>2 z*l%{VzaoeP>NwfE>9*dfa!Wy_TS(3@&*(+)<1+0>_eQlF)Dr*x@qQ)n!G#+Y1zoKi zi6(g2>f=qg>l^B;6E#tp_WyWQ^YI4VR2n)pER`5})#f45NOaTmOX!E)$5B5mcTY&) zadp!mGy$W^gfpr6-^8O|K@Gm@e?r#Yt9+f}v=U`i3!^Hiy`-3+Gtp$Z+CtRG2^BGr zU%b1`Z-sPd{+KVL$^XJU`cqM{kwOiWi;|KNxBGNd&6J~1_zRbY{e|#`xp-1`&RvO8 z!QkgcMwTzj?!J&2<6B6a|7EdKjpSCLw{OJx_AfSn)RQ#s2jHu&dph68`Ean-Ig~>e z=`aRwP_sNWB*cjc%m$xKtZk5293;#dvlv;D`|?P){#yQ5idLLX2>d(O!x(QDd&BrBI+Oplc~DMwXNy-C%uia(F0L&tkNBLF>B*ay&bdz1XXm zNZ_I>s<-g^r`2DpSu(a~);5kDV{+Q~!%jUs_j|18Abc;pH^t4e9*la$9($%!cfU=L zY5W;z-~J?NCGLm4P_Ge~Fp_mf-E!~bLYHia>1U+Ofo$!TwDi7z%D2?&F&t6LMED!* zsZDCCsPg6~r8cz|^{*|;%F#ngD)g5>4NRQsnV!}Bdna37zW?PSAvBANEj~GT?=M=< zzVzf9q^+okX{Ua_>5u4qefu&<(;&Pj$7fWaObZGEJBW4>W{RDXNI3&_(b!#bw?FjK z5N`jb^K7n8LAJ`Cn)&@?VR%2MeVhl5dW6%7(Z8|1aySocuQ}`wjNjK3s)2J!Rj7AH z9RNxZ~WiX?ww~D_+$3y8u%x!1x^lgXqf_<~-FeBF5*YmlS2+=+^nuzjF?T zmfBg{!SR%#6cgKdW)0_>!L0^ouZ?-AqnI)P|4+}Gg%%ca-fkv3Zww^?5<_eh%3!gp z^Lc?!&~I!Fv80!Bfy%9pjb#f*Zm=iBVC*UgJ1#j=8B7W#@0L|cDh^?t5{y;;Fx;bq z>Gq~?)Iyp4T6_b76U-C784mr0#)xIj4-VQ`ckSZ0xUNxdpOd!Edt-SlFH5?5 ziCf%YXoVVGCvRvUYm93+;bgDb8f`NP;wZ&DA`VTxxUMsu#i4;hn5maHhrMA7C%xDw z9gxDiOOxFr5o$`Yhq=pN>-TWkgmX*&8?WcatdSdo+hMu2{5*_{?_hciSoEsI-ZM1M zZmIrakhjunKu>p3-QvbkR*(C9G4ZS_B5D9PuUUihM@P{#_o)sjKWk;yDm4UYOd z_GeQ3goa}gZNntUXgd4#Q1zj_mM@ICxV77x;uU8J0yU)Lm!bQVo0~a9=!@6YQ&a{o z+7ABnVW_PT<{jxV1gdE|7GO1_yrq4PwL-VXedCZdQSr=Ylgni_3hXnl%L-tUg(WkF_wn-Yk6xh5Z@1IQGMk zh5s=DHhmh_M2s4JYmAx)XR3_lYuYU0QzxV~oJ$gd9(_&uM1pJWyOJBq zfF;^IGRj!--3`~x(v+ugM^`AT18IdYuNpL^>kJH6AMEVtGY>yRcz3|UlR#a|iwqH4 z#&!|VuIPm&Phl1v-Rhw)+3Gpylp=Es2XO-%w*rkFRuJeI!M`^TW7fiLVUwah6lr_9 zd=99pg5pqK>~1N}kHja?f7Lo>PyPgb$SZPwcy9I8{NS>(x@UA_XlZXsA|4wMPzS2o z$V*I89oH%mup@#Itfl^(AAb5_Ubfc6gD2I9Af8QfIZCnRSF58F%kJ1u{GMJfRQlzs zXN6w3u7^f&5)Mq`^8;!En;9-LFwPCmQI>|y9gDfmIR(qrow}lhoD%!*U2yvH7yyvs zoD#-qhb`Cn|K64Un;z%|6$?G=eXSeuUMVp=m6&9=U0$N*Eg^uDSH516R|0AYW(=B{I#ykT&oZ76a2F) zRC4b#{|k--Y=A>~a{<_~hE8`~^+VMRYT`EkxdHt3ByD8z!}Aj-)l(FwiQks3!W#(N z=!U5OC=U6n4G3ArKc|vvn-x5tQb!7kMqgULTB5tIJx=GW9 zuIpmRJ+ZkUQY1Be>u*x2gDjvQ(o`%PF>B$>3%{WGvVTfudoYyAWur0JzFU70^{S)Il zSCoI;g+1l}(oaenC&-OWuDIQZS%{KSa4zDDL{%$?0`5IiP$%^?FNt^%S&3j4Xkc*` zDIT5ONxDG4?uiccb*C{kK%Q#3fA5rxQvYn^>Z;Qk|2@>`w z{FW*r$!vb)T5g|gyXB!FEI_467t2N==~?4q`4JE11Ybp zgrnjcxXbAwUA_zA|KCscg9`~)x{5BzJV-0(ro*&mt{CP?uN~|~b;985WwTO|p{j>M zQK}80Xk$=k&OUhv!3_JXAM@PwEP;|31zFvE>n))>T0D17^)p(z2sC(D?QhjlQRSfU zuaX+upBF#P?gd-jFiaLqr+*0;e4u*U zw2b->3bd4P!XtHc^@2-VM&Jiwe}IzyNEdb5){>s(IyQfA5R`EsLtwn`^Yl=WkVnYU zotifO9+RGkjv2I7Ej-NlA)N%h{`P+FjZ|+eiK;U6$Q{xCXm>F!jZaNv%{aNlnj_2~ z1l8GgO4t z@$GFws5*>2xD%2+zhyOd;Rv}YMJOBTb7bpea#_8{P5=z$EY+np5PtsP$lYLDpH^~i zwq=6%;e+&P>k0HWX^AN-uA2CI*(N2Dr6z$zI)`zK_%wILBF=UMtHqUknZShX#3Nqg zL$P09zw_+Dk=~1u#FT9IfWjQX&8voDUj?ljbFrW+Ga914G1Ua zRcFOxlEMR0r2y4VjYcS8ayCQ0)p(Y)h*sd+$!26CON{dcF@n2*k&VAG1y>3>RxJsh zr2}zlnzJZhkz8(d^;?c7UQR6q+#r5L)abDaZBv-s6WprzDjI%~W9IkR9DD1P2=#;Y zA5`C3GzRo{or^5$TN*%~I4bVyDdXVRL67_|oho;5S+P$gjd`q0-;F6K7Yyne=tN|^ zNeIeFQ`%uNU>4WYha(L9(|NAvAG|8HLs?JsV{PB6cC*R!I_xkBk1y79iE?jyw9meU zTg7p;nh1p)$Fe$_CMN9Xc%>=o&)aRb3zG2>v~j8#CKO(nmc$tp%AdixVM#TUy$(dX zbIG~GBIjazdOV#OI_%HdT@i0|o*pjxL5pYFDaQ{TI9BjFcuRx_M41FqeAl%6oR*Fe z+OB!!o!k06I^3Fm*t)$^RF>k|ZksL>MuewL%?n?ouepJY7<{_Lp%*roxw5C|nB{Co zw>IsQy0l6SB>n|?NjchUW7ItH>S4tYvr{~JhX*n|2zK%&9ds^H0bx^YJJ;#(gGqMO z&4-E$4|8F`wC#%FwA^95`ytPE=A=s;XH|cNktNZ8Cc0K)-iLq{;~ZX9PK&~1OKMzF zNUj^T1WX_x0>F-@N?fsTZTL?VaGlq@Xxe3-AoW99jVRf04?@noxV*attg_vMR3^Pc zC|9c=qfcvA9Pctry1{6_XXp<&ob_9V7zxBbKg&*iZR~7qDyu@kRkg`v@dT|$c({>wLb>w8(K)p{x^|O%Hm{7O`tK7asgdEbRlsJhxc^pX6iwl3Ay$ z(%Q2%^0=eCC=dz9Ao^3|+T}m@OfZr5fD)o)x0}0iN+s@jny1_*ub7G)b3NXt7NGLX zlc^h-%$kns-cU|V+i5k%!Ac{7@DbJyL#*qIIl!$1>zD0z!}LM;QVZlX_n#j#SQXW$ z533bVh}`DTOH4R_5;-&u_=}@pI%SGS+FuKXbzX+{(mSuyswF5Q3{0}~+9r+;4XQju z!`H0CLdJJYf#$h_4w9f;pA^O}RU2h=WoUW%Ew?9ZRHbB;>dtq}el0~N@aGTMxU`y- zEYr`u`JS4^z#$xVq2AcJ%TY342oj>a_ePyle>f8AK=`=8*O697Y7qr628dVaP4G30 z+kZLUuVv|7RIM>rFJwqrwkt>=~RUCNs`rI-N`Dl${KGZ zBiPr3i-4oe{Uu^Ll+o>U@DbE0mM|FU&<|qSCWxODNcDJBKzN?fR6=Q7v|T!G=oGPH z!Jb!dpD#)y@99lIvvu<@1V!1~XY_TR(-m0e zdxwA@`)rde!?_o&wrz^SS#BryRiZ5~9+U*!KsWIPZC6V?^7vR0HL(}j++E{L_g=-6nHF6; zqKPk%&W+E-yGLt_%R5EX+eq^$p4dAa*&QcByyXKc9JMxO091YUieUG+O;AyBQU1RF zTYNc5B|mXP`lFyf&>f>OO@+$7tyl@}Jhfk+GvksMKa@o0P+^hOx z!CpUQ-ZA=vy_2)GJ!N47+3 zbKi(@RSVZXd|)UkyC>Hr&ec^qf6HKFjI)Q_ zVpk(OO3{$U!BFk|cbp>5mXsZIWU7x*DpT_}#Dxn%tdW5n4IF@^Mc69>0nJuv=P?1W znS;{6q!V9G4Ox695TmY)2&6H*bD};Jy%fds$`aQgT$3r!AeHI73UNOPGYY)YaYB-n zKHu)@2!Yq@uR5?kBHJOUy$PStP*M+0EPSxhB}v6btKnsl8>+rceS-Z{#Mdng3NX;< z-U3Pz;yp`sUb9`ua}N1=keUe#yWOxj}$_p`v_> z>x+ptGPSbMQZ%cX`1m2WYy{Js;u3?h%4qeMl(5K%t1=ptV<-nM#*rf6xA55UcG8dSZ+P>G*glX`J*ko48Gi+A z;faC64|5ZZU^qS51C9Dy6!d@u74_mNOiR5P^YUOM+73;uk*$|YHl}bQwUA%Az9QEk zBqih_Jjvt+D2HwJF)!GxmQz|jZ~^L)2rgN#`%K)u_tGZ!!^uAWgX#p<l+oI%!2B~GWb2M&_&t*zO3AWcwqI{cQtUfd~93`gkxNi|+={=_;T zeqfleW~)?X3DN&m%RyYG$>=%#4JGTWPSy2vlJI9PK4Fq&q@8Ajt_dbqxxh1L>|)+{ zttk-nMPJ84-b0-QGuJd_Gg0+~DrJ1C&x~yxbVNp`w=xztx;iRQyj2V6l5l;{!_m;$ z{jaGMu%w%mX$7ISY0EW7p_eSgw$%4a-ekF2R~4&+woLLevu$+_;z?=7-jid$G$yG} z8+sN3Tnh_z_OSCq_{w5pwsPx$J8z0vjQ#AVlzGgMVESmr+?7qtPHbwGKXBok1L)ma z=sVcP%@%hfXIY35lrKs0@<Uc-GIu5)>XmpaBw7gmYXM9c7v7uU=cvD{Agt9cNqur>qq#1|SEh zBV9XQ<4fkVjaUF}G8e#(>kD4St}opI7IyIv*rS@c^w+8%)`FuHv#h5zgXnB$fc-QEGfR<*Rg7nMX zlA*;^_~03`Y)XaY4q0)bq=HjzMW+m=K{f41x}l=@AakhIC&mtw|BJ7)42mOsw>%I6 z!QI{6gIjQScXuBgg1fszaCaF7cXziz0t^r|L4#-c@9w={?$%ay)qL&l>FT%7^PclN z7m-4968$h%HL^MWGX*`W3pA7g#i*hAWeo_+UCc^7Uz$a*NT%aGS~3e7AcaTNyFvFi zx<;xU6&+qOA*gN*6B5q##=|K_gFk(a`3gAP^(KuB?wGwHkkMW z@AvU{BFf{t{>3{$RYM7jZC9 zpy2OnUF3Ka2BKuH3>+c@bxKxPjyEqYL1$SHdM|X6|MzkT@(5 zO={Z0)*OX``vp^95$%crg;l+OLkE*ft?su@WJ01kOQHs8b_ADnj$;=Y{nxRcFej7}ytKay1&U44C{2 z2n&s__?qx-!aPvrqSd!Ia!ct^y1d(S6~i?`1WM;Z93RTI?FK&*F zm*Z7FzZ=_?>?`FiWp?qSeoS1F2t|x#TgD!K+fkOYV*i=RF30$&)r+4p`*Mq_nT6ao*Z zY-EeFAn-l}i|aw>i3<9p_RZ_Lta^q0a^^|J5YZXZRmidn_jk>L9J#2Dg0Z08vfk>3 zmPmZs%HQRq!=of>`+~)|8?59D0Q~9ZM7|+ADcj{Pl!p`6Lx}W4uIjnTq4wF{;T>ZJ zRkd9IptuMq3$wVjb2@&#Tx!Kap3)VUG*&F4wKPcIh<^%!tzuw9-tq@bjWT|r2nLj_ zw8t9Eq7BA_!xxTHmX(D&XdaS2!C#O3wCENn$BMin=rAg6!?i!HnF0Y;hh&`hyCY9H z6?lzsGnI zh>6jy)%Lsw*hAM$L(42k-lRIodkTI*ui%({jQY}Wzk=H<$+Kh&FDoSdh9~f}jD@J< zo;f7w^ssXH!@8SAcpI11cpvkNw@r{u;_8GqP)kuVj*Nr$WPS~eRMA+nPBffb5;R$I z%HXjrMc#dw^h4>7=62b(q6n_p;c)5RLdhPJPFB&flSA}%b-ye}mIE74(vLuE*2x=b zJ+IdB*r?vBNqNhj90s185L&b!%+DMtumOC}FPv{BWrLJ|UkNh_nllyqx7ZRU=k-@E zY5KNkhAGuobaN+_b3iB$k^-w)c$3hqH(H7mr*&TT+_Pxb;cop7D)M4$@N-r7~Fc*T1;G2OqeODUuzK zk$>zfL*l9t*QM{*2?bfWUSkb#UqQR+?9Q7bc#OX6;kYp$r&khHuGnB>@G&D%Vl*;5UTzTdyJzMZUI zf0$fw>hCH^jX-#(HQSd?>$&GM&CNcd?zVapt`T2n%K$8~q4Dk5%^z{u4pzjrma7uR zPFaiGA~s)>DVd2{EzS zD0f~-Hga}>Q`9ZLJjITdI>r;s!#0vRMpO;eGj4FSydIkKVoG2@zs;$Z<;V5=}j@D0kMu_!rrm#7nY_grTjRIUedxJ ztxVQNtr0jK>WdUHR5%1VVy<;1UF$abT(O3;&0F;Vu& z5X+~TncHb%LkN46>zm|-*-2M*SPR$9}`Y*C#9#(x=& zC{T8u8;EVoZRE!`6dw1bA2=a+-bZY{da{Cpo}E0f5n1YA&%D8*di_VcxIb^Q*`mX2q|BisBm z%$jZ)r4>7yS`k;M$-``|*!yx9E-7Ysr*4CZ(p-WlXXD2s_{&i$H@q`1FLqC+piRHf zb?l}&JR&RC=FzWG-TtT_qC4y!WPrt&=3FaSOT^zM%*xYp3vFK1*KmYbn(arsVIT0r zj7rme7QdP?!FR-P`XEz4ddU{YuxoS^I|8?*&Jaaprm|TR5}8#|4)j%R9pz?j2H$(O z5%Qr*j8Jb%~pID#MtKMMfv2G$yg-N%Vuaroq+EAC+(ru4$9~7 zA5>u}X>ZRl#yrJGGw1hHu~_}Xw&x#rV@Aj^B~J{?o6H$v^*pXv0w7OP*qdju?*VZgQpNgw0a!XPh@=uu<6hCeTY^W{-W@KQXqdCU& zt$0GNKt6dI`_HhN3j4~k<|jGq;3wGT>?=4};bN}?nip`*G9W_VHBQ72QE04*719WS{~jp^a}GeUX*NBvA2IOJ?uj9teVJ`)@p%JqFy5}4y6CPE*U`>=ay8X zc9mvlyn?YSyprV9(q%0)8OpyDOUBGRP3NaS4W_%#O@@B=>yb8$y*^b3F@>aN zw^>eLR(tv1yHj#ksJ|}8rsVjIralb8U^<5g*P@!b0F<=Fka70V54z)TBr>s>`euf1 zCdIirp>e5te=geR0{eHmgc4#u=iigM_tlf7oVG%a@A`DgHAF<h@4E3HpZOdCNX=}l+EThw(& zB(_ZD2WeE*L}C#Szn4%7wg2wN(;>*ovvx+@?3F#1vGVJzKl>%?&9`7D;$Vae~cNw_Db?!5d0cC_rl@&yvE|nzbt#PiS3j9 zI{I4Eq=kF6xlSl80*!#!I*Aybj5bhq0HQpjXddsMz`oGuVh`&2pyBX-Z4HxAV|VGB z>k`l-wYRmhzWm6^o0MBLrr!M!lKdtl<{2zYuJ#E-WkTMRcQBSbaEPoZiV1I93cS!K zcp-JV_sE3##_CI$0Nqazq}n*aNz1V3q&D%GE1kWaP+ENHE#xD^vyvyrse~?dnBhkJ zVD20f{#iXkDq58v8=cjX7BV(>bw#ZGS@sJb7AmEoz{jKAc)kejj~B_Te^l724AYKd zav;Q!-sm%>XQjp!0=3p*nDIj`(+84xl>DTU!BB}*xhKGxN|mixaq@c*Cw zPs{Xf%Da~YUm=H)ixA3%cT(!&)Nhhpq*srX|)ENsO!hoUh?&;nA; z18F0q;Ne4AbCy(Dvi``9vY;{{&_N;N6XETLyn1;hATOGJo@&!t%dH95MNWDGqz6j& zMD*0JtQgdO&G=3iul1RmIV=u~h+~|+Z+?@)Tu9cZ+JDkWi2JUqB-C_DSDG-p&>ItT zNcZ9Bk}D1Mz_6yF{ilG>iK#xK6z8O#zJ7d8ygBwDW1>hi_V{n`66$pW%Js)chwb|P z%2NIEQF`EVM4mJ50!PvWn1N#e{CwSh!1=Y`Wft<5SV1V?7pe5@{G7O!jBTiRzOFjy zm^xea^jsym$4QFSn{oCH7M&c$ol{S;bOTC$_S?MyUVuS3_j%snYB8qs@9#31&5##8 z4VG4BaD#8)lIBFU5VNoSCRfTa5it%FdrcTvpgvp?%Iv}F2If7#;6l?y%(`7YQ&|a% z==apq^q=s#-KLboTYB?*?bR&*1PLy_^ahj|XF-`i;^M}k!)#?`^Cd=-E(NB30qeqF zXJmWw(r)bED}!Jt;+o)83mD!-0={K>qpAn)I>2XL&iNZ>150A*0;c3sXrD2Dm^6U4 zs1dF_Te$!-DslbO9OLH$edU4z#9OUMtA88%wV2bzyGEV`KFI!hmL062sMMEkN!Gfu zmBxUd0o-K^Mf;l*LuFLk=az7=6v`IqJ+Ykz#M7l{7~brUF>mqPa3vnZxXvl z`_>Pg01!|@nbIbC`%L@rB*ux=ytq*Z~O${-i1e&|a(lB&(TyUSeh{%AF3T$WLu={I;X z$ z<=MBQ%bvc=?Tg8c8s4yAR(&(+u}vpI9~2SK$)Lj?W6OBeys{p7uv3?pYN(#gcdnej zk>tn`(^P{aP+s^Yjz>aq7@5M1^Z38T{X`&FO+Nl)Epz^tneNQ*m76!(GK|zE4m009 zW8Ly;T;K<=i#nT1y*Tb;u(&DfkD1eWBn>x72=EuI*Q858OIxQyu_=A1A}!bQ##D5_ z0q1}HI=I+D1bS}OUCQ?v$_MT|k9ZGC`!P8&59nu`F*gSW-I)q&3r^7)=fE;Ooyv!C ztCj70qQT5_)`imw*GXDMtd6dGGJ)iZ+1@zWT7kwC1@0dp^LWST=db?5TKlCs?>HQK zm-Nm!UNyg1ze*0P$-lH4rP+`qa*-MhjJvV2Y#TWOGdz-Ymgc2&`tw$JXyPsul|~c; zeg@~qjp@@WWUhtkEN^ALAV$EX zfZf{zgZ*uy5qdG4JJfeW(^tf|bb zsA7(?72FoOO5Tg`m+vfJKb+f{wa%`rB*Yy==2Wb&nT5TpzJe=UUrV&K1*78>k*_5G z9R2acKzldOc|z%LOCo2ELk`>pK1+yg?RL80td$r9l{HPNlJN9^LyI<;3GB2ME}O4|DvKG zY%^EpyVx4eeOS?s)pcyQ4l(*VHP1I%Qz#j~U!N4C$C~N@DN;5+xdwL(vSl1FUniQ_?RF@<6n>lTp9YsDm-A zQzRbfd6hUWUl5}5Gp2x7-iT8t2di+(q`%Oh$eM<_&I5>47nT-z@hahL9`bI9-YiWB zudb4xe;U=FrPbruc_plm6ILx5_yDHn_}ds^QiI zcX}b4PI+oJ^23msJl1*=ykKgNVFGR0t>SnK!xA`jxdUv(H;+W9f>@i+x)adF5@Vv{t)qQeFTLZ+#G?k_ z3*9*6Va!tuZY}LIMM48`-Nrx@`lYTSkN1pI+OVx_%C$=4g6$S{Oyc&wiXqU-ecwRt z=kijA<9Az!oScGX3r)wTBdfH1Al4TOa;h&b!@6qc1K@G3zP@?k(TQYwNG=JbF zYkQk2_sr0p;LXVjcg&+_`dl+;Rxg>cAYe=jq~6Dr;P%~_8dq8bxBq3#kjPQt|3qNM zIj-tkn-UWfUPy&uO?Q_SbW`8s&qeUbj5z#?2KoU;1OS@9>ht*^gAh}bS?HiwwV4n$r= zb{yiC%1P~Tb~H>dhv=a*^pPjS1l3Wd#8l65$yWH}i^Ly85+`Ngps(nZI0FqEk#n}m zXkY(9sh5_IZYVYX?GZKcp6g-UNgP#Z`364I0NndK$$PPm>o*UIdSeM2H4RMgrbXsO zrkmC{j83p}+iM&hdkx_30fRuf7!sFF zJodWW<#rfWn#%4b4HmU)^3HyMLdk~nYBVs-v8LnjB zdzmk&q5V^0|QywqzUbF;##w`J`aq?Xmq+9d*%VW&@e6}L)TU4viQqF z^K0AgeT9Hu7eG8l_ia$GrCeywMx-BiGb64LsE)N%UVwC^XmepD)!A;)u$vJy$fjkeh?Hh zd9H1_kVs;JU|g^PylNv(BZek6HUveZK6pJD&6Lo>Q^H&$P4fU8vGSKQLe3gt)+6ZV?% ztMVDyv6x554bLO4p@JPZH1+u;$~5PT=V%Mi2MXLBCyqhLqHaXy2w-kL?&6 z0%53BI1rq|ofI^TAZK0j^2dG&WcpGJrqu7&5W{=T;u&K{s|#?el_n87$l z(q5Z-IbANT+LnDtmnIisU%)=s-KQ*3nmm;ss+pagmE82TjBWKPy#=1Q7`thTON_la zBm^NOr2U(z#6ZY+9QxmyOZS6%tHmjpyJ;?}>J3799jgUJ8IU`a{AdR{+Fqw6(cgbi z*H%Y^Hmi71pQ#`R8~`-@nQa8a2)Ukm;1YZvS%NH=-;{Zvv7{#?p1Yx!^iM6 z>^jROvFVJzYscxddsohZr29JmZzbjfkbP*IUrIwK7pFtdP%5A~hep@} z&|~FuUVuBW9j>nLsXat`+D7Fm`GuP9uIAEsc7Y?7Y}R13^UQ3sg>EEBzG!xHL#&18 zh3ck1^tGaHTAo*#AxyKFsa_iog?y8~c#-qKL}hQ1U({ko0r8u9&QS4V)*s2}(t{jH zgLdYPq+(cnqscw0yMItdnY!}~T9sewIhKp_=T_c?jEsR1At9q6ZRWPOnX!gMSl4#~ zdoccM*>yaT8ACX(QG3UBUUIO6UyTtlt;(!RQr*Yi){bKzUu#?#$gcf))t9*2{x7-F zTT-y(_F+vYYlrETs_W3Lkt5_vQ3LA3B~+&p6ZXKBbWdt-^m)rHr=zWI{w)9}!<^Gk zCb(NQ1%CG*RJo~p%ws>!r=NIYG)RYUW8{c7Z~vf-A#5CjJ5kORcm|(v&3C+c^4erMw4CK=a}w2OMV>rzR~gI4Td@+>0x#7oY|uX3 z-NXWbI8T7-9$i4Em#!!449uJ%xMAWso1x7b9tSNF}J=x62;z9BhC-o6I@PCBheabs)7zp?iD7f zvK{FE-5nRq>Uv68|2Sdww<76j(t6us$Vo$KeKELy6}xbvg0AA0mmuhyNYQs>ixitw z!u1F*+G=82EP~rfVbiu4P5UG>Xy{hc=#`!U!H{j5y$48A*2;*t=vn<#CRB9HVYkgIiO z#Rd1pfY}t!Hy4Qlj0jznrFf954~&%tvahV~gVJOu)Vfu+LGl`(e^xlu*9G zHl{9~{QTg<^VS%vj|DTI)tq6lsAG=Ko0OCmw&nno6{;2TXQ&Ubuo-)Z#LG9>K+*Hb zUwhu(&Lyg~JTtSuG=}dszJ@uh9Gs-re^wH>0@`{F9NRI_5IvtH5r8W=Dwt~}uq!w} zK2M_v!0^{-6tXzv-^oTSTo7&5OZ$2j0oj|-?|Jw;)?Gbp!GedoS(ILQ6t^ zz8bpaK0d;aGxi6gKrd0*z-{K#XSZ64W714^0Q_|CTuaq7B+Ms^_CT1h)5ZC>8jy+v zQr4VcW7jVWj*L^D>+R{(w=U1fRCU0Yny4UASI7TBV@8gza0B!ir1^7pS8Q_FZKS_~wi>`^0PD4ks{=Z@=)6lXh)X z!Lz5_%z>FbOMR$y<<+QP*ab*V+$34%$7MzIYC)zZZuZKp&u31Vs6Xn}GPGL}RjVa& z0$&_*pl#`QkJbqGvWZ_Ut_(ei2Ub5PU6EP68EcT1)8!g;xd{mS zOt|YI(gTd6F0pWdvj@Xhr3L!rr9V$7Vx--G8TKW1bvEkAHB7+xNi|1sfdYv-3qb^i zJChMZ`jW5NLds6H<@y@sX$?iVayz@zSVcBbgroTO&R2?|GM^Lt_e>)+Fh@~?K2FSL(n48c_i=PXMVK@~szl8lq6Zz<1cT^#Gj z4LF~j38&hF;7(yJjZ~T4-3qpPfTKKtGZQ`E#M&+t#xzi%akK--h>oSbymq?M-&#TN zP6ZM{A|DO0m)wj3 zj|E?m$03vlEY!j6=Cm-3HR2D1NXkJ40xk27$($tw0)9UXBdUuY^#~r^E}QNoPN{Hz z8}>E#wHGXVE2NQf8<9z}DBz=7L zrS8}f#LGo+Wfj?)wvZHU9iX*&tw;RttI!+x|0j=!Q0M>AxqtPS~Xd))s z>u*-(-7Nabj$QcUxa>TK)vnma^bt{vK+@M#&Kl}iQy42$$u#~J;r2@l&hRaZ z8VIdc&6#(-?2HaSIGK;>(-D7uf2n4LcJDJ}3~mXw{B?NPPi+Dx_}yRd^~|DWQTTIB zY&Mv{b>_+K`_TzoYu{A<_r>~_kJW?$^6YRULO<4P=y`vvrA-iZ?ZG28&bJG2oh(@+ zVluW@DLO;oHqwAr%g*`?shyF4Obd2WZWQK@?qhju+VpyFC&ZRtDYHg^Nt$A&8mS%s z_M{0CIcrbHa3c5SE=M%tSKnPMZmQZjGn6|J;^41P_RX*}P?moEE=&!2*s9UB13UO= zDbvJ2hWqBbn-TC@y(q|}-_G;8)mNr9=G_Gt)k%ionE^JA;W-^Il5uO`p$?4QA%}p* zwUm!irP^4yYurfZ12qvS=LVhc%$|F`O(d#CePS=I*mt4&4)P6-o9<4ro?fL#i&k^ zt$r^Lz1Jyg^4e!CF(rz$p|lb7Il9wdhMt^JqyDgVeZ_jc|}t zC+bpyPZ?9o&^c`wBk0rrL&d&9{eE_^%WM1)UdK4(SZBEt3qAa6{0EM%@&R zA6;u3{RxBrCV7m$=9EHO5~4D3;uAQ^y&b7C<<)ibZhalt(z=+J5nJ z_`CHV#Bys$oJXXm!;dtbF5kXKKga5%=Ex@w$EBateCDFMr_CjV)a|;M__LSP(gHY=I^pb zz}L1T82~74TnO`u+36rw(f`{kGO|Bgc<`AVNBbF*Dz?@qJ?DDj{ag{gevjgQwIs`d zuBTESFs&*^sljyW9TUs(oA>566SrWZ6IbMz!A=FcTTMDek!JOR8`X{m40U~>W z5^KbX_DFNAfiaPyy4nS;D2Ik!B{mN1(&!WvT$Nd2E;lwVUgnz9D5^5i$aq;Un4i1N z!qiO9$-BiJTSg*>+#Zk(Y<-o(=~so(3yJ9R3l$RjaS{U>RG3r!k9?>0pCy2l(j)8Y z2=edvLs2)TFWJP>Zb}3)U#Y*DIx3o)K4#-*Qjft>kFXAjABan&X23>@CCbizXnRad z8yj;>r;&*95CpDft|WMyold`>M!ZOrdEse%>4|BKtO$R|OC=(&D6jl9l};_m%Sq-E*nPT$6lDgv|iasAr*l7+M&ZZ#)5F%zWa zRaAT3SagcQueGY{nJ!+=07Hn}-{&P#|uL ztWoa*O?m$b_ZI^SX6t@MY)3_LR*WAfT2xlUsi_QkNBH%^_ts6vkVe7sfjygkxo{mPB7o#YkFCg9JGa(K&r%tn;T_C5N4WmY+ zaUvb87R9YgBY&Vk`a_nS*EvIJ(Vcen>w}5PdGmCw`C*WbT_lrNR*H1$>1@=!lB0c2 zXeS)?ubdQTEK1?`t+BtPTedHT?_kbeAcc&~kn{wT_+sw_|D;x>N_Q*&SO#s0-CUFa zTkQ9@0%sAuIw;uY#gIP@VtF=jo*0@Unw;E~2;UKcKZ`L09UXBG7EnuHeq1F_sjV|N z`%%+m^BbN1^HNlF#)Fx%@pPm18KP{ii8nDOX63vdkQ8nokC^~c#U(Q4~Q+b*KgBok&5ow@apTAk$p zFn9bqVQ;w4x{7&T0Fxvi;o2*x4VXc$Z0@*;1X=;g=#l0ocyx`1dr{#y5BwQ1l%wrK$^5}_h zo=+-Owbe)#1Sk62L za;O_#0%@_Nb^EC4lwXN`KK6qYFQ*i{8Jxf3<(|KdEvs{9P8YB%ASY~ckXMnG9Amnm zXK|)pMH9hCUz6TyHCuausC0@vQ5OjtnzUy2^F}S|a<(uR(Z8PggPc@VQiqi3y_KEQ?>7NdKlSSIez! zI0_BT&U?L&^YGkz7qNReIGO7b=TS;v_E$iuLI8*p-(-~f^y8pNiNU;syKYqXV$20i zKi!`)*5@irCQ)e;{6$D`{P!Zj)yp!jqiL6_MZ3Ul@d*+^0L9~o&);q7YpVQ&#ODb1 z%B=bA$OOb+OfXoClBNCLc}&$u(S9)-bKxsuC{wL{=+dR*iN5f>wFz$xEZ!C&wm)r^ zBR-00_@kFZu!ikbZ9slPL5R?*m+uDWUCZH|U)CniQRz+@7X*+(0TH{PC;}wVV@bLn%`e%N)9RCcp)KX4eVj3r~3Js5JA-*)W$oiM-mSP6ZYl z2Ib-cd5$&Tsd!SELpZlq!9FmNa{hHH{CHa;XxZ+}j^3bsDyR6#(lkk)EHf=*41ykAnfWl8xsLD^Ildv0oG-=Ot zvZo)DCP5MsS0PXCe^3uQuC5l5i7C-63x#-O;n{O#1Ko;l0LTUlTZogwHs|iIi#3UC z(@ANT>XodAm{YivloZD#ES8+ceHtdp7N-r`f`%O(M_N_L%~wALyom!?QX;KoZW@r( zX)gV)Ov-W90DgY_#84(DuG4lW)d#o9J8Bg~f9h1v`6nL@`9l(gR3T$38EU~4t z+pi4gAg3VT-kIsl>+v>Y6R((zr{josM@V$TB0eUg%03}I;fNO=8N)(z!+7&uVYLd% zr_4!=36PO1HjquQU}PZSt#}d2BjyLL7;uSCYi5>j$iMduQ_4!#>;MGcN#7~cw8h9A zPp-J17_x^z0>6ovqsFbhyaFpt3^q(!{{#ws2kNQ5ZK5$l z@6?=jQkq@YlrLHSBNy*@o`m+(-xf6kF)NT6m=yL6R;s=iW^Ly+?g)c>voLS_3}d%+ zkAGq~V>L{XP)YR&RLfMIe$8@RobEfVC%mSaGG{@(sHw_XRz=Pxut5LGK<|2DQP#L? zMX!I3@*~z}3^Q=X`a2@!KPU~J7suCYos7YySxJFwVEXJg%5>QyC_ zc)r;@+CemejP86dU;{NsnJ47vrPiNh1mHIB@pkI}WW$mk8hLAb>jM+G1Glc2J5EfP zZ@Irr+TTtb1j~(X^T;{OrpMH&xoRgf=OM($QZod|Km?T&aAH9kipckV!Mi_TjsmJq z=lA8}NJcBFoVxx&H9a&6KAH64Xl*5_h`Ss=q!3g%v-BzsPEe0d_o(s*{id&)a!)*B zMriZ;IhW7*d2g!042xhj)J`mjc3+J2Edxz8nBp0}PUs9+;G*Of8BX@Iet-N`k3a4N zYP2tfg*B!0mo05QE2j<~+MnUz*EwIjO?`olh#_SH#tL5RwjXMfUWg53qZll6F(gw~ z$Uw8Cq9uJUoLF)j>dZW*A~dX|c)Qu3A|gVGY=7Z_o6b1#zn7vt+=AlhsJwdB0HP(` zU~VFv?O)Z=foRP05UIJ3I*4X6Yk9H2((`grXgnDK`Tc6i)iFY{MsA!2yH?C1E??&( zn9*8aK_<@ZpckoEBI5Wz)z^>)i|@3*PadC+6l)r{DP7|(6BAN$lFiUi2QTW{YS)^Z z-BRjx0;p&xpFFl&l9DV}xfrj{=CqW)rYcsbNnta5(ZC;N`_fQYx+NGVKzl&!3(C_| zh@aWfaBq`L@n}@e^2>!EZ7>ukkW*+7Q&YRHY7L1@{tK#gILH(!B-R)i&6$lkwA|If zw&9O=Y((8NZ~?vL&0+D*Ouq{oa5^1+ zHfVjYw$jre;-i(Bh^H~l7|-4>)$kh`cB*dDdRSn^zSFed%puBJ(p!QYuZEO_mf+8q z#mh4%Ro@Dao81RTJs-4{@~`x8yALj`pwBLj{LcPKgoW{!BgQ-E^BCK&G|x&*GMA~g zj}abqfdak4YQVXk4q5@Clviu#1Oe1bT8I+%lvTVK2CS?aTj1fWmedyo3IfHaF7T33 zSu97i9WTb8*y{+Q(6_woj?QNpfxwdMCunPvNhQfl)%PWRaz*n;T62T|6$*~-Cush} zwG%8%yXx`dZy z59>6SrYLJ|eFX9a*W*~XBbj*WY4g#marRPF*7RpXLr?IeX8;{voDP#?nw;Lo4&KKN zJ$HF?k8Ejgp+ZBft`KKJ5TI?88%L>j6ZsSDVE86{UogT?)5BZBoopC zJjQ-5hANe0Hx;(2(C3RS;v{y%C31#b+Tt%!p56dwK5(DU3exScPp1Pz(){r7X$8F{ z?`(zOr*$PIW`HCMhUFgsUYT4@hp3m*iU9yp!!*rA!6$W3{d9(s-zv2np3}`Kep#%= zZ_vpJcl&Lc^3y@}gc)D*5Xm$|g!VP6&^w@gFZA(X?&4}&FW|nLCbGaR6r^cm&G=B$ zGvX8pv}%+Siu}NOwQQ!{T>AKt|FUFO!l&!I07$}{OJL`l4Ig)k< zNcc!M)*86mh7JW7xUNcD^XhxmUdB_E-mWmY8C&@kR1h-o)H~L%$`z|vRMV@+3~z6p zMq1xq)g8J!trJcw8G5c@-f18?UKsud%mzq`M!M=}zqn{-qCaiGK2gvibt8i8jKJ+k zf8OVKeM>!3QwwgrI=PG31~XN7{?(lpvA}D(O9&m%VbDSOMUWf3xRpf73 z@#+pzX?_>8jEg9dmJOBCOwhI`(F-(fdy;A$ksx2(rI)mbv_txl-CfOu^de6n$gXT? z_lPA3HAy60eDX|r$P_Q7L`=4u^Z#*qHTSEvz!p zto4tng;HtxMWD{9>yG35uYB9p>y2w2dScu=`B`IP4hE#%`p^Mb>hEbF zlzV+vf_TfT#vTF3B?xv?nO!;0gf({lw3K?Lf#a8>^!^o}~#jaPgc-%^6U>_SY%=@&b@r5@SKVE)-Og$-#~5em0nTG>EweBvd>l_MwW_MXEY=V^ zBvbbtYjO5XMYNMARSaKm14KdL%C|ETp7U`$xKRY;%N67s8fE8<mSs!blwfyz55wc&(@)-_xPFQ@P;|60Pr6a@*91#J5zUsTcyXCaKw)j#QBA{*<^kc`C@L$AbMN1(>pQQD3o9Bfmqfec}!r+AX zNn47h7gUfuFQ+T532X17($aLR!+A#Y_5I$xdFZZv%gBZJbIJqfURV0h?Ak24h<>+$ zX~PP=KcxWbrZhcYp}B|%mQ`&eMh|Mt{^*$O9~rlvdp+XxioIXCpSyPG{6||!U5c&K zT{H|P1QNkEsGCn@-HgMEs(wPba$}Cwj$y8%~7&oUg6Ojloi{Q`CL*Omv zvg14?3aT`(>5Ery+qie|=yHzys_N=h%N*6okIhFK#o;{TFABwiYby8t$FGZgzQ9YqUxt;j^zLiXRX~#tEwOm{0RMj1 zPcf2L*c>yA*~dpiyY_aQPx(HzitkRYB|O&X8To;K?{De*fIJLoAAq^oR!QSBiW@jJ zat1|Lvc2Y1-hWW5bAFfy%*J@5p6acR2A*loz!Ypu{7Ui%%;+!pf>FQ7&P-B%|AV?Z zR&S~sRCPSJd{29^;K$BLPdz>C!*uiX#N*GG8&$8xlX#5{>jP*Z%q`do@5^j#i_OB9ihVjKZYcJZT zY{%q-0M*Htm9@$E{)7h?5Np(Vp!sRVT@!HrGZ*bZDxr7tD&Kzfd-y>b>*8rV)aW*+%Iu%u>~4S9L%6ygbqw>>c+1^oWGk{b zT3-DZ2#rVQQnu3h#nyZnzuG{QYp5dp^|KeZ$gw=%IN|2T+&Ha)bvl!(|`>pvdMY~ zL+3i|?j9MXOk3@yJ_8PeebKPt4)ac17m6W0Ci<~}nzrt$;h1cN)ZCE#*Vr*Z`f0J# z9h@ducop~u&95rL_k=a&=?+|Vb;=}Ln?kLYOooxzJ(Z402=rSXiF)JNH7z-0_`ApW z7Mpc%hc>&dKfHD3-J=xuP?sRQs9{jahOObq1Jv0jjr3;jJa-lsMsR77d;g2BcYce+ zjo-IxH*>RX+qP}jWZT-XHQBc9nvBhEvyDwto89~A^WgYCzkL3LIgWc~?)!ROuk#cx zYk{5*uk>@6hVQg=!Qee$v1o2YZ4c~TVgn#rY&{}x8KoEK9e|KW*UmrT#}?wTM9)Qj z^AF5>I>qnxeveYEp0u=GR#+=kHS!zGx4eu(9RK2wE6KPoWZR|c(zW)Yttc|>SJk{1 zC|nRg9M3Elv?+38aV-BiHIQ&c}-^+Cq!yb9t+q<{J2L_N~NiRwrVu6)55bmk7S3?8p)Yx%_j;=Rnr;j zn9s<8ZZ}EgiTZ{ZwqZk7lC9`RTL5px>iAm5k%-*k0Qf!@F*kJK&t2GcN+ZB&ttR!X z-mG5<@V2FdOvlx2CTfob0Dr%Pm0O7Y`<6Lz4(y*EC-aOee#obFdCu#}er{1YxQgagsB#qr@WP0TkORP{e7sI!F% zcAc*F)4Z6H2){m1<>d~P7~|YxFpn+~Vp?(O%_7Z3)7Y)0OY)Sm^pK>Svb0c~5|5qm z=wp_b!v^Okj>D1jg0`l?1>HpzrBAgjk|N2`lSnPh7Lr0((~tfly{d|cdW2~GpSGlx zIM&Vy!#klkC)O9}FG~jUgGTh)1dgyY^T#(qx}%^dd}7^EYzUeiTAXobv_zmlYN{HY z-(7ihYjQ}sQ*rHy8C8}Xm!3MKF!8UJZQBN~XZy2GKVv;|Feba>44QxM-p77IkoceN z*nf_ zahuM0eDNY;%OCdw5Y^ zu&{e>c|vHCl35a@WArzfzu|J>71Hi3Fqc@)7&Th~In;IMW#jL9YqpL7^>3BKcd=~f z3n~S(jrpqK>?)IVG_haHadmiSS_X5Ha!|Y3Z3QXvGjx7&q2iSb54S-qno7g$<2?%i zv;jM@oFCq6)I@QhfB~xu*i?G|?fBxNs-`9F=cnvMzN|Njzict-ma=+QK1VJ$-*!`{ z431`-^K{q(gH71Z+!=||8=&PTx+dh}M>9w2gkbiT58kno9>sst0TMadm;W{| zU`tTw+9Uoz&)iDbY0;VKV(JuMXlq&71g{+URp+#cE=uzzrV#c(ZgqC%WKEe3>k>ve zg0mN*i}BB+U%iUsR}~-Fg?*zMz1CpOwgi}lo87q4Ols4-5RJJKkW6j35NO-#q%7>C z%gJfGy-}fm=oN^V zLm3Uodt|0gou$ND&FDiD8&y@d8mN z&^GTLGc51HHI|SYjq5%3HBaDCm5O{38MB0j=i_OA0_ZQKg5~;HrV4DM(%V|(!Tc~3 z|GNC&^==&&pnfQd0f(D9$sogRg3+8qYsf!r`YeJS@6&_b6AZE!h5mU?e`wEv9BUd} zi6h{Ne;^GcOLEzr1;&CLrFWJn|Y@*74yrpLcy`nVXS#+w1 z>Q&Q^8F zHu_@aAA@y2d!fC;94-9)YfcQp*70z(WWUQ*k??|hW-O--!wF8GR}!`hXLw3YTI*Zy zJAZd~$NQ<1{psdAA`DIpN#XJD7mEMus6}N#RntE*H79QMtITkwvs8-lU((_&{OoT! z1aM3$TBO?yOpGA;TZ6xSRhNBMixFLg)Vod?s6gK_{vz-TR1J$gqImg>>5l=uS8rZM zi#8pQF5L4Ko)&j(0aP^sd!pAn!h71b)RHVMgns}$VT0Rb51s)BYo$eJXW9bzDg@0* zYGXR2x+h+}}YwMFtZxX5P?JEQ@lT@=w=_%EI9H5pFM-9}%*}1zoZV z*(^BN`>2J7=i}j-EI3t_HfCo~^*p$(IW?281XWUhZ3e4+2!~vQ(dS1LG(0lxF7)<) zlI(>oJF9?n_B$V7Ed(aqbhPvQ$GW<^++Uq_)!XP$qq+QkN_T4YfZaB;@0Rk_K&?&3 z0a;DjaFjh~-r1kh5%IAVi#l>8^dFYo&P7=?M3m6l(KNRDEu}nklrSV&6U{8lQ90;LC4r8IBUHt#C0{@->Z8NaT?%~w8eFX9gNXT ztyuDiD38oCpbtGzZ76V)PIq%OKeuD-O^bZ5^;?&Bw99TXWk`!#Or8*%oKhI$XwlEx z9u>WhsJI<(z>}6MmMpP{}Yh`dUbS z*eTVgQ1^4Q2$XDkz?ckHxtawS{tB&iPaPK`tvZ~-a|4+sxV15b6N@9!8RSGd+Ew#t z|GAM-p)!{}OY!Tu8{){6%C+4(U_8FE|Esi<>3Fn50iZXM~74}WuVin=+?)*NT zJ9k}^4hsfb77EbRRB9gjfc`2r&K|}FQ|&7N<-gWxX<-H@(fJiyd$Nf7d3ah>!p?lrQM-<=a)OI_jVmYm2<(x%~@<@EKx<=bPD&3?p& zC4f|vM+HnzFHeZxekDFp8h#a7p9rdJQ9jLuWLJ!TaVlBQM|-)MNq1TZSPA$-6XT|% zc!N{)+=^1F?Zp=hcc_fT#jUtXxIxya+SoVaojzy5TyUMAd|?nvIca3P|_!;^-+HR7fYQ-Yq+(xl}N32m;~STEl608|*1i0&c{DKz($vZ+{J( zxV)mr>oL_ERY+jbFXd4;qQ!0?1I;&xt#sQ`J)RKEOREWsl3vF^&|9XT7$jA1EWgDg z;3f#p7VLc;)U@Qgco$7s?}xd0*Y!uXy|s;O#(DMK;J3Rf&(Eyu1)L71kh-BW<>oC9 z=bZuZZf8@_`hL_|k$4(v#`m+Jg_RaR+p0FBe6x@;mm~ad=H&3_2I0SPPGu$TERqvPA3D~G!xXY-2DSKnE8JKzQY5dj zG{RbqESi+j=lc~$k2pMAIbf8=l~&fwQ{8!Rr+dUY>IeIh6}sggLjOb{&r3{dj7oG0 zh8|8WPUL|zQ8x;JJhS23$SBTgUkIGsQ{X&**l_3k9ClXGlQARg+i=7EjIj8WZkcLSEHl%7A{nDJw1#QkY&>@|kpU>K5a(QK z1$x`%6}UO~6mCY$R81*sEVp?IXO)!|1J@hBLjCg0Sl&aAF~q7ZK=ickh9=Q(GGiqS0|`Cr}4POIjiY8L#J zaw85swkwEY=FJv%yOd6)TMf7X_gJ4Yr;ez;n6HMzBImz;&63BQ=LXiLH&-L-;bnU~ z;%XNqYO7xSfST;?+zkYbyp5lKuU}o)esv9EL!AA*wg!vP ze~5eIEO(>#>iYYqsx*clpPow(q5*LCsI8U5{K>SjYWrB=YVCr_zDi$VeDJ>vMyN9j!!gB?_b$LW-ai;Tii*{x`b*Vw z8sSse-h$P_N6~l&lf?t`p8a|it8oue%!r-!o-Ju~O^P(8glo6F#*^w>G8HbzWk%So(+9nH{BD@!ejJ8y z7V;`nWU>@HXZY${(Wl{XYb~H0kZbA{JCh#222q-|f5Qqf8Rxuhx8s97_cXwbgk+Gb zl#Ti&fh54K92-2o)6gu31K}R*8nWReFLFKWyFREV+JSx12$-df%CTCvS5us*wD5<+ zjmBf%?RO)TC3$@hetk*nd-vY;jM)agdujhZ6VcUxyGJ|U&g33drjDuZ)*n>wu5P-6 zG0N+wI`JX2lhlu|SipuCSezE6%khijG1h_b` z7|zny9etM|uNd&0vR3cxBI}SQTc-QZN#-y4lISOBhbT%yNxUI>AwG1**Y9%U!GAWq zOj%K`Ev#W#U#6{kMUOS?m$h~+4}(oP7`MkIX<19kL`b!-q(SlMn;VMXl(wffA{UJnxK4TAsiMy)-4!w^#EmjE70X`UO68yQHv zj>eY}Qze^TKYIFCDJZ*ZWLdzP4Mub;cRz`pShe^fg0w)tc@@sI=0W=|qa>R#m!lPB znr1SM+)S-=N@m@`akd5^))Xs;rK~r)E+qrU6~Nk_w^af>PJ4;^MB+uQA^^-ZKJ;^3 z71`%G8kXN<$bZ^8CyT~&?=k(Wm^SXbVYa?Hc1$z(4tBeP`EUS9uD|b`^E&CQDkj;& zLWR~bU{2N&P!?C;Z%lEe@dJlhqn)CIimPdlH-8z5_*Bmk)i*s(X?Jq`e`(YIq`eOL zInC*cZ1_*I?d$Z8(XH2w}BwVOdzI{^4Fc-_ZOa#}@tEti9$1z6sE~ zN*f(`pMqK#_pxB4@4~ocIqr2}?U#HK*O+S^=(1-zi>cYTck_UIUl7`rSe>h)vyEvDY$)dZD%4TAWBJGtd}nkE9}y5e$-7WN zrp7ec9dBQ6kz7qdgGxmx?NCmsV5U7L^;0ffV^E%Mv#&{2a|4`YaBdl|^Yhr{w0%u< ziuxP5*?8mvIn#(M&c>^K+Nk`it}=HnWP+eK1ZT|P0p{X|2YNufXjm5 z!A|_73^t>3?UbaOk!y?jzmYf>|H9K{Okw8b`UacIn{385oU0|Zvs7|#y#gEqf2jFyjHV@*1vhcvI zTi>!}T1r~AimWDfkgx8VR{}p1OR$iLi?1xPLZB5HFOTuGVKc0ktJBd=`WCz6O8T1( zVlRp0?4RYuBNu{KlUl@ncs8?OF$bT2s%{f^@Y0M_01~d$s5FZeWqP%w=^8%T)p4{b zoSAr2NK8#J@l1#TjYP>|-XF)T*nY8tx`*j>_%@ciOXyT`OMSl%x%fDaupG)*54Erf+eOzExL|ojF;iDI9H^3 zDZpvIUg5sbrmZ}1-0Q1am*=7Vvx6(rSm7Fq^vchW6maTaudxBk; zyF*bX{C^Pi-_MVSn}+v=fJB{g(isAd#(8xW^@UZu=HDmb2b$6`K2LWS6Ii(SSuI9s zrl({CL!$?MX^3`Ou1=P)h33?czA6|1B)xSw9n(SM1%^VWTA5xdUizYhc|f zD9kcB2Bs?P+qCPNSJvy6Zq(1|GvKR>UH$Y^?k)Oylcgt<*k|wZp^A&Mc!r@$qjz7r5wf#@XMAn+pU1K4_(^G5`=R?o@-5x7*RK~4y190_e%=aW zZEkyzlxrEW=PAn>bGE|YaVexMWi?XYjW6XALGSsYu}E_2zl3+*PKwv{_LrqOn_~aK z=IGddI$VoDlT=~%^T+gE_V`@?2Y%0>lFlqwj=ahj(d1K*5_TsdlDVlPT#MC2+mp-g zKq9Lhc~`g+N43=K{`YF~iegy4=|J&y7N?X4gsRK zb~Hw%Acd2FljKK|v))I+oi@E)QEAjk)-KVbnG?0ehbZ!n%Glb>^gAZ?UI0$(wxX8= z#UY_(GIebh!Zw-iIKgorA2u{*<^p*E=DF4Z;QW*x`Ot{7A!)&<1fyNA$ASW8cUT*v zSWOS`SAkZ2&rm^7lptbXj0>3JlVH1a*f^cjci*uJY5!xF`~>onj>ll?Z5eCPP)ASC zu&u32nzHDd-Qe!}9h$7a(|+(_U${4OYGrblHkfX4p`Nzc*7i_llbeMW#H^SF7?j^P zYn@~$CzpM#3#CmZtOz75pV!qP%MW7v#t=LQf=8YoeAmsgyfw#p1;|$;nC`-( zbuL&vIX!doyuYrVTyvI_5{xDT7-RtwykM{DLtp)CLP_I9)=#syDG28F91nBYJwA(A zzq~TwYu`lRaskhP&!-%l%~)l96~7C)2Hg{|p^aisN<+0m$?A5578jG=?Cxf5^m=kg z#b7vm@Ch-o?|t}uIy?JF)ODiboGl4NV@CASi|A#2*=E(jxf0-?eCHKqRPBQ($CPa^ z+jKzKM5p9^g-t%D~+%4`l7-Ys=!)_D70wf zksFL^C#O_XWy3}W<=OHlU6o34_vV1O9T=7fEU-QskmL63b@Q-!CI_Q=8;md$$L7_p z^Ve_%G`85(tYws9Qpb;@Wtqh*p>&0{&-a)5xwY(DYm>V1Ztc3YlcTeu>@nGx9d<2`M7P174Ni3&+k$0= zBaV<^=UQ3G_FNKP8$}%wnqCd%Cizw`ng$n9A=1}hen%vmP^UpNZ;RL0JvNfr!N?VD zC2vuq2OU#GV_jP2*Wq~PZt5<15R|wBxvrZ9A-iGtjvFMYQa7yZ7?(vTV`eMnl9hBU zKBaaYJ`ZV1(+|07+j8~DQ+0QEAYO+E^p_sxC91{k6VT&8mtA{3B|2$L$=mX5NXt+1DHXpG>V6hKOOSX_(LV0}oQQdd zo@3wfV6?A9Itnj`=ak7$`wR zY2a55=88-`0euxkyW%R(E2pVTNNq~_eE{Y$@a8#t()m8IC3jYvWY}w+Jcd^}e<;)+ zQnqRksu6B@?L?zh?V{p_?|=u-fNTtG5#C@l$C%@0@N629*qw5-$-jd&gfr(RbH?q) z=kuIw&y{~&*ys6P%_oc{Mx%J>cJxexlQ6<-4aQ5kLweCepnvXXD{A&Um>*4WMHB=N z-6|%ny;e1)e6-h^FG`#X0vY>s@(y+s)yOvpPaLy&g`;?)e&mo=-)#|A_551x5FCY6 z$+T>%HfRqZ&FhUpXJ4U(`u8&VD$D5p- z7<}V=VziZnmOeN@b~fhyCX|M@xCx(9w%MK#pXaUxv@(H7dKgpLtQJolH06k@NWe}E zs0#Pb)$%Z9%~aYWdiS9#JqN4>7OW`jEey_HnJ=LE?M|(~)eJgkH@B$%P<}DfL|#+5 z+VQ_;qlJU0M3t?m6zX5?znF^?tXrn2&d-Luh|0LCcbc&O8J4x80ugKys8c13hPv6& z9V!yUZ!2W=n)6JPBeliMavSs95c96tNKejUR;e!i{GM;#W$pSQ3^ikhjz*HOCQ-nz z9@K>M%Jhy=h;qR8YWc47wIHPl3ElL`s?z~GVJB%L@&IZ2Ks>bj!Fwk3`!!=H^27F{ z;e|!WzSSU!#Ds9(9}aa$T|YCy_2WH9|9j(q5P!bMC-rxe%)RTZ#OBlkf?M9Pvb@o1 z-ZTDO6jLwF&dTYj#Bd|h+Ff84aK_5{Q5j!o_Z^J;+sB`n9Lcjmf46rU20wFh*DR+@;Ou9Ovz$E zW_W;TQs})K^-{1Fehc{9bI!ut^aUyoGc(c_R}6={`9_KFsJA|GHf%uq1F7 zn4w;sA2@_Vd`4#e)N!ZaN2&NTt&uqu_OlZ*MZ1NZRcWzy%Z*!6W5z7ZP~DRs5*EbO1M-N+H&bO`o5g6 zGOHJ~tnulf-T8k$A<7GZewY{Gash>)@ZpOU60+2CKmD@Iva$oYexn6+sSO$qQ?9uL( zUQ`+UWiLn7u{&J46K^3Dho3nJlF8R}rm>k{g*%|ZyN1F9Tpo5q<)qHVJoZ7M&bRAd zeVy*miyGQlu~`DuG&PO~J}KbX%$5;d*qdL6bGKxz7masc_uNlUsrjYkn02J*5v1Zu z=1WZO?mZX6-h9HCrS7!iW`~-Y{U7`%_i3(fM~}=a&n3yGpGJC2DNp()_;im{|E7lKjQL{Xi4zyyUcIi z_(c++ecEu76ICb3)?%!2y6~1TTD=`#;4hUQA6$CGsA3JG=ARgcY}qHp$$VSY*Lv(f z&JhPr;W>OvMQgcPnK6Xz9nqmpvoZP>93|h%1jhL>(V56dcXFd~EA&eJ=qrtf`Gz41 zp$yah?{M%^2xbxK*Ak+AlX8{0T&DbT7-fHk+C%fO4#JS;`LYe3fL8P1Sq>Yt#a8>z z$N(n2a*JOVBLr>iU|`c$v6PR|TmA88nh_P3GKTmQG%ll19pAhnO$Q$;iq5|&g1Y{9 zjixybYG#`r5QQz3`i*50RvV=FuP7Hw;*YJD;3j zi5p$dF>Opwbk#=RJ(T^0mJW;r9CS1mEoxNr&za#?Cr^mDNA?kJStse zJfop2*}7xOk6|{TTNH`}ys`vD>M$#=JRq}VbNFjPom8aoR?f@I&6+5$pZ_>(ebejQ zq+2HbaGU&5Xkj{^lp52pT_m*XC1c|i%Zo_g+y-3BNaVyKqAsyrShkC-fWnIRwm)$iYE!LRiZZtGc?sRg1q>z0Z||a@^x|?9RTorPb)> z$+Ez+D^T)>U6I9a(BWCzW&tp(sWl0y&C$ejlHzu5FufGwqzDUQqp*mfrx>|loY7jF z9)AzGvyJvTzCfXLd1!_+`YMShBN!I=RPVm_xy2Tqk5>e++y_-vap zSoH^c^V>M?57@eFy~Y=ix@X-Omga5jq+)7hhgK2YRDCmRD=;}(TEANaN)KU&*NJ7l zhB7g2no39P32W!TY!Hr34fAfMo0tgS^PJIc64&rlNhrLq1Uwl-hRS@6GPVr zB*2ES`Go*an8zIY`1A?hYd&3t#kmnovzKJAgTs>l8&YhW7gm#e5{3rhwE29h4@63^ zFAfdqi#eR2Px-g)Dw&~D}!ce~5$fC*(TR*8r3#W9G~GCll2 z%!1#Ga8g?`lwH!!w&TrGRBnws+;m%u$wm?AxsSwZ*UbCQDi14-=jVr|F{Q$QAXOMJ zo*%(uziK;|L69}Ol@C6qlot;7Q3G}8$4RS5dL@j)@$%Yfc-DEL1 z)0KEB=+JD&C7P*vD1urm-;E zc|@~L`wznX=$-+awsfcV#-jIN4a<~KROzGQp=(`DUXmK>-TeHy7l9p%wO&OjXsTjO zV$nsNIpd4pg{oxw1H4BK`TX+T9nYE(03iNx%Jsmoe5~w!sd}gXjYxx9qEk^B>H!ZG zmsoe(Qf+P3o@Mc3ktbf;D)ld zdlo#Q5!=7Rv;H4Ml^+^v4LZuEwDciP%0h!CJyK?gS-uZ=I>G-o#-bKCB9VcScw$5kMx6@(<85$ z-@}1I>94P;x%Mz~9_$NXhJKqPrYC++k>4*AG&QMpnkW2m&i%_KN@edb-O?y!CVvnPna+4m#9 zWMh>}O~zxd$)t=9sh#>RVD+*jut{7GRDXg znS7T%N?OhN;Eb#n^YW*#Y6wFY(qltNfE5SEMph)dNt%=2w6L_O1K2sRqkjzR{lsO1Kx*2a*lOd_ zmr=DtJm$JOMw4LTjnNo(`k^8EeII-LID@w zOSrgiSu^!!y{bCbi$8-0(neGlVuzXrJ%d=xY5@Lm;&n%|yj{)?q%jKNjUVkw=2h_n zohEU6e5lOz(s@NCshwCy-F%Tj#>~&@p!h-SJP-dG*}MnVv~`z@LZ6Y%M$A&My`Vnv zj?tXS-W=XD(62Z)t1s13tX_nkea28Ey-#1k81OrZ;6TR+u5RfOU(eVekg$1L-8?~w ztzY;14IIF611-qior8@q9F{xzr+BkL>F+p4Nih^W%Xvv+bm~1f5<2?t&KI3Y%tqrR*&ZruC1iBMoRweg1CDY^DRdW!mKxTG|t4;tB#p>}4&96}29I z8C}Jyc#1Luu9>eL%&7loJ|4a56QSCfa>l=IbtG%Db|2Z`1?2@ZteHSwB~m&y6~-6mL|m4`YN(%N|f4PV|Vmd-4?7_1@ylwO<-=%R~;Rv z*5FSt{*X?Jev0(JoN}OMTwmNF{6k@HYWb(<=O>+T4xky5mXw>89{u0-7GItY;}WY zlrJ#dRFzq1e6eNoZ>A0rGHhSH#wWa${`;DM-_G|fd2<3f(@L8EU3Z~OvKR)Sa<2vD zR~Ai5mJ^;tA4H%%V@zK>YC0?xTv7WW%adH0?qfDNwzB`Y-&)qQ$%>xCevsHji1kH2 zAPx^$QS)`TO2jPtR%~MFZDmRt;8Q6P>@5hcge|-+s|cPAfJ{lS0!QeZEgQArvyVf*Z_B=_`%@AjE*>eIJb>xfOn) z4{&c$7J6Xi@$tPG$3#a;>!gcwt1N`fl_-X9(WQ`a(QU^S92oUUG<&7tc*_{LqC;~+ zFUmFkD@`r79dmyEvPdo5Lh4Gh{;w_-kj{^jUbn8YD{)L-{h0wm<3O@tUGgJB|B*>+ z7VFmLd+SaR`^ZfT1n`Wx$X1!SF#BIysQxZ5) z40+*3hDK8Q+#G*Zi>D*Yy;@0CVD9lo)bA|ctZqL%vCe!f-n2k|TOVLf-vY4g(UI&0 zIX$u!np>2Zmsem#MZ-_P#1Vp=_BYtk8``zceZQB|195dhV{CuX@8gY>E?iFbPYu&P z_u<3Q)U?quJ5Sh1es_RDGzm7%=j$&9Eb>kNK}ZKsMAN*gn9-+z%|q8;S5*}g(#)Rb z@9^{ucrx2~t{YgBZur=0r?b&P+L*%(o(MJCHy1@LFvJ*1r=>>%4K-Ed$;E{;O*G{D zr<-A@OH-xA(X@1Q13H0yDc#qPT4J~1QY!FZ;UPOqfATrY>K)W6J{lr` z;ha_6n@7HWjX9k~k;4sogSs5|Bg3({nPs7+rG9ye?M;0h^E^6iEhOtHScYm6u5R_4 zTSGWuQDT2PkQZBJm(iH!g7x5i`bcf1q-8`#jZ5o$LXHImr_x8r)HG^>hg-j85A0C0 zBE|Dvr(rX^tm!{~x%#MntekpLHCWn&L2xd$^DlzxOx$Qp{}5nNwDa&*QC5K!wJmIq zLbK8V`a@=9YVWGjcKdLyO6O*+LPyRH@t-#-z>B}gq!eF#@#6k^4Zs_7MjP{Vl|f4D zTx%f}zbO;c2M}kJ{wAp`yH;M99FJ~)q#{);t-JQRILReNXeK82V=-$K8HQ;(-{*D=amcp! zn>jaPwnmkUHz_E$>I%VWuif}FKbwK&FmX|W-L|TnZ=Ui=`qAjb&zfTHKSbrBZ^Ev0 zYJM$9RMtjkR!?+V#uLX&kG0Iw%&l+kL)|(ds1%nMmZ6nKmEEyms!yuRM0v%)Iw|@q zMG)YyU)5O|@a%B(<^KmUm{xlqnAiOm2`~g{oHHgfE~VBicn4n@6Ii|oErdwAq8x=R zZbI82KztmQU=*ugRHLlm50x&XpYfS{WDiNjRy%VekVP*ZFe?? zBMMkwzz{unD^CS?2-2bq`kZ0%4WY(LGHG#fQBKuqW&-yyw(D1aLZRQbCsx{@`O#tL z+yxi79FXPmy`=xli z(_&joU)A0v^x?NYr)1LnIFF-x9@O`cozD~o>R@ zpO!%9jb=SfsovzxV#8VMq<~hP8!IMq^4wdR!DyxB;4*`kJth=KO)r0hBq4XxSeGNE z>}#vmnJ#D!O|ON2pg_*Zy(ZCZ|;5 zO^w(bS5^TVT$;gpg@4sF8$}_}A0e+q+P~P+|3L)zGf4eYXxGIrtOC-e(ZL-LUqqH? z{zyRoo~!5r@dJVt?)@{j9^EXR$J?=8+YTxoUe~~TxL<2|xao@L?5_I*n%@u*Sbr`Q z+J}^y;TQBL;C-UmHjKuM zn})c_iRA$mtJ3G#YPZA{-KqW9xo(wprLEx1djve9oi*g=_fr?2wxOqCzt%aOs&JJZ zp#II__*56rLYz#)iwcY@GyV*cR)s%sa&mkPR^9$`Vpi1DE9!#(EKDC5JYYY=nO{4% z*IsBD_%v_w8a8mI@;=<;EA3lh}S1o9Z*Hu)_D`g!H3$Y3|4d6lntP)+t)0l~Q^=ExEWw zL}TZIJ_nD_1bnp26p6)S0|fLh|f0dPTF9 zT(;ZfPEWb|nY}we*GF=*pqb+SwI`;lO1x#&%1blSJ_{RB$d@04*>GJQK-@Dl` z14|iCb}lvbB!)FH3-ZaG_*2&lu{d5{cVg5bl}?~(#@MVod>KG}e{^l^EE87mrjkBr z_{51mw!HLM=Y1vWtbH4}JZ>gV?c{&FWK!@&o@Ve^dTT?ShAmTH)_Oz;&R+`DsG(bu z4lc)dmPSHg;A(gscc=I~@+4%qH124Xw4+K@T$YFvA8~rb zeV$-sd|Vmd_I#?y_pV)g>oLFu&~Pa!1oxy;yyY-ASeOj@_UsAgLr+Z{AitHR5n`4lCWoexh(r*c%`L^U?O6n}>4k;#&on72{*Xf}B~7 z1>Vc~vOQDpP|ON4r?TWtC@GH}bRutp_~Ny{I!ih<0Bn29y!4Eygd`@1X+qi!Y9h;g z{=d~M855 z=ua)g(J+Cmu=jVEev3Pa zzD9KQ?ncjKwWBX;$HvFo;%*}-(co%+&CR%vo!H%4e%ucV2eR(LpYv*7g@;zfTF6ET z{9qD@=@j6m=$gd#LUX(g%(!R>RvptO@``K`9d_92(~NHx31)rIyg*#8%XF>bQMbmY9B_3aQ%zqe_EF%Zd@S&ri@u%6raZQ@4Lt9N*T{D0QC= z`>5XJR*grCnH5jS?nG6q5HqWQ>*(JiZ*S-poc6S2CE?887irzEP_~_>$I;nbtXzX_ zYLxB?WwUC^o{X6^y)^h;d1~Tsk@+GAe-Y3>7jVm<9oR&USI0%vCCvT%endqU1XXk_ zU!}8gpB>Y=oSQF9#jP|rU9$p>AoQVE3B0G7H&T1P)4hVH%tXCdcP2LKl^l~(P@Ne$ zB&qemxvCZ7;}|n=DW%yb{Pn1isomDcbDvLH2y3P$CNlO~oup{`AH-W!PBy)_H`cQ9 z*7Ro@-8M!SK=U=nVR?guW4*lkwZFDi*I}XnQAKY9XKJ-SJ&jsqblE#8ivAHgrM-;+ zGqyF=4^cLZf8E?%s^o?GI>&(wXMN@wysp2I;<~}TpJH)=dXcd7tz^l>pQiars8o5O z>5;csbT8V}Ae-S!r#<{7o;%agzQ~n7;ZJNqsc>|Mr<~Eq8nQyW9KZYhw?2y<8$Yt| zf1T4}=H45(2E#t+{fTncnTIu?O1StI%<=>59b~6lvHOAgPo5$WG5PiruOaEZR`8|?J6hwsfX>Bn>9)HTxrTTbbDni>UY8%GwDeA z=CqtX{vX7)$Iq{+w=zGyamvK9rZK%i(#L1)*nKS`aZ+#p*~tZ2Lde%zJB1ak&Ob7l z@$qc6@*-nRFX-#{{z1I6$Vc#r^ODkpy&U#yP}F86g6SJO&K+&L7DwD;L+7{|OD*g( zy|H_-KGgqt?rU$Jv8d)O5=RHhJe|clbnz`Zr^pui|5(?Cy9U7R%sJ zv^6*_8a<9#d2{>s1b+3vNuTh6X9PLtl{7RMWK`r~=~Av6e{yuEfM-C1^n>pQF>hw&tm?G}l09HXrL3CA6Z~&26Xp>7;=Bk6oPp}x_axcG zB(h-3DHezLfgmBRWBAXW+p7$OI+?)ET}tb-YppMQ?fqDi`RWw1z<2*{7I{1Lip59! zz*6p0M^&~0B)3xuvx#0`YVTlw=J7|J!{whTuW0in6*$Uz>K#!tn}m-;-2?#|h0+-I zhL;H$9duglrNB_!AHt|WfbK;vYRiEUdG+jeqd zJ14d|(F7;9ZQHhOPV8jDiRb3Odv|Yb-Tu;FySjf>{XXv_qLZ;4=mtw=?ha1tH?XVi-%G0NADGz4biVam=K2F+H^6^GReio4y z@-v^xdIVoohB*$MX;QH#9;ZKfYGn&Q_vJsZ`>*_dhU6slg;Dus=dbOU)}NuY#*?El z_r3dy0ZEyL`eq;-GR2Np$h_ZIK^Zgr$2St*65&zuI%PkJ{sC*Maz&B~>jKvl2s*L2 zZYp^b3hG2`P%UL&8iu$^8b2j51e&eWE4>YX*p`ZL^l0|^xid8Qhoo;Nlc17`sZuK2=^X^>3ptks-aa%)A>PRQ4wAVZ-r02`pe>7SHh3*pM2Ml;H3BP<^@@ z$4jfBaPfLz{}aY6b$r4S?>*#45<|W|Bt`bnaa@W=inEa*bI5h|(2oQ6TELBJZ%~iL zcpmvyLSNzXJx~)pn>0;3Qt9GAX)h}o) zd1^J9p%uP41!8BrGgObUs)kt=LFT~y8o$kTMp3e#lp1AA%^CC1EcC97TnvC86^H)= z5QuOzy>To;DLDM## zZ5^Qx|L82(5A^?nFM2iOefjn+N-{LX!K@Zj@s0`5dK67T*F~2tXD6kG^Q3bk4yyg^ zc4|r(sEr7wI8TsIz16AJ4^rmw5;7{sXs!lJk#l*oj3a5rJKXp7l2}2we_q2_)G)=7sJUe1@;QcG zSQe}hLgrt$!M^}!x1)|uw0_YU?ntSs@_^XheW1|NwE6t{Nx=%I1ewjM@cU%qvb{1? z&gJ$huG+kFy@cWPpk9Bj-HkxoC;7J4Ky1Y1doBsYy^q{s*o1;=FlUCh2K7Z*c}bW< z(l&YO5>wN?m)xA|i+R~EJ^VKuU}}J=DLU7Qf#S|1Z1a^yt|7Zl>0+>4Gn)a^besV% zl@QN{dgjQ}X@t9mPKj*s!0#?vy$GOFRP*rQSft6rmDxwZd_yFU(b*Zs>F+z_%JIS3 z>y=I|Y#W~9^wDFuKDn#N`N^X&xfTO+`?f84K5kLe>wjRl>D(WwZV(FW;|1`6HJKtr zYuj%Oq4;>KWAM2LV?!P$>7Hidigd{PTgA+AU?_P+{OhVOh>I8@H=e8e28SrE7X%@O zg0puT3_DtGgwg@)IwY+D7lNW44 za}8}A1J(Nqq1z+d7mxamZ^5TjIr^wVRo3jGu~(@r}9< z-_gMyWi+%~Czz5BiJR!v84bGIh#ogqES;~U#*@iI3;mR zK0Q6ndQ+5FoqXtQcr}!9W&4cq8pLmqb@1^HeR!U0<3f~vxK*kG@KjPYNr)lejek;U z)1u5$#1Mg{YqKXRjrH$c3l(M&0+V!`u5Vm!; zgerq`adE-2Al~IszGP-rEOi7mr&%-Iv)lcS-avU{`N4Q4kT5H|*>4vvx59abd_^P& zXSd2+tWjB1X^``QRrk)YAeUsyYT*g*1M)Evj)bsj=S9WxYOTOIrb&a?ihc0HIUz=6 z3g4vm5IFR^JO09TIefRe8q}z3h8CNHldqL&E}F~W%bGNt22{Zw!+7gDJm1%wI8laC zXsedPX-uiMzfC0-M_*w63{u9_rkmP+ivVY4+A0SWFwdaMW zQmCcgIw_1SAESII%p;ft;iQDhm!P9Up^C6#oS;Db}nO1Z5|a&8BMw@Ce`*2RX@MN&l=VM$Aq?^NO2usG%GSk z^EBK1A)ZiO;bBAonbtY^SNEm!lWDnSLTYRj^-t?nz&0`R=rT3WuJkL&^=<=)s7g!G zK6!}?d(6c|i;s@V~=}v;mlX)of494>! z{5$I;R_je;H^`_1K=x`_GX{uBUhy|qsHms`BIeT(-W7FR=ZLFV`gU5obv#S%QZ(Egi49oKz{KcPL!xjuuix-iuBI;~2`de*}gsghF1;mSMM*GK3sK2zr70j@lp?%O9aAOSUpwe+c`4 zA@?Oog(yq71v?L_)Pw$-xbXMmmJDnA*M|&i(@aFq4;!6T5xylZ#oAuV8!ofq;Y_H!$y2`7G&KRdT8gst+T{EGfi=Epw2oB|;j=pJ6N7>&jFIP{ew(KL zM;|?MLN5D}?{R*uKP|^rC*;FB<>q3`DJFXlrQxw`Tg?{18sdW*=tDJL_^sk-rr_vJ zh8CVlyiBgB5I9XzShdK9W9YcVmZd>yWA zH46KmlVVVPa7Q z;7GO0)1;0b78r>3sO$}DpT5SNXV8uH#L1+da{PD^NRE}U?(p#cu>z2LkQM0F!WKA# zRA=~L?J3X^iG-)djB+xN5e^bGjKo{0d{l?}^p!_q3EB>;^S}t$OdyJJ_Y+c_{+*HM z|Au|TgrJGQai@7<@(cE@rrd8P+vPv&l>dfb)xod}wOYf&O$MTpGMitJ9=D*d)WMKn zD|)@jdK>LaZ(MLrC5nfO2$&*dY$Ll8T`+{?EFEAy^|Q26+tC3iY=d1*s*K;?`8 zsuc$gnz69Zn(yJ6VS`HnFw>yzb$j0e1EM?%7{;9=PKMoc(#IYZBZaH?`HR&zhw-*; zWwwtPJQ*1RpU^|pRRU`#wHSOTEJ_b@d@KKcS4G;ksQ3wFhlOZNY9l_Lk{tsBL5tKR zK)%QSIL8Xxk$kEaV@$eAsw#2Jfbr?}HNu@fF+07*}D6+r(7D-)&gby&aFLA(Xt@2(e1{5GNmTd+RtqPZGAw9d6r)659_1eCvS zGjM&#>MA8`GVaqmc>l6#10}7+$P%#TC@w}N;6!ZSBxDrtCqyOYM{(lQUvYSHjc=Ha ziFIpH^@~U9ERC%s1v9M7;0j_Z*^+Nj$^0P*k8k#XqhxCal}R2JQjAC8VWgbv_Z3Ir zZ{eHbF3-C1w$+SQTYipV%>$G5w%0^EBVJIdiC?8U@OgWq5%DBAIe?tdibz?|kP6Wi zjp~%(J&a@O0`_P?Qeo#Kd(#8fdtNZpZC;GDK|uF%Yf$lDUPFwK1s@D=hyWa!q}EHF)L0dwf=X zMY1Ys^1(ndit6cvHnh7lTtDWcFny|$xCBYdl{ncV+*xjvFy!QF>pzLMd`JeA(NB&` zjfo?Od$dFqo-(@*>8J>nKzfH>U|esuBXU%5Am7uNpd>wNAFcZ>__aG&+5JpzZvw>i zqf6Ayi2IQq^0f?)k5-8x@pHRpuV~lWT0alsujs8`EUfT%3#bPYgqb!$(vFu*Hi(NN zC8CpZ!hgp!AfmpyiZ_{yC{fQWbBoz?nCeNLOR(CeG%AE_B$W7Uq2fI=gWI}y_J9*P z+%1Ut(WfU8=H)?6w&oP}7%FfB*r~|j%TrxDGb1UAf)}ynMCFMx+2k?ff6jbj8P0Ux zb*Im;{YFJ2{zH1*N6cC10((kc1dttUI1bA;jx75hnBq=BUVhlY$4hCh#yNbc zZ>0|Lp8{~^rk8{bvEoZdE_kWr?iZQObHa3EchGqpL;uIdQ>as9_Rp9rEO+&i$nbZR zvP!bsddwf;VJ30nQoZ{Giz^0|L-2CZ$I_l1P`>`LM+sEjHOY;nTuUR-E?KMQWf%~k2im~NlNo6(Uc(q7e{>Qs;S zVpfVww+yvEivQEU#jC?m5J9ok5;A#CH!StD!?I|t9D>?D0{wdf7Mi=ounkyNA;d1V zySd)f?TTFa)40zNYs}g4qIkEuYJ2q@1I<2s$2g5C9J`yr&}F_(uLU4;sK_~C7n(L? zMCfQj-J0|8@bK8MBPlh`ho0ial-q}#;>u%ohsl4(hS&2o}@LbL~*ikufb+ z0*?;?+!S17DzOm|)nDM|t?=^0+*Yb+ZMxq0+(D}Oqqp#g(P>ilt{r(H8^2C#<^D^9 zNTSbr%(Tb=4BR=?PODT6QhmI>xAATmH8qdR?V(DNgOpq*xx7(NjM2_dq}Mo3N}zE1 zzP^qjw&^YjDfsxU?6?{te2mwwRr|!1baziGQo9nPN+fq@S4{v^lg_yBMgz~S$yu!*=`e>(E538o`!xXsnCm9hdsR3 zZC@jGg*;S*eLgq3h~m>8>cGrGu=K6;@wi&86=71eG2YQ|Xi7y982Kw$Y+r02+&h>D>hnJ^dsI8P2ESF*O}y06 zl?vU;6cTheFFZlF%-4so62qke&C|XY{{i^aPr%)Ui>TjoC-&;#Gd=VqzuCKv2~6LEtPcZ zi<-2Au!vbCE))$21?9qHRT6L}X(eDR@+#oSOj_r^Kdj&Q`0Tgk?)Ll?QI)V4Rs0x< zs|4#?v`%EQ@90_QvT=gIAiU&xJW@dl!l=k(MDFku-Mxn7;JvLOI(%j<^CUWMlKpV4 z7_(tqO6GJ^s1To&R6 z{N(4RJh4}ypx->$|G@l5{;(OAXOHyB(C^m4F+QD+YzK->@ znR3v*aQRkeY%q1_6(^o24ZFa~n4}EGyq=k;7G&fn@VcuoKuM24(sWGUUT+>8z*`}o z0$!(rdmYZd^c1aph-kX&rNr0gN;hDh>0%)t9=Fa@4d{A_|k5UOIrF?Fo2ahGC%jEsHGW z9!9HK)_#dj%+AL#F3tG_Br!B)(k#c&C0_X}*VPE)o5lrye57l{WU8pM zger>UTT=|f!PeEQr(3o8ehz%4pSD^ro+CNr4H~h}oPH|NW45JW$G&}4hMU6K6-N?a z^=k5Lku9YGDaTM0vAdx?!Ht?vj>5)|?nJ?bby?0%JG4Pju-Z}~W6Er=r(Y?{=<+C8 zyD~GeX$jNJsfCp3S}+Xl3f$WdYF8*Rnx}` z)oX=EyPe!g(b4sFEm{D6*=13RHeNY8C1V0yzwXWFuPW=)!r(^K-RBPnEXh7kjK zno)-P^bF$pnoaKWnMP@$+Mac!C+mFNTc{z9-N`UFk%rNi;-MK#hd`X%qnj9ko5-5( z==Kl_37hlIUO}1iE{F~QiCU9Ve0$%6&7E!RfqzEWgI$Gb$w9$Ks#fEinMDs+8>JH_cA zBN98uzqj1&fxo9d4jDRVb=Vj*k!9Ksr%anLa3YvB-}zcEKRITrj0t%y1cOJ_tvZYF z>ZH4cKjC~5(m4_?MM?67i_xVyt-HaMR4|qnAJpTYkXnnVu^)na{?z+O5d+OFnbb0R zEQ`JwSXiDyoy^E(yqa&0wP`BX_rzfy%0LHHo4wU0>aUMV6K0Vi+C8| z{iwaOGr2{>IX~B)nCozR=NbGL5-MUv7%vntn@_A7o>DAZIAjcQU-)Aaj@b|gDC>UW zTzJ=;s+2c60&un?izD{^CSN?LFQ(L9WXn9<^BYHTZdTbt%rB3kg#B%Em;a_b5u(aZ zKQ9j*GIkVzgFoH!Pd<42f%NtMNC|&9=#8$$ROynoE`I;6!o;^EU9n8n%uoSl?3$SA zPEt+~Q#iX;q(JEqj(>OenDWBo)p2E9PM;Q1qa+KxR|+0>!+G*|Hew@8aPF@dC3(E?rH?gVD(1iuejyv0^z`Y6XE7p1J7=1;Cnhni--1E2{Yi~ku8|!$C zrAVQkFD~#FlPX8Tz$!)JjE6Jca}=AZ8c#4lZk&UUkn9XT^A6|A?*XxdC9{!5`HUgM zUWA;?rS%7@$~$Pd7l4j`r7~>| zjUD19E`YM3X8NM02Y6Yk16Yh{P9^2bFnGOf*YfL|cP~!&Z2OgE9}YIw8X1-QX6Zqm zm^@&^B@F_OyXu~HSK&euoafxTX*9HKPeqf<7vK=QKKRTArrQ%du1%Baf(}CYDC5 zU*I;ky9OUU;VxNG7u&x{hAPY9B&R7xo|Pq*V_?`GH5h7V?^>wE|7c8nWSxA7Ej5%t zjM#k7Tr{x~XfSQYX)apa+{d&EgDDeb9dg%@ccx+)Ti2I(m^ci!NYGsW@a2BwXYSKb3 z9CvD$&2hr^eCin{v>fHK(%#VD!2+)~nCCAdw@O36SU?!(Gns$P>AQU}lN;9O zw5QE^{fxIzHZn$256XGGr)%gVj(vqc3WMzX0LxAw>=9+3}scJ<;IqxfzC6ylXuG* zPGM8$4AzmO)4VYN@kqwhvk(7Fw98IWB&{k4q>)}+DKO0Ydm3YZx#bQFXeeVtAslbx z3;!rx7ZI#{FdnjHQE#OL3g-Fom1)={XD4xTW=t#{tm%E_n5bHH_Z>}+5R@6Vh<0Pi z9mVv+%4LM6G>lGBLZcpQ%zsBDF(G$XWymtDOs%YJs1`-7;|aHwnCy+XWla6yHhZpG z<5g(Tyjg1Be6-cs>e#UzSKI(2wf+6V*v+QhoNw+&yVyrhFVJ_rVdcvaQ0?1*D-~+7 zz(`eBXG{P4n6aDyZ(>ZnZ`A2jPS1o)4-NwGADy;fq2rS?DL@s}7`ya0wK9PaBvHU>wILqYj?d)mX= zlw5`OQ|PjnP`(5vh)~6^Q&v#xpY=mv!r0X^gsZT>k(EG^^eTPMONS@U?w|+=>W?W| zBsO0Ja8=)R%8o#zw-3({mEOGyDrpYY*+>BF^GUQ`QihaP#bZr#o3**(*;pnq;oyi(?6UQ~Ns4S4#_kZCHjMJfR!jc_le!pZIZ^Zb z)w|?Tumdy+NiHCt-buWySjRbP-VDObe!2|O0rFE+Y=rJ zl;~IQeik@_p{Fv;J8_D#{)VA}i`x_YBP`w{5M%$f;+S4;^(bzKeXVCM8+P$%8EILj z?zwu&7B;7p&^LZk`G~5x%%mq$TZAMS#c8*~nR^HkhF09QeMSKTN1iKYK9~{I7^vRu z^w58RIuR$F1u>lHlhh^Gns9tpH)5sZNw#R;3-SlfuF@o9S--Z2AD$>nZj=7S>Rt|s zfO<5{p z^JeFBQmNiA;qB;@s-MuStW(m{STplFO|>@#mRopWTDj-}p!-JXo+!dm&E^pjc{*DG}I5(AZL1u7X9Rb8guD#Q)#juQMfLw6+D4x z?vy5g10&rw%@P;#Y@Dd_QMEj;zbNY1H>9$5Cf)`B6KRETmy>F~ypUMiLw@yY2%qJQ z;B&#3jCvHK7ZU%?$D0wJ)!g~cAhkvFpo4m4l>hfSh) zdZ@KyEF}Eidg669R)x>iw#pq%w~QvyCKFw6BT#(Luc{JPDBudfpw2XOmYDD|gQFrV z-%B|sm>@(EPbtZv(*jmxb?{mX^C;|=3Bx*5KRIfW{?aM`T@vmsWBpwic0p1X0eR-l z_d?A!T z5?P#LDgR;-NushoeNE%Y2WLq&Gt%LY`1nlU{=rjb@$>ZjdR;5VxJ*|a|0utC+B7II z&<^>*Xe{q~w&u@PA`MPW)?Me@ zITf*Q;VFDZX~-q@#b`(K$dErR-wm-+|4_6n zZ~UIm4Asf0PGAI;Stk-3sZ~B=2;j6(29VupNZClC3Nxx^vNy2Rv9;)REBcwne55c- zYSq|Zs1vFcJ9tj$c8D`(aobKtP5$l zuupK}C1EE0iSwd@GA2}Kjp2xFlaXo@@P?RHXy9N`_n)4vPYf{vM$foIDYrWhJw9}@ z{ZPR5-E6fA=|>R5l# zkW!Yv14q~HkrBOqX-o*tzt#r~;n{g#{KI_jchwlcur`Uvkr}ZE(*KvB(6@<0XZ*j3 z;lBr%v=CCi1RM5$8wvfmKDZi(TJUGm$ZZ;O#LJb>(Q1E0!AMR#$*WrMA7Xcd(zC3L zCjZ>V7VnnD@h6imv!V0EeML;z^L%&Tn@yIGL4sB`BZ^+NU}q;KSHL6?p>dZ9Z1d*4 z-g~Sy)#1p@pVi}UI9{%ab#IhrBXfh;bjc|nGEk1t+*47-EtAO}RDE5y>lC_|4iXs6hH%Vl_6e+xV}(1`qAi z9}d_=EP9BT{qt}=U0H2Rmff;DtVHvA;qQHf5D~i-cbq-ja}Xk*R#N?EU@wW;49-HC z68vB8oJ3QPSAI1g71)nLbvY=z7Z)(pBcfI2&iz+9KW}eWgLC(L6ZS>x>og^3qb}Vj z7Y+WIoBbB7*OjYy$?z3c6)r{ny~t|y3%Vy+N{gYrLo!zMX<`jqJMtY~mBz9oRjQPR zCOVM=oGtBL--ZVtp>ut^h8g$sSZ>~w1W^cBEF{F9?NsO8&R8V+i*v(AhO3kwH@Gzh zyV6x(zQo6opu1Md@W`Gy6DG{$8n@Ra8@-g*cFVHyp$VB0#JNR8zP2RKwc`lhsSnNz z6vSHHWkl`CbF%ZjEOQEd`lh?*4AeVOkaZ4H)r!-Qo~#sgP(MEZ1c%SJWtOfe_>K(c z1`Dn`HR(KMS`2eGrUiQg#hBVgRen28lU&RZPPWxvi>NRvWi-N#F|vXL075IZbGDnH zbb0`XJRr3fuEPe_HQ}7H4)}EqJc|4vcI$J^rw)+6gn}!pm0wS+PZ1BhFuxV*S2~Sr)U? zRIX0mhMcz0bF*6UO?H}esDHG+jPBk*!?^D259Hp6?% zsO)Y^%5@OLT;nhWM2ke*r>qkGh?mK*TVReST+in7+7~Z2GfOW4vG;UdPi;Dy-)4e( zK5SrGK2$%%j_cpI7-i$DJr|ia(psY%FV$6XnNFy>ET&l$GMuieTw+a7)X5?OiG2rT zsD_n)Ph;)Syb572Pqkm1)0}tKwKYGHH`zkD3AXZ~oFi>hN1k%<2iUa^_n1|}PE%a{ zxcz-iijBCcg~h%9z5Gl4+`m}9DUjeqNz6Wifz`00 z9X4IbQllcO^Lq!LV{zqHSX{;W>w57YPYLBz_Zt+&i;sB^h2e^ z;T86&N|lu+GF|cQ6r)%MfjyBGTwI*5UQ3%mT%LSuz!ggB5W!FUFdX{psGCpg2?n4xj&fl_4bXQ6FF$CoSN` z7CBZ`a2=fpRKkI_?sng!=+Yt-q6o!G0MYd!c!_-KT8Pw=B3P!m~)iAeD?0Iyu@$n{I`0dwhJxfO>~%`=N)iV30Tf^rfcN?P+oc{4v`2S!8J z-j5}T4i2^~vP1r^$b=!@s2y$FmKc`B{vd5yW6DawJ zTn1~!-a|;(h%u&-X8ELih;y%4b6KU|NzzozMl@uAr#sr{>EgQQ6{!o+0FQJ_hr+fw zY{w~~Yz+lpP|}b9oTON!Yan0Js}gzgJ=Lr!v5b?lnz>7oe%ihK(AAi2aRlT zH|u`Om9N-UF}n{X7to79(oU6WAzW4C7Cx9(XNX65z3CE|MJN4kKT2Rc_#i5PUmAQbaj#z1(n5mveb)C%l{HK|3Bdy{kXY}=+hO>DFPKN zbm4JRs@pC6xo5fvd$t(3sfWr`putB1S}uIgGttLz?$3bfvCWAl!}n4|Irp*}jr*5K zRoD-6k{6c5e_$CFrT&cS4zM;)(b$-E>m~`C7q>v=1pTp`%u&Ahx#hSDi z+vA*hhFh}fJGA$27+%@=ts{2=Q!3aOks~XGBXbTb2lW1h6~Lo3@CtMOR83a@_)0H` zBQRR`+lOC7qm%@+&#(_qSRbAKJN(zHNMB{t|2<$c>%hQU%<~{<*GhJ#*J%|O=H(TT z&$ETyHKN_1#(<(twz8)>n|InJD8`7XctgQHJSF_PBl1LlUsf;Dm-@=Y8{$4>ER7?c zu7%`n79wV=|>n&P5Zyfh_@`Uh5J@JZwwS}Mjzk}?>q)3ShtEBDR^TM2Xm|;Fyq-U%B$pp9=-pO|?pdX6M8xU#H zYFMF>Z^9ZJAFf(wrP&Ap%#F<2(nf#QTS&2U2Oy);#vFX{(rB3} zzS$c(=^dKiMK|F@cMoLOzi>Og|Ler+s%EZd$Sz;VFpHbNG%?O+gwQ!n#06Jt`SmV< zF>M;9k=S!|%HG=KUG@kT)(NA8ZP*H$sh1g^8tF`OnirH*7YJJywDK6emSX^&jA2r6 z5u(3X+0Ev$=!yfi({z3f7MCEpp*k=ob&VVCo9U;vFH!q9l@)kcCPb%h+1! z(KG!Pgu-4dPpvgsS@Ym zq!A+9D&1cR0l~zCmZkHCD25M3mt-ds&8*|Cj7DxNaSq*^x)YVX5=P|saDzW99H)5s zF*Xe4F@|H~TG?DubSXq}_nglpZ?otBz=%B#%&Xg0Fi`oO@DatQ-h6_00_t!&Cb!Y_ zs>?D!b%e64!x`i_Sc3>*maG*cmpwDfWQ7nyM6ER=&93)`ZY3NGhW1UDtj&v3b+NYd zlzB9aX1MK%EQfwkI_(@Bx_sd|0BoxdL)U;B_1e}=s1dd}mY;kK`h_=JU3%MQN<*KN zv#}l0Zghif$McCe564q(47lhfW34HFE-d)z6B{J}k)N{yLIlm3gabQCIURBhl~C3I z_$IOhhZKv#rUQ6-Ote)6$I@Ti`$J!xnBx_;AyRj8W@ti9LxFdE1{LcO+)F29pA>`p zZudJ6_DtLN)NeGAPhjEY`n0U{#^Z3EIhCtLo69z`ipe?J`M@*IhQ-ST2j(QgsV}dC z%=e~<6@FD95nPLXK>}S@&jU)6O9SfVBeJIoJ_Nra1{lnr|OD7)_ z;-c%M+g>|dN|COvP?;R<1i;*ohbxzMjVS=xY;5a&xE7J0c_8+5rTnRFaRUAWYZ3;{ zk(n84AcSxVRjWt35N0Yp!eSc}rF$PZ#kjz?a1F7!!TN|K<{$Szh_w`YRJH&O2T$b- z=qSD*mOIF%Syd~FI=zEsg-MOGE^2U=4tlJU1>A`_$uET%MD}3c+^qRx_Di!xMJ~!0 zzCd}1{CuBevpsc^1nbCS^6Sm2!W_}>z>H(PTEI-#e#N99nvSOMZ^qUwzi$6x(F?Vv zr3qb|(6YI`PQgkp?pe{sj8oY7E)ibxaZ6BiFvx11p%hw5yTQ7Nq`?^ci(yy7x}0%U zVXtje@vg^|nFU0UJ&>v9V<;F!<0H4G`kJynGYVWqR3;*xoE( zr8oXe+*KqRl{eEOfL+Qps$F<36lp%bO1Hw>{)SQP*uzFHGUh(v9b9uMM~$<*IYJBS z*k}<0H$#)aidk`RWynTA)g<^nxstl4Z)`xhZG*idHJS=;0mZ;cYfcw!?Kd zMzczN;la7=#4EJq_jhOBmwz3aq0MHsIbB@# zaH%L`4Zw`g*cF`UR8Vw5b=d*# z+I{62SjnDsFJ)F@gp4d6P60Wzr#l^rztuupl-CSwX`lYOV_O@j=1qoIKhm0a8>MnX z%lt|&bxuHD6Q^b(f>N=vJpcA^|2rE{`7qYmu~k#TyZEkm&$!9Tm}9+l2cRY=v#2rF z9afy#te*mDEifQMMcJIThTGi`5V}b71(3L)x_**uZ@XTA7iUXz;H$d{c88@bWq(gA zvlOR{h$0;1?WmmC*WISlVQO0DoQ)Nx11RGh_drEvCAuD_Qeb*Ms>g^z5;4uLQ*B<6 zJG#4HV1K|zMl;LXIn^mm#If3T*#Hq2NnWFMD$X#b_R_IPA^>zu@UHyAVDJ{lv|aKB zR$bfs&KAdRz23i)#9P)ue^bl>V0iO=sf*6^&PJdyjSa z!XG#s60b z>b|bXwb)$6C@cm#mx_@_pNW`5ox{Rn|G;PhU(9x0gcPr9hc+efg&bo~%_E(Ybso%3 zQ^Moj@Y*BYGHAXL972MN?@$UkLc;oQN59=)w9H(c8baS$xZh|$X+rBOifAe3t8+9Y zs$?qlhPE3Ko_aj26Z{h;!2M7tm-MZuIgF8h ze1Kt~o}LJs3T?`W+884Nk@gKm=4ig+!r)$4n$*eNGgFCXVz*iDwe|e9TJ7F=OtG#c)8^(HwK!Q+={Q8A*eg5+!GeCF zG3cS3j@2pW!jsh_r4POa-!jvok@^ikSI9$cqS>umIMb+KM*jngpu1o#U&|n*c7FJ) zD3YaI5#KkdpjvE(jYct40#VWA(;R4#f6SQTy!MOU`xciwjMlq%^1T;GX*E``$INbb z@ELG?`Rb(6bFsFU4XR9mZ>;x5);X$4!03cHFLGp66kpfmc;h-tD|}yCws>Tr4G|K} zZ0)-jT$*__L*9>(e2bY>_s6oPIRgGh3;sA(H!qG?tMXV{QN~bCrzgphIvEPl9`Y$b z$uT4WQ~wf;)u!_Jq#hOR)~3FG(APBwYtYvY#*GxXfTcyl+ww(mM9K zH*@vDatl>wuJ8!Y)BA%3Zfswo)Be4P0aUFrm`sQMKZc3_tAzVcRhw%TkRrOZU{{QO zU|-2YWGCyUHa0}w^a+@9hF_^|Vfgc1mL}RPc*|Gr7=py;1o4QKD^tXp%f7?$m%~R! zc!ayZ;-TeZb71z9b#Mal$Cw!=$n}?NwNI6QN-J_-BBtF|e(fu4Y7AXiE0cfz4^`%pLZ6`0gbpif2=Ab=#b$BFj&#fRL%giuJtn#U1$hECr)|3h7cnd|` zgwdMLu*nKa?fD0Wacp(djs9LS@>M&8e1tPZmROZvcQngU-M{sG6yABAp9wTF4=)0c zAKU9$6IF7l>NSs#9*nhxj=RL7NeggfPh>lxXZ7X1+#6{40aR?4YgA{jKT!On(C{VmR z|99Tm=j_?@o)70!W>%69&wAF(bFb^Z?%#FBpa1pmlS$BqGH~&uRxtXsuGig;VMVzs z>ORR~*k-@m1@Rqt1KyiEczmey7^HGkI^P6++D<4u69EDDqmOnPiJBA_H2KrbcBI

    T|w_ZxuwdER@Nk*<)W`j_;buI*#(1iR(WZ{lGD+t7%n_hv`#Q2|l8sYar| z8;D|dXSG99gOF+-7B%%0b9Tl2(Dt2+Gii%Xp8yx}>n8zi6oluyizE=Da^)LdeCK=Q zxCZa~ewm%qqDP9IN3YMNZy@daje>DKI;aMSkG;!d zipoBcB)R|aJ|007sc;S|-Jw$GUTH}<`Zl|$whx>m5|-Ysynb#}Zur3DMF#(!IOQeo zS!m_oyui^l!))(U%+}Ge0&&B!n$3=GlO23K@#^yZo9t}d?r<%Q46W?``&vZ7I*TPB zf}Ik`5^laIVRd)k8d7EJ@jJ*=?j^`fhItcP4?e%Q+`XU-T%Afc#w%VrFc)-(xA=yE zc_b93&@ELyU%b&XYk_JxArf3C4o^R?(R-)sZD9NXNVkUvdM*ur6?kxpI@9v2NaoU9 zJ;-UvW6s1)Yq>Y+q}YX3`@?k^#otKHeoP(`@$eCR8jzSqJgc9h@>XLBx<{sO{bU_) zj_gx@m_VXs+6v6d6&uIoq>XD?7FRfPW=~{vc1vt#Y*NBC$C7OnzPzFs&n7yTzRBYa zmedRx&$fhj;gQXCvL(6CRN^8NDid%yahK!PGoRnB zr>5_0A)XEAPqT_kI0iiyLeVdlR?Ng2`Q;B3I1L6X`gTq0@=3EVX};e3`VS z4t_bu#7OuwkyF(5pjfg$yng#gQSq_O|2~uTV$nQy;!hyBW{q{l&{IfRVD-#sC#%{H zsv~wQ?MDb}63T9&?rxvN)6@hz=V76*iSzd_qw*0)@}{u0I+1*C#pFCRpN|v}I8K+Y zcV6GOwXb%{bnpqZ7h%li%}+2UZ)lv9W2Bcx7rtM%menC6pT{JhtookYB9$`pLzfUT z*&DkssWCklgfHMENW{Tv3tv`RL9$E*EDo;nY|CTszg z*7R}3;q0nk{B^@3qhzrmnHXUf7Qyj|yeF92%hy^=^*0G$fD9rZr%0oskYGp>@!9t+ z*RUHO&MR%QqaGQKSHn36bAR!y-z77hK)l_)L0VMmdgaFr&pnA}1m}4Ktz2{rzp3K4 zn+>V*D1-4_>)<^lN(OOP-hFv;9W*!$g9X>_GdDimXqpwTt6{!2Z9Iu9bgh68t_AH_y^AmP4?dzc z#x2GaqvsMMJ~R52T+*>x_#Y5H=kX3E_5??)kozXMN1Hn1r}C^zi$t{OU%Ipga#=*s zw3D+_Tc7T}fN5G)6+}86n3*%7-;BZ-l$w=>)13W^;cU5}jP~w8M}n)0k_O5d8(+*} z_)7Od>$n?br8+#;?&RD~YJ%6ndde)`C|Im-0Ifa$IA zq!oLkB2=11ap_&|l2a98$|edSt;?~dVr3Z?bLMEuwTj~u zOU5?d!r!*@>S(7+I_s9e)>rOHYGnk{iuRdq4pR73g6P#RreXLJvbrx4Q*a45y$D|m z=Y0SX>&ba~07h@$6!P&`PI$_P>eb;C!zOgpFfU;K8i?<3aQ z#muy_Pvw6Tx3yZPu?SXiQa|>p=ubvAvc2Npt0NLTH7Y`*y{%GYMO16q!kJdq(PA7r zyjaQ650m%vN+L>a2st+PEIuKK`?of%oS&Mf#xokZC8%6KkehVR(-5MUg40$ zFWb0esnD6&4A%S2JUdtba{lRGLK)r2Y4Rjd_q5m*x7=X1L;7O)#zb0gY=4nI#Xi~G zNVH}3s?4qs=Qpt3eGR6Gz!Ue5ZG$HBAL%D=SV8V~YY~3|do-np^=RERjF)@AA2!HH z(Ow9m^OWwVtw%~D^i+JM3ez8uz(9d2QM8`@Y=EUrs4sS#H*2%;>+EyP(I=i7_4XaO zZ~3s|cu}%Lk8w^`k1K3({`^B4u-r@c%LRe1xyB=IZ2vYZ9giJd+2WT1#)xHUanE-3 z>#Io!kY4^FO^AMyJg2OcTg`urHi~Y+bKW1n$xwC>#kmY-Pg3P0^Bue((jR~63axHp zWA|qgI;Bl7L^MpD?8<+vABn5>N`nyDOeE(`<=FVn zIVUVo$TXob(MR;q*Rmh0fy^5{F~LwMDdq!Gh0A?p#ASAFW#(4j!+*BVYU?zJIpb=b zV^E_q->^D2xsvpOkzveI(~vDahqtYl;h7tc2SEU6XNYsbBM{dr=@|_ct{lXzpJiK5-25jn8c+=rsN4g#K@IffAIx{IxYh-~L z5WE&PB*)sZ#XqKrhl`K9&P1~+-y@=29LV>e7~!p_KbF9B<70-koA>?ACB-{$E4_A` z8ui5*fmjC2LHhD4y_lVfd&D#nhAi!sHSdsZsu0IKSI8UV$YW}$G5h!ddZrViR1FTg zF|IlDKl&m^$vtGsHT&Hz8EH3+C06fe0>!GG8rQ|9a0zwngvvZN^FNDpc2@aDmM6xv zHrC7ajqn7#UST9)3cGb#5eJ=)5LlpQH8{1L=+b)H>~ue}3b;2*|6dJ@|M=?u>tYSO zB1OLO`F)$!58V&FHEVV^FNz*M=XzM|A|yopVq(d(_q3r&Q`oVqude=5Ga&;Lrvmh6 zc7IqxX#8rC-E=XZn41mt zzIf2=Dt%R4fXtE>TOd8pdFEOrKA?Zh!$~<>cPmfch+DV}skdNjze*>N`STXeFEF(M zd8fYtHMJD=(aOK81E8{b2L#nmk*EE5ga18!%-aw22?-fqFBq8Va=Y7I6w%xH-%CoI zRqAn?rTzjdZ@#{MZW+0uA0wexq@4x~g5 z1gwVOKYW7tk5$+K9jcBoF&xkmtU0?rGkGxY^!GIaD@&`ZN{h-Vp==CjKZ2}zKBrV~5J5ISQ$@kV9pEPot=#ax!lenN+3w~6v3GpmK z&ZLQ8It;z{zi&)xdl=__2tC-jKG5v2^>i<(9c(muMvQM%i8B(mQ-04H$DjT~^d&`! zbM?n-|MSg95jB{?rbLBlaei6}bD3=r|D*HWP4I>LpE~N7W}SpUS%^#NyqvH|qz)pu z9dj~Mn}0~vqKF&6lHSf95Yfu35QA2N(oO;t*sEfA9lGtYlz_bJPBOgHJ#lepZrJMW zqEyFNX4fE`fzh^{caxymO^N8Mi`Vd?Hq76T&*3i$j~L2oxML^?c~>`RxyEuC%51Nv z>$4W0qd9vL;SW=~{;;{nqGj0H9C3Gc0XOxv`vOE*nJOW&C3z#H_a1mbv6=H*+i-V% z#WnGzL#gJaI^)f&+lM`XwTaLdwwsD)q+bjA3t6{o>7`qfIh#|G23Bni>h?`R0H z=dU|I8hqgav*~lFU5@728Afk_z-yjE+Z@RRXsywsX(AV`T9ovy4G&(`qP2&US0qPMPk)i zR;%m9(uo6juydVLgSw|+{rchOA6MJf)>*t{eO(uZ8E>I$AK^sThp_7c_rNqncGdA? zhJU8HH8kmRCyM`sK;cmZxeiy6KRPxxHrlQei)iX@h{_Vo7$o5LQOG$g_%eNgGc6_p z7-|S4Ga+izIQb8`bZjzbT)9CCezZU~mfzUKKIGkMS3NHIsX@PNd$sI})8VZHN1vLN zt+ALCk%sG<&VsDWk0Z)*796zJ+J0x^nX|k>s}Nhhea%U&?-^{vI>bG2TV~B_L2vJI z2~uKZjzd{d_bNdq?=8Y8SQD=^m=y{-yu)*3kI!tJvP_Q6826I|*a8iNODqa)8U@zJ zeUc-?A=YHy`HkWHx#{%VsUi~$&dE{HGDF#)Px>0 zmKRJn831@ewWaDujfK6xTfTieN`~jC`zpkWOxx(?tAP(ds0b9)T^nkGvi zLT7n-zksyOKJF?vu&dHTtrL6c8s?+GIXx{dH#M!>l=kTJN2(VqXYe1=+!rCNM~TxX z!$2l57<{ZnHVqHR_q<*26!;3!inLG25#?+-vrKzc5u5KjGLtMHG3uPG5~-=Bdpc1i zNEEk5UkjSQCk}t2WHoahSn-wCJAudSt8ocHQ&6@j6O#f%ZoH}w>Ri;lJSF{|aVqLJ zzc!zyq>#bP%dK*ep_ALEbtuw%36{HLt#8Ag#B7sw1>-ezZSiX-_48{(gi5ap%{7t{ z_pybdP%9R<#2zW4Wof4qgiUMVWfbZ!U19J6`ybNYUV$Jt)x`^dgOHxjmkb;oF}w?= zAq$#Dh}qFbRJ-gwO{iNJBsEv^u=V{Ly-tMB1F}?1+!N2v+ZAKTHc;gs9^$GK%lrzB z{ghZAEei?hs0!c@3;u`nEiE?n#p-HD49n(4gvO=l{oo@}%6`^s^Khr08BV?Dy?ZO! z(3*3BqaHb)j7nshU$2(t4yXuaLR>}xZY1br8`TCqx-)L;0FX21&cj4=4@cF1gxz1( zB8lY+cgPsq-{la6gWi|4)C63ipC@N24sNuO$hBEyW zu@K%-<6V7Eu|qh}y65ZpdtRYNri?%m5gWioh<~P}mHQ8Ade^sdAW%!?06!9~yhs1x z!*QfMWp1pHdez&%TcYb9`rS`?g9YcSEzXP?8-MzJ2F&p9W%K*WKzt5P%hAdA-r}Yg z36c>z#cf*{q-(g!5((x_TTLzpcyvVX-7*xxe(Ig%w=j|0_FI}2Yw|lPeGx4cPgM!D zrP6Omd*>9^Jc~l4h!dQnm^#fPGP6?TucQRM_r=CWzQA+cdiL5ot`+H&EK8Nm-sFO_Up_G^wXg|`wc}Y!Xc_IC#3T!rLtd`Ug3_OU5fjzO^=s@J-H*H-5@NfV}04VuYyiN0NO{ zX!@!T4dgkvuVXNy4M(|U)xXadTUqawlv4XU1c2~3iGB;GVF*?Bj?fdIz?sciZ7k@; zVV6WMPqq~^=Bfv3=Y{P7AotsMBgR2(Jh)k6NZOZqrKPK4IsGj5IlEfZ>@~lVwH!Jj z7qrHw-hhXM1WrMgHDdf{>)_pLov*l{By_1jK zM#T{;V)rk14Kwb|*y3yDUZ$Yg|ByC@nuHPAh&Lv)t)o64&!{wid$N9^{cMq|Y@Pc> zT<6oPhY}BiX@!q}-?YEGXG~ua&c86A9_`MzRkNw&{trobBKq;=rJVT!6$k$j#C#oVmt~is=!2sR&n9t7R_R&wilGGb3@!a~XyX#NKKKPS z`qqV6ik+!`29hTI(_mKRw!Hcs=s47+FwU(Jq;Rq#Bu_T5ShcD|w1n6P= z`=#|rsuej<{J}Ex(K!CS>a2>2smUol!A+*5kG&$bQVn%TB}TW#80LFMW~%%c`(O+@ zy1zd3;9xzsi(}u*Un;_1&%7cQ$2=Qlvj!ig{GOM`7>Q8LO*%P9gHrbwjzR+uotqss9^tHF;f?E_MD zJa!LC(PynBBG)Z2in%}nJ+NZb)f}xRduAPn#TutPtop@mVA^hHBGJwcm;GujyVH}> zs~k_4&9(Z<)SY?o+zM0?9t zPdV&Q1)n%zq|CT{r&D7-O`Hw5t0Jx!=V{;vry7ePL-v;t1e3gpFPbu>I2pn_mg!a# zXiEET_>G6nzyb9Z$JPp@o35h~CWeoU6;m881Tu6D0cQDh+Hv^J41&e-pE7X4^7X#&UtuTplyu1*z|j z`!4o6k+p3N`ebX%BF%ga10R;Ch4dVHB)K&4S(c8zXGgUNx`(FfuM4^~e}CbJD>=h#3AJsevaXCdm9nr;yHdY#jZK z7X|DxxYZPsj}J20#JckP{~5~o@0ZE{{;2*l4Yz2{bh^F}^;BJtOIXCyYApT4yHEu7 z^JBuBxbF{Nv z!#3!Cx0t6EUA(-V%q>l@pY>BJs4|FQ0?tv(4>#}l2lrmb#aAjbaD25NowFr3X$jnl!32Y{@!$Tp_)B2RLW@-$MtYl&ejhKIKRefL9eW3;SxUQ@-vqJ_vqc|DqDV z%t7K11&}dS9Bb@W5(YS>0b|bKQoOND$)BWjo^=9MP%rmQDbMiQD6U9OLgt$PVyKJ6 z=NbEbY^C!l1_kR&J(8skgB{+_5{*8rM?7@~2VNa%afBsH>sN(P2!SQbf`V0{6)im@ z3pY(jCVQCtxB}UaMmdotQ2+LpJ)s(W2NA+4M18RhkAASHdxXPV%#3C&&?h}8WngyEcry3kNO~*VMCD=kv zBI0;-zQ3;NdrO||CdlQ)Mu9!GCmJqu{RimSXu_fMQuVgd3Kdh=!o>xz zZfaxyGllgUtHZ8p&{NL28b>Z}3|0Ho9zOC@@=fL_*RSJBicd{KQ6b7)8o^mc*X>dc zl6v{H&4Su{jXMm34SFoMzo{=t?g39xnGY&1$ItgprpwRR-Sp3F*{0ed%Uv>_s>eZ- z_tZN!GJWPxbSQ$c=DQm`dzX(sTY@1U>&{$CQ?2s^YV`RKJ3Bx{Hu0eHMK*Y#t&Vtn{8X-R~wR##fuw~FLa!n(lpu) zbrq*`P}Zk)bK9&|p;Q7SCg`j3!}F4sPn~{$g0bPh&AHc>Z`TGxK3mE5K!%EhGN}uggG*WD^BE@c~wwz1Lk0;&6 zicg~ZG&PxQv{fE-8v zua-;WAsSa@2stY(*vqD>G9v#$o}+8=8N8gK5^4UmD4s&})BKs#uXwXBo*x-^I-T3Tx7&Kw`Nbqp*epJcKEzinLG!cZ0p&>lwdEhBBJg=f=>5Naw) z!$j1q9(p$}Cle<51hv~{Ki!q^;J^m*9c|}mcXw29_%dCQNB$w1BWs2qPnR!s&jW?4 zOJl)&1b;DLnJ?&Mv258Qs3=;j`=c4>TI#0x?N1okSm135;O(^v((64nZzHNHL$eO4 z-;pdqt^1y&&F^N@=>L!^4+N_3BQJL^E_{EHY2D)p^PLX-cEwwnK&KXy-pQuQGhHDk z2;Nx!hlJb1jk_R^9$CE4jNifozsE&WXNaF#y=Yp%9g=*5>;6fIX&JaS)UqvL*Vp8-0}_M z!x~KGK7===r-DXKf4DtZtm1`yydeO!-1ym}!6wcnsfaN%3&Uw_U!G)?l|B+mIZ|cf z4HlI5+WMfS+hibriL=z~fva1vS50Ip@joVp5QOWK9A!e=Qw{v-Zw$tB)rm~|mLeTp z8S#&5Yk7&rUfY~wdbjj?Mj>r zK$^rVNU{@((r17ZGCE2YBscg-T$#oVoEtYwWNqY#tJ8VbbYBBUih<4+(tZ;8xbEU{ z`>2#Ngn1^jL|RkzVm{<1g``T6?#@n!S?nltnzNydUjU28fN4n^iua9`iKqMUppBI_ zw&VBT%wM}+Iumwd$oQ+R??$wQR)hfPFEOu zz4ozoSpzTv%~De$(f}hQg6^fIWwLCRJ3G6-jWbt2jfMsXhnig<9-CX%=RZ%&hrD zFcm^Pc(}p82+5}@F~t!La~aLlBH;337~}K`Frcb!N~0d#Qo=HsB8M(jIj|sgx{vf{ zTAtZ>W~0SSX~a?Q?5|l*=@~J%u2dYUHsn(7Z6)?8PKD?hV??;<#+!RWD^SKL>k|{q zQE6y{0-P&{CmR8?&O5fagH-~#)8o7)_Q&fU5tcH#NwGfhPMxz*I?ztvlm>;(BLR9s?=cZ3rF2| z?ta&EbENUC&}>U7(uk;CbXdLpP<_KJkH|iYx-;!*Rj7(Yl$u!QPs!*PtWaWlfy$0( z2BxWT@WdEW8i5xv?)L<_D=S9PV})NR8+pB%1&ROqZ_JzAbk}C&RhEi=jsL=fg8T}w z?=1dt8T@dIh*nK|SUKUCWijG=FDZ>h6);KSmS8lRc`L-@=rP*LxxHicEt`FBLPE4n zLF6@E;SQYXUBX-t6EL$4S*Ey}Le(*2fcD*4lB9J9oN9lS9;V^_fSm1%JW9B8i?+7@-R|rntL?lW7AHwhfs$Evli<0 zZ#g!paxcj00{<@QTD@LVy!o3`uWgQ#IPpY=Zx#Bhx#>Jb$9ZQnnP25L-o@_Mn2nsL z%dsaXPf^NOuEDw(-E8?<{LotGPXbT8oDwlK@7^oP`)n-GU_KQfY<$`hT6%KMYH|*y zJK1E0J{OFP3{(}i`4Y*&d-5)3B03waZMtLSA`_BKJQL2=>^HyvKRQd(*GKANi$Qe9 z)17x>*iztkeTz>{#*PV4_p%h%-S4`E)jq(iEA9x_+(p+58&+0Dahs7*iL8G}@8I<| zTO`z|Kq4J##2jCv{}TH^&Eq;5q_)k(h~N=)5)W? zPS=^BdL%8Pecy7K>($sj6V~!r*DfNwgN9B+`xY5{BRQ2D%?CdUJ%*Zo%!CRi4V|E= zXf>zXDbhEYf5yRq&-X>Sy8Ov#Y#kb_)Hef()Tm@Cnr`wonjO@3j@EF_YE5>ygvzio05P<( z&@^y{AKR0J++Jpc))rpp1aylg)EQtMMoJrO3Gd)ETu)dPQ_eHx zsws$pGECry9(IGnY2vT~ewoiU4$vJi{f9&xEHP~cyka7C*G+S^`x6#U*=S;Bee_ea zpIHV)%%+~r5KlK{G}2Z}$a5a$E)R>cYRbMKQHiVLZsB2Tdv2fWIY5usQLUb$Ehv>5 zfdJOp+I#g6X^ewZlXR+3wNeQ|1J{UGI#Y~n$Qcx z#I5%1v}6>;v0Q0~q{jG7<{z#l27xtRCeR$3e1yST>RVr1@Gvs~gku0%LlCWAktH*6hb9afpKPE;w>r6y62+4D$(-)_ z!^h$4gQ1!h9LUnzv!=^t)e~7D=Qp}Lgd!9(x^pEc_63ifxM5fJLpRDt2LE|kff(9X zyH*XNfaEdBLe#4#M0)jNK?tT1f*`*7l8tjnB)^F{dNbC0?eompb#Zxa%6+|c%T%cfvswUoRr84)v<8A6B5yzMfvZqo9QK>L)=@bP8* z`dpdrdt7O&swps}dH5RR&h(UNib;w!TL|}8^4V3sRu(HXaoF;8Z(sb=Ko=~t{bNrB zBh3*@PUc+tU>~mAT^7ZStceqyGx43hsOqyd?{k&W#9no=aAVCWj4id4obnrhNI0rv z8^CnVL@PooED{)Si^mce>2iK`)xfxZCj4h)r>ENXf!M^~e;hqnHa~ZjX2IxYHqi6N zW?ikN-G=!HeL`Lz_B!t{Z6A9`#8}){t`zV2AJRCEzyTu!_CA#x=3fP-B)-cft-Ry1 z73*_5iy6acCm|f=J`MByQBjnH7F=RC$S}*bw-hWE7|HI}Vxp$cY)I{Tx)iR$-jJ>Q zdSC>drc2}(-o+U%lJjg^@Mjyu5!Lk%>43ofPzLW--WIZ(w7m55^W|fd4-!r29nIgp z!OLJ-Z|b{-GYZAAvGks9b`=JhlIucaB56D!OztnBj(FpIFAWt$y~AW(t@Y`uK5DWR zZ*y#V3=cA3EZWSh!}?TP6ePArdu`3!WLBP6?lfb#Kbo+gOIA}>hY#{|hI7yKlGb@y zlo+W(*fAM3O$hW?n|wF=C#zDJbDCqyp8k)9*Z*7e;rLtSf0QJ+W953@Y_%}x<~PyW zrli9ck?amb(_zpjVmjkvu*;rT>%l<^FR6}+P8wDW7fV;tCjI&z&{#ef;nm-M;K9S0 zPbcY@TxqY?+|o}5xI{Amr>)3AMv`wRY8>QBW4{8}H^^R5Fix>n@QnB>A@AwB?&NZjm%?gs;140e6mJOFwcgxK zC-}oRL#IMT&}1qvGycHlN}aPV={~b>mAlaOh5-F%->d`uywX&Kl~V$&If4mQ3YA{M z+Myq_#Lg4G2T>9R=me*XEqA9K%H3^k8%MTZS~7%fleYoflqNB>z0v*bB9V}_mNmFH zB>l@(P+33)$*i&U()u@*tdaGIZy5F%qIuj3Oba^Zm2T_JC@%(+#WsZ>Socx4BwX(}YV8xwU`7H}Nrd-TZ>y zD>vVB_L`ppZfVMZ#ZfX$b5t-ZosI58{L3mEX+`>PA>J||2GbVdXpju43nlZsI_TSh z`&uTC!Ic*mF&qTpP8Y7qUsV3wui|1}v*nki%=QmSX-y`*P9U|R!QOz>Fv{RjOMN{< z(Szyo=R#0^!LRyblZYST*&B22-r(iOXc*&F8z;(CE={ftPmMl)spW#AfxkDIuaQ_q`oy$fzKLuVrf^9em+d&v_rQ!$g{03@ zd(f&*Q_JV(hAIJ=wsQBH5}sbW5Bdmv)vEPja}sDf%|)Bv0Wo9E4;=j+G^b;(tH1?(gHW! zzWt-zLatiVI2^m7$Zhq~jBv4E%Tq9)qc8>>-?Xbhy4cbJcrooaYC*Tns=Rszj zm>h4A{pBtYiV%p(>SL{$2x^1AoBHPjkOPWj{?Pg{As>399TjoCaL~`M{`jt}$4}7=vw^4b; zhGvl1@Ux^Fm*Urq#R<62kKaPT>gcZ?FUpVc-u*c?Ox46<);V!i^1pF^vg4iC&W#nE=eZI&oY52y0We&)#Kw$Sw^{~Zd(xrACM_K+3 zX!q-!@cp_la?U1kZWb%8*?KoPen!bxKYx)zq!351g6=0n4gV>n$)+2cPA2k^Ngw-j zk7^uWfAQJ;EsL-#M&`yxvEN3s)#h@P(V&T&cR!DGYXl*)Wsg2FCw|3ueCG6)Al$)r zRxcEV$#`?B=D@W9CyY^KMpW*#@9vJRmb`o_DfX1Vs&m~}liN?XPY2KREwhWQ@WF1H zi?fNvUk6;eXI7gt88R6TFB@8b8RI^WYLFi!I@M=I#ZKHr3~bFtx-|xJGuoJv`8R2v z+aJgoCO;25%g5Z~roHBzx?m=Dk$>ZF^abP`f7eqAlU!`JHdPhXv{P*Jwvw-fsligl!xX|{<#(8+*=WZ|%I20dv=hcZT$NM1n- zB;_C;Dkme5l9K9~f=wu!X0;x}#%_};-he6;lnb);-6f5PzE7*Z0UmlZ#R+~ znr!nR@b}iEhca^{rpFG9k#^~q;Bi$S=J#l0jHQ*HJw!#vFNMNy@b2~nCl76N+x^c= z2=K0}k7K{O4(JVR1#wKaqhc%p(hI6hifveUQhZndERA+kGj_ycVPbD;$wrMo$LZUX zTlL6F3xjlLbt1)Y%Y3MA@j|4B{2NFH^I}(upBiUMiO|6AEUcf;$=e}kMA_mtH#x@w zfrEdT?eIWczr15cYGX=RqgkUzT!AsphAac7OQHE|=Ju4?ajMH1in@uTLMN)hkqIZ6 zoyj4sl3J|AQp3%aj-}g+Ou4cf?0sE^pKM_5va>exePa*ycYqjXUF&2(bo*~hf}kv8 zPd_uJk;Kn`8)fB%w*q22-EtcijQR}8CB#c$6Cs&L#8`f=N^}oX6!keu!~=r_U6H2! z@-nKkZo03i+D8xesoFKQ>)l+zAe{(#2YX`fTo0B@g`w0;Zgs1bG6qUC$6XOE@{|Znq^vTJouNU7xJS0x2iTg0y`|f*wc;^}q0*Hzq7K2-w`T)3dk$#wS0 z8BT3yAgkt{trE)ed+XMz>ImzRyYHnvU5)dS0}Gy$OSAam{Wq^-tRx@q>BoZzCD-^u z%<+3>#>D=>E>6w)9zEfpD$x*&z~v%ZL`O9Q2~YU0EX7uqMqp87pj4IN#~6zTVK`m* zAeTfqk606yidr}2{$#SkU2W!gj(TUC5Y}P~pXhP-pj958gOLbnXL(R%PwXcUpCiNi zn}BdPb0A|PsY2}@6hf)alOVOc4vn+m z_t!^7p=Q0jm`RHdw;>EIJsj-m08!MLV(*9Sx@5h1Q6kkzNy2<#c&+A`-Xgz>Yy9MZ zKkunq-s>u1GG;x;?PP3cCU1@BUD}R_y{o{5lFAa_A|IkWNfd z-A`u?i_ItV$WoIS&Gc+|sME4h_R8V#clYPZiRD~=LiZz&q-~iL1uW~_fx^`T>a`dR zWS$8NTBNMrF~j_|?2a`(wLZ@C)uOW6jq7_a<>I45=eT`pD2K6JXT&zx%#yvaNle~& z7@K}N6Z3mBT}{YY0(Bv7YkP>HBTHBGXGN%N4%s#*S#i>D!JiEt!7kekMwN{l#d}Z3 zc*;Wf)vn5PT!cIaT%HAO-YM+8+Q?G;d1Tszqcn4(7M>GGg)(d5U(G3-qFtI|VbvKt zaCZ0`ulFwPyw7wGSl3r8F9lhW*rM4h5lK1nBTpG*Y+NVn@ zFm2=)yQm<7_+*;tK9n+JYSVpB!8@zJ3udgYxzwvl7SMoLrFV?C z2q(#+VxT6!x&;PKP{qR|ew&kkuYvo^`=jd53~PKg1R6m~f-B2gCJf0iCMmG{n&^S; zs~du}?m4kUOFRwvzgtdHS9l@Htfl{{kJUG3`91^qzq$T3aWRI0Iec+q+ zlH*GbXu5nX>E4S$V}}`=J9^gZ*Cf%(2gBpxCI#tD)fsc3v+xx^A7?Z1<#(UP{S*s2 zgrUA;p*2^8Pi_Vd?fsJqQPn{@wR|89^zce13Ht3|;>L>XeWr72^Og3P+eW*NEPZ&9 zUIi0|LIoorhSMfRVKn_UAuy)+FZRS5!<5BunLyo3o*#vMWlTQaJCj=o<66D^85`-5 zIHmumXK`3_3D04rNWHkkAEigJDAuUQY{p+js}xFm!gph-0x@2z?LOrHkZjrFjRnq8 zQ;47AEZte6A;nDGVCT9`s8nAK!ixVtkBa^u-}&4&-l!cDlndy2s=BRA6ed)-)lrYg zY4onjwj>gstM;xd0twW*WX9wM!y;qYJN6KeXx6R11Z-{g!YL~tcF(h#xSqQNcFUH? zL};w_Pp`1#8r8jyDK2Y+amBs~zW1ImUwZ?4nXPZs?7d+0^gk^84CI)JuDx)1U{Rxu z(a-XqCUL_hZTRY%jZCP0#<7)+8Dwk#1IPEWbxiR=bN#!Fwty=20(yGVmHO=- z2W%;Tl0tj%5`uD&Y!KUgLZcy1x7v8}uFJN@(1Tf>O)E~;X|?w34PB=I8mipOuVSkZ2POl;ipNcg#zB-XspwwI3a!0N-Jd{L_%wc7(X_nbjDi7w=9#v@f zjfv)VklnVyWS$vp{)-@3bST~6&%?X5+YH?Wj$y{>*=}f#UF()N8LQ7>ELZCkJkHy} zvRB_ybtzg@DAS?@A<4NqZE*eU2=z5flxWS{5VBPmKslx5& zQyo8@B)-*V1lWSzDvU8ph)@5_F4Q3FCJu{;bnMlE$7){MdUv^ZSyk|F(S`-G8b89E zr(?ggphfq!I$Y|Hz~oeZpPuL~k}WX4q#oPmv?u5OxOvwiQo01-m}sc^s^{zt1BIBU zN;?ZuJ8)`ErTQ662Ty)uSsN%qtJQg;WC3Qqn3F{m1R94#2YE1q!O4@|;tTMR4INLj zfN{Tmn$z19>&f_|t+e$Iyig0uPexl;;@G?>jIn%6>NfloS#X9OI40QR(|q3>5A3s< zcZH`cc+sXJ58WI%Pj1(_E0Slui=0KIc^4|2#6|jb3z@h{;~dMjIkFXj_bd`WA_R z)Q;-gM6JfpD0+f&8-rx-ztU7@oK^-cu98bCqDKKzNkgCkoFJO8 zJc%dO{l2O|^?^ozFqNklp+Hdg<=(AOfLdc^)Q$+(V11lgh+<;Hdfx{+dJUJ|rEyjfsBu21=Jn%j8kLjk=_bzF$o?Qr*WRx0OA{b!+fQP+tk|HH0K17 zZ&F@aN0Vl72rO!;@}0_5R);JGV}d`?mXiMD=`=gDWqPbD0<>_}hh_T?ZR<~QI~dWh zCYgvms5-})>CyczwYJltbo$_t)HuPEJt)yLw&W03LZ46jT(o7D2Ny6@F4A|JMZnFn zb6K@XV@ljf2k;+ZXDv@8?`_R10^Aw=)8ImIbR|STcWq$M+JB*At+b?OY5JVBjtQl& z(({YeeKv8XpI}MJN#yj{ckdyiABUvx+0=Fox;b-_Pikg)`z0Wk&WGYv3-7AD%X>20 zgfogmUMa17IA#?R;=bU9g?jN87ZZ6@Y&Bj1f`9mVVM}xMu~Z&w&-d6p6iiKzXKR;C z^L$}v2<0gw8BA8+vP*B?Rfv_{-v}?s9rmVR8Q`~=sHNo8o1|zJp(m5agKxJ3V!!^6 z&1(`h2kfs0lZR93LB5L^R+;RPw)E|9WPN~xiw@0EJu=RnyT#&S5|Wm1~D=^EQ_6j5HRtVut-`nweb+5myJtBLTm z(|-O#QdGfWV%3e8|-$6#I%y_G* z$fcp>-2S1Z_=jv)OsNTLYPjCcgM%UWkpJ}jPe_Bf8U>3pHTlB46_12?PKus5ET%fb z=qA8(UWdRpakZGq`R)oTZws6?LCJ`fJ74}PGe#NHxfGQ^wsRcFv&^EWd1EKAb&3X+ zEvjyCulb@18`>3$x#X=3YhpT!4TqI@KFgR0%k1HD=u9jp^PH<)r20m_6gb@1sA}`~ zr&MR_sA}3=mk9e2>e4BAPSMi5y)*=5Aq7ObXYO2XX-%EYoivMrFG>zno#qB%3c9wY zR$c@Wz!lLsBQ|k2%f)d>s_x#Y%65wE$5Df$TL${mhS4H)&fSJY`mQlmb5UR{Q{E*r zYB0{j#tp~lqIzk{gI`7lTs6e3#^;x5Z5x+UA4y;kQ=e6{Vm548v?G_4wOZ-Jd?#+Q z7(qEm|x}tD!kt-ak*hf70j18|2`@?{^gq$}$$uYxA6pw1EcWmfDN>SSdpm?2J1BUJe7TNQIi z7u#3RUQ_c*X8>-?*;^siER*I_fu7Hi6OYrv^p<^dD`BPmG)23L0dt$szA+QsaiS{8>5OK(1jzxNE@q|(|E8Gmmt;rUX${#JqAuN`7V_o=pM%c z{~$|R@9Br~i0&GgmmRMws50$X@Z8doS{R}-Is=rq&G1H&lM{A!Kwvhll#%^rnB6f( zD>C(n^LNKAmDY0qorHa-!$NTT>n^gx0LRQ~Fl#TiFltU>>TSE>s`XK*pL%P4&!}c!trXQn)+j?L)65-T2r%3%09Q*pM zlTuE%;o-phFa7q18i)=a9+zeX?`29dd^Uxd`hF%-AyTv8v;wfu=*HG(+h%>Xw8!kF zR{J0n@_zjR7giB}ZEb(V<}Gw08`2;y(@5oJ6lkMaN}>dr2`ESxI*#HNAmT&=5PP$K zAT?&wzPM-)i`aslkDVg&Xa?L{O<4OH1pLi;y!YvGF^$2`{xQt?F^U_g>c3w%fCqSK z`s3s6##ToBu2o>xj&V}$RDI2i)2gZ}q}ZyAL-ve*An-jo4Cx2!|6Qf<-EdMGl|CxZ zhK}k+TN+?u+e4Ha{ds7|AOWFH^EMRX(jh>RkOG*iem4KU+?#K$BzNm7R^zR{@E~&r zII~gjlMF8;_k>IgA}aPOI*O>?kd*pAV68v@iK6{K+Z+Gei2vF3;lCIh|Jxn^KXnI~ zuY4~%_Ynmr3j&!HpB|Iw=~+Vj5ve5dd10Jeu$wttn7n(z});cHC3*< z#g?=|)1oe-X0Yp5g+f6BB*|xWcg%-0AdGICulTZPkNP>eazk) zNL0i>B#F7lA9be*_fTrB{O`=^3DhDXiasBQR;=~ z&%3OwsI7+AhTv<#^$(z0`6q_p`?<-|@nD~%bsNXxgI)%0^x`j-of090+1ga^dSSgw zh~q40qR~e>XLY`4q*QF5w>+yy)6&A?B~Hzs>O)dEnwtBVVbav^r$Lw@^_LgXzY|<* zzR=v^c^Med)l?-{N#;2!NKsLm^|cZJeMXq`$sOvH_YF$8-!-+*QaaAtOvjw|2fO|1 zVnvJaMl8Qfwq$STD5D02UJ{)9w$p*Jc3>oPh6LvVbKo_6$q^m|Q__QI;6YPWig%XwNXJzvfEoB9U-q@`YpZc8A~z z0HgrG0)YSk%!ahwEdXO9m|rfaz2jBKxzpmwSzW&)kHSUSayscn`IYvHAMjP~o=nTs ztrIomD!od%?Tk^ncXbpwIw&If#ZRH~zatIGykeGXOO|D#7Dch+hAWi`Oq;;~7!)+3 zGx}Xt1k_@P>%s3dLVeN|{n309-PW}&hmwg9QaHv!@5%r`5 z7sfHLHnaZSqvf9d?x3RmPWR5{@e{pH@H&V5Y++9y!7Y4Rr24C+UMohj)PcRZhGfMU zMV@T>`5&O}JuzV?PqIq)KY#Fl&`W(!&{xf}^< zrldn2y5?p5xJ#THO5E8}e`*~3jf2SSKdA~V8a$ORRR#vL=9QCoOe8jhx%wnG?5Sf= zc=%QFVgCbEu!xc6ySxTMaZcKwlx0l8&ueQs&)R@-&=2Af^RBViO&Z154CUp|)}y0m zCYMsW)}QF8a8G?mWkHQvs>dDX&013BEa|tC2)Ifq5r8cqc}!IDaASFS$D>to+v4E- z+?YrQgTzzxM|!29`%6l?G1(`BB8M-@<5g=GzV=kH?Y-;G!*uj9d|j-<1UL2Q^<|&N z{s9K?x@7e0!H~TJ*2-z&93gMieQeNBXeEygZKx|o#8;7@o!E6W8uGxzkYw}3m*qy= z3(CqLh=#YNJbnA7$@SI(tpE;}ucd&*PjCY}{z|Imso`=kuC(!J>XkL3L53Aa#m5`{ zse6QNT!?Iul^$>mVPc`jZK&boz_FFI(p6M0jD+vnkt=_`?=$(K;|p5Xk`&ZjOVF|9 zzZY{f4nX#&x|=GPrHsPVPNL#bo53L1baOZ9+pKnauIM26k#7y zO}J8Q=jS7i4aGdM;8fbX;8)#rwM!XWL3S%rLSWc=jTw9p_%rf01UQ`<2i+I$;)_YG zLWY)V%I|Z!t-ew1QxYzRsx%;74QLy)hi2s>Yfah_d;o1B$Wzk$VJb)^$sT>S7FE8` z`umBL$75m3q3V+3kUc_7Q5m^CDV$4rj>9vOWn7%_-WRi7;1_;p`;?UKm$sAlGS+zr zV%WHcr#5y-3i1?*2o^8k_lVD3dkk{D%~OCuZm~5pR5=Sob*=_shy;hy!Nc>RS)0KS zu;2sUEId*Nyfnm2uYuuw3HLVz*YeKa8|^o>ZEMgYd*UNagYsE&tfOoYuaGT=X?C&A z4L&nyFQhy1l(Rx2=GC>ehxgLabz_afqx$#24Sa6SOxakgIoHwNw5pBowY?)%i|;ib zcdiQqqsPL={jvhKz5UFTOI7Tcap#*c?bzk&vcsBn%FTB!Uvq(b-afNK{dCp{~vq^)uRW) zSl8xR{q7JG%rBMrTL~T($w5JdEsg}MTRT4UR7ajI*ylGP5Dk#}ZEkV&6ON;*+Y!MZ znJ98!Bv0%5d5txoJ+af{)5i>{aN1orIK?PSR6(`CD6&5PqaOLNmZd^SOP0OVd2JYl zJV;NwZe_A@ti$=9VzeB;cla)dbGW9-N?or=3V^k<2>TRH5ji4rj3Qfl?V+!JDD~i9 za7va}OlM({fFCV*bsQHS@*u{L0YvVdGSYEg_k{1h#Mq3*#UOCu4g~ zILs++yt;Nec3uhN$ZP%saAwDYrSXdtqV21Wjr*y_T~L4Crb`ucf$Vmn0k>{%7mK9T zMGxG#mF#BR*}^YGW)a~UNF#}>$0YbBi|+Q&>01r0x2-k)klTHiLm1P^nT&x>D_t4o zLmK-Tmij|xSGjE`dM*o*oL%v;LXSLU#tol9y}vb%$VNnhA8I3v^O8ssK4H_?TXomg zh_<#-)stCK9Bl{(4B@qXlsBqOzO%Tq4eRu45gprv#~-u+aw`3_8eU%;Rn2`RK1pwLJcGUu>m|*opZn4DXEQ!lt4WQPvYbo$FGe8R6|!Hf zfL{)H$B>=#z%fMF+Hi4yL{G=$W9y<%wSU#h+b0}hcVDQi+Ape=K;^v<5L~Fkr)oF9vJXe##mnKIHZj5 z48njdFSsgyxM#_!xA;Q|SR2_sla#SXr{ZsAffA1}wEIVkEFj}B(4lqiT9u+Do=?Fc zf`pM})|_T^_P)TRm6>B+W>}eNOPC(jC_7C8nU8-?E&Ymq7jZ?ZV zt(>`DSIn>RQv{0hmK22haJ_y(d9BjV1Y(-?bp(Zb)o{#Ch)jOzv3A7x{py2lf3Axb z;{u=)s4o_L$60Qtk_X%xKrm)eNrSfL0+Tzn(;Kw;_?6sZe(}%AG2?gbqz~#JO6jtD z0Ej%&S1@6dPT6o=8LihbJ(93Yip7@(#hRPHJ>5+X%A4m$53S({lmv+4*!!I^ettDS zlm;He8S)NVDk@kCTWGYI8@Xk2?BfWAt@9*8)^k0R9nzqr!krN-yeXE=O<{4|>RX%~ z)7m7Y+{tOqn%C&K3L2C7xv8mPeFlzKtK`KQ2gk>A$MkjY!lF;lMl;+*n4-Jq;!dsSlE%p^nQuS> zW0dNZr}{2g#mUT%XmNLPB+L2ug0%Y7iwT*HM45S+?PcvmG)wY@h9%Mq3}H)oj;TI-m?Ieo`HqDv4bFUH0t}}fb9@f7tL%j`(O?zrY5y+Rf8g9XYs99bNQg@*ub2r15yB~pVoR!KA6ojk z^uVo*d6Z2XHst1U#^w+o6SJx%*m_>WkLRQN8f-vcu@R%nyraX5`+WA@`ISO6$`9dI z(4`GW-ZY#$+z(VOKMDMT+8elff3GP?C@jlpxN}8^+#FiquSR+Q#zdc&G<1P*8OPQ! zR5;?`Yk4kmdbVJB1lojHjEnz@7jGV~@WVas8v&MtLu2c4gF4F0S1pqT!s?lK#0G~k8H$|9P5%J| zyjZHH1G+_&GL@8mGT2dcu%b@Fz<1t+cMXU&wBJ`dQa@zey{-n_$3L=IQm#)SOWz?0 zI_1swEHthuh747^2jy~RC?JsE^n7_RPS~>DBt@t!Tv*iDFo`ro<5EHk$p$?rz3gA| zqj);bv>JDHHn0k5oyK@x7>6PqXH~G_KxiM^+dX83Kj^gqPmCX)cz+*UTf2H**x(LX zF-dPw!|G_Oe=Lz^+n(aTyGWp%xnO?y(rpIbZCR;d4k@*(B$1nVX$8Hqkotcx`_cH4C_Dj z;WYj(GkEkUs%YQ%=paIDbx7!hntbELTsF*VF3byyjWw{yg}pV;^gY{4!{i^pmeXAy z1A844%#$ju&OEqib+t1`rEepT+w*{fT$E9+2Cw=|Ffloz@4>LX1o9sli_pG5yigCG zOI0S%NlZ}Y;efD&mu+_WJFS4Tf4NV1@QEs9Sj=sy*_|(-{#o_H6Ph?YmzkC0_bly_ zG>+>Kop60Ha$6CXQ|IXmqX{dx&XMkf5~FTjd@?i$^WCkmQS5MS;{Q%Y8i7Y zA%_OVX?H0;;y|IGTTQLw4i;s3Eib&g)G1l+FtTT8N(hqZb61@tTl|Jz_m*?AvF_nh zT~(j968r4joQUQE^o~6`6WYojjpDp&wMOn|{^)`^YIfwRHh(X8`z=p_o7&o;zPjD} zvf^V>L(tTJ0H`*+&eCZugJ?=xY;wnrs=9kcLP=I0frp^e zY7VT;2-=MMio`^i)d~gI%zQ^YsT`@XGAZuQpOU^Z+%=P27b#fM>qpV&0?t&+369Fy z>K+i|Pp)8_#VfSkJy7%h$36UHcF#L4>Rn_I&+~+qx^2qARvNYHX~p0-T#g}e^kIZ* zU%yN|VL?OZly2kmHm18CKt)kA)U%&6L20s=R&Mrw^aFWdmm!&e>BBM89Zl8x`>Ea1 zxZ2`I_AjHaPn0i6K5NsC*@Yy80AIEIVorUDI|J z)(5?p&RFZ6Pdhb*N6LJ+$i1LdaILK~iX|=DkjV~sx!i5Te5uu(@E3hz`cYy7vV>;V~Rt6??$8GF%`0&{hV~% z5I&vfSU*UwY z?8oO^+Kw*0YR^qHn*Ke-3Z7=peJ==>8ID}aKBoeQEY7|Vmm^xkjX8Yymi?36BY%p)ssYTn+%|-j!iWKMJ zh8k+SinKIEQ$`#{kH}`enM7blj-L^V00I@J8TU#CjjJ}Ru2#?BDF(MeNFTV4(8 zPf}7#OXYMo1cplk+-x`vY%DMJ#>dplcqCOi-KJ3SG4_~-Xh~-A#_)qvdR;fidlq4p zgg6fqI2FpGAw8>o6BqAXH$KV(?2EEXUa+u)rmFW6rr2KUg6l0ip?N@zCNAz8>oqgmW3dwT9cdb@jenVg8Dha1Cyjb)E;Tr?(jRV) zo(jNviNH?(yDw1Ym}1X#*Eof~dp8FbzzC&0g1m(**<6g^(Qi9n>7C#G)%T_?`ZlW9 zWo^`eIM0W5Z`E;(HafgeW9C;mFuQ{jmf)x8c(8`t;d{2xsbHX;D5Nb{hsW2>Da(JV?6*#bA`O*#AI*CbaAuw?=QvSkCYGfV71V0v`**JqKdv5Q zw$|!z%4?OUW$~4Rpm0Qd`jC4^LOCb%<11x{(YFV^83f8$Oc$so4Vk*QIOxl^Ed#{F7da(vrUKznv082PN8__nyn*?k}w z0wiBPUf<~qe(jl8uylJBJHWRle>0I^{1W%*jV@rJi}75={w6~{|HiiO+irfK%=SFq z^yXD_f0}KD7sZ`AZ#Aj7mCZop?34t8(Wg*k5sw$(b8cDU;2pfLeNznJ1GXSryuQd&Y>ByVUai zio^}*2t*i~i|e)T;G(gXqB7S+M=VL~o{MM&-*ADah;|t^Uj7D->llYz6*Q>iUN-EYxMhfqp#)yH_kRkr&M8+0azW;zecOM?x^QpaZpg#paqTlTNWr zzZ^x3j)YWy#y&d|WJs%wZCCi1J9U~kAWCtFiYBWZct`U1Y_&&Zv9!bhR`?BK!HMRw9U}~FOVoB{&}YVG zjYXgwMEzi2e}A4dNg|gF)|PjO^*f5L{8b-!qm^{c%|Gb6Yxxi@1`5=JHsIVTl68*D z3(NHq(b zX(@^nL}%Jb0M*3!wblAcRL)|ld!tvu{1wgg?!XQ(mf* zL+bGxNuzSV9R1tZUH3O>Hl9|8A(h-~Ws5G2%ny(@iT4Gh!}L?8KS*^6S={~E@}>51zY4%zUhxHPqx&0uTQ%35Z^HP3{DJ_FfPB>&yeR{JV^ zbdnBqrd1t&s1Q~CJY}gWag6Zw$J81+Km)Jcqg;f~w!t3dM=FwnKuwivI zl?j4!&ACX1gLCw~(h?X>+{*CqHBV$jYEaAz9(KFYAO+$*r0eLVP)p0m?j>1QTWrs3 zh$IT^I&EFRi8T@rRIPum_9`+94J{tmCgn0ymZc-~Uy-~ES$`g+f(A@@8P;IlZ_Foo z?VjFAEnoA%qFp$~qbJ7*QE--a_ z3oHwb-e?5AO?-04|2b21tA-hj-=nOlX=FAvM#7oz8{_DVIfz)lk2$ebw@nlD`OVwD zALoVGJ~l5ePBlH_FiuziU1@~6OaPya-iOtqpH&8Jr-d5f9HUOatum@TSX@)j1n}j@ z{?8w;0wl*LM#9ZTBf&V@oA2>_qhcGzTa^i7G&}A9Qp+u^@Lm zw?s>2BCr`H(@elJo1%~9dJ+l4{(TMJdSB7m1ld^cPm{uwmH`6l^UVu~CYYSZ8+^Cc z6aj$|Mb{$6h{_f8`$>^ig}WJYgQg<%dD|3me2)$$#@IZFiu9>|MMO1kQf<{14utI= zRg$CReb`1HG{wd=@a6l6U!{J3c>nL44!&kHzZS7<)!`cX{N>#>$a%mKZagC#M99td zwxV;oB;|8m=+&+%CNF1IW(!)+P>?i3<-9$b$9U${7v_|AGU;T(>;JXUTso!@W~8}upIiE4%8YBn*HyhS+Rx8(S%EqX!cmjqRRyZ^BN>91rgI(SO2__A zJ2l_qn3zTy{Rl*{pH{Ujr?v(_Xsi1EqQC|J)_;KNqodMd&XVHbpN<<`7`nD@?th?K zL~J72dk3!~Ce4E(Pn+R2^plKzVl>n_TH4R)b_gdBG2V*CG+%9iSgGJ|k6>%X=|L{h z>T3n>W5cqJvOD*YM56gxP9CU303os*k1rkCn&M2!tUB2AWG~d+b+h}aDU#Bg0C-Nq?o`1YqtKErCP&rzwjdNs|&u0nN2r=DKMf@M2i%*0Iy@Z9u^jck)`GB;ef+oI#bD!P{;5g~M_cMvR zczaxGt6mt>9gvF|=0$`(M)p03QxO{UHD2#D1$7Zp6w2Z= zKc}wUrLyV;0!|AK-esL}GT`#ZMoFxvASFr{;Be@MqgoI?T#}&DlI@D(qX>w9QC;{F?3!l`pRKe0aQP1q_Fk)(pwWpz4WE`( z^V>xv{S8fU_b7?8;iRPcVHJUal>({aBBgAsMx?8g+A9U1`Ag^p>BXHaE3FI$J1-9; zYcfWN34X~P$&|lZ(45?7pT@zw&rtg8lG?x~mWH>#L-6Gor8&l7%yEN))$qHL$j*bYCbnqK$cQIS~~}Am)~YzZ1i=G0$IX2k+On z)c&R+ja}Re6pO}7RJsvtJLL>8w_TpQbPVxgr#OtW=31|bq$-t5dS}^{jB~)@yO6$% zs5_sNtJ`3>5a@j?fE{)r6{5~Y>5n}JK|0+{#yrf)4ooaVcRcadW|(oopSIvu%hNKU zA#e#od}Mai&LRxwo=$Vyrtu;yUWHC#zTe(uzz4>?-x-YLUo)TLU%CK7{D{l7Not9D z9(-2KX1irBUI-;l2Ex_&bA`q*7H1zObkI}OIcu2OIfkSXzaV*FmNDA6YHnWpD9X!} zc;!`n1XZ(ne_hKig-M@!>f;H=xIlVlj1jHLpq~y(rcK29bR_I|_zmkcP`lRFq;n z#q6i{niFpVLx*$xERN>T>=Cu(TFd{`?GQ zr7#u8kuJOfp-8*gu-IcEhXlbGeGg5oiin@rtLh9clhfi6sE~245T_JrbC z>~dsxtCdq~+eH;q7e=&k1bCwcW2yJgCEgR)eIrlw*TD46*kLUT)t5-WvHfNv-pG0( zAE)|bl?iIoj!K(aWqgLBb z%4~HGchp@SD)Y)L!^lG7gN~ByR=f0arTh&*AbvS>PBg^kbIqw2dSX%i$W$e(=8z1# zw^BHgV%d6USs>sq78WqG!OYq~O24)-6VVCTGmRa5vIA9M%*Z)S&9*Y#29Cwb@r}OY zL)O|9e;jAK6Xe*WWVdKPk7sN#=I>N@U28aZ!S8SY$i3Nn;Z~SCYQ3DxoBV_VjJaI! z$g`zINph@Vx!CN|WKFKHH#xD&R_&clhjy>39;xuHvZYQLuN_kHP;~q(y*Kd{MEOZ& zGVlPYj;`qY(gwpHdrTMza^r4i4)ABIx!1=zPf58vD+TG2uGn}5!|-86ZCtTVELhqR z7S`|eJus)&J{^_)p2Cu|T;M&1tr2%8=l|#i6c&(H4MYu8?UofOGR#FmA>6*=`lw^n zrt>|9U67-05EDeoX61uN`>~=aJY4*c*?@Vv9&xlIaBt>@P6+V5y!_n{b?enWSlgj9 z%#qLJtWAdt#ln1QU>EoYsO6f-&}G$fpT1{NH~PTy6n`lzJQF=1SGd6T)-Wpds)n#p z(msIHPE!0m(*mIgc({u0ZpkP`fyI@{Ze2})&Ebg6*0+p^D#A|xl5wv}@d7fV7AdBF zKOyrZtDL2r@+|oxR*Zq0fr;Ay=hL&(y450UJQJ5+74`?AVScS9n>a{y*UM&uC?*=@ zay)qb$o{;sk%=tdrvFJ*G^9>(ys?@?M{@8Yn+Eb;I*7ZhEmNX<1>1U_qDyI!V@xa<(8y@-qdXkXa+RbC(ji<_cuM`Y6aq05k-ya>tGd1Qpz9TS&y+39y(5{_i-M@&wQA~vfGuz<`_ zjW%(-#u<4!5*}L)$U^^eczSos5M;jtsXz4hqSC%5krb5+=R~EKu))>wgUbwQ3l3{$ zc}{fio{ll+Jy=$meOG>p#l-5e35!SQ_8wr-BV~Lv#lbD0A(Qr80+%|WSq&$L>L0WG z1Egh$cknmf=IfaJHrd!zP^y5gSK3$7+cQyxHa1A@vgKbjIrgzQtyF)N>OR#Ly+zikZP?h&&* z`ug3NdlP?28S`p|h7=0=S4jQQYl>kfRpkh&uW!XrQ@{1K`o={blTw8ZLG^2v_;FUA~3O|1}ZYL-bC%aG8^apo}Y~MCIK^ES_+# zs)jh4W!U}np)~4e5NRq6JlvZ(4PTin9IjBJ)YV~_>N|rHuyv6hS#JNm?>a6Q z3!i9jGmj>rLoc1rqju_Y^}%}nvxD7M{!B5&49WfW50WUhl=hcGW1g?IOja!Y(Vev< zIr?QK7n)J=%3h>c$#x60Sk56Gg3@ES$Uo7(MO;+^>ZRk!>z&{CAu2~&hylk|KI)$mHpOOWAZ)ivO7&A5}9KqxSs9>xs z!7F!_k%ME@^rWI+7nhjv@!cD1ec^FN)Sbup1B_2RvVYt;ufXk*(ihkaAHFRpm9pL9 zqCI+GsQXDSdI~0}X{sA52>Sb<_D1m+X8a<9?7Btj7Yk5gBaE0*;{VxgJol$lUeY^n z(q7jq%Sz5D>6f=a&M$_;&H%C_gNzzSSFeAMxz|7-aT9-&8)tII#z6e)dnbsOc%D~# zsgqWC#uKS=bo!cv0Wonvs?q+UvZA^og{n%0qN;-E_t|K2v{PEzXjZhju|EZ3lpEL5Z_q`uUl;mb#e`lA5!zJd)KwkNM)&p*`Q5B0yeKeCZbZd==b_l z*ghgoY;XCEgsSG?%SG{ZYV}^Ry?Q%Xf&CUv^XIU3E`q*iu)EZp#SdP6n{-jXE2GR~ z5iT0d1w3R=88+p^SLRyzd5Z+apIo>4789*2P7|%d)mQ_WI;v=!*w7(a_6$#mW4LWY zlKMD35#K(8jJSG3$dFo;JjZLV6!Z%gJ7GsHP35WQw_j|y%{%(^!)`lF?X9#THBs5# zgJ0^b8WuW&(UcvTtYjqShh-5n%zwB0`aZ4Kx=`HdGa$|}K_c{@N7!^3DQG}d9Y$vr zTH_W-kURwpQ!K1=^6vtxhm0|Yl_H@EVIC}@^F%c2ik`W<PDJLtojye})h#mRerYm^- zDHiOK{OaLe2B|zkMv@e#vw$NsGjpXqB*0EIj_H7i)clJ4F;13PP!VSxzGu$PVPg)P ztV`*}szE?F)(|{*FhSO5wQfXp`Z5HSh)biy$yVW|{fM=20?Jee6*?c2F7XVsm_@$^)kzB%b^qt42qvWcPf5bi{yJCl@V;=i#he~~F}KIo}p z9Cz^Wy#4)0e}eiO2Jb%rEH+ViU;sag)6S6D0!f6^FfTQW7E~K(H7B7HOFkzv;S*;} z%GGZESR6_ipOtf5WX1sAD3^{+98?Pz@WLmR@S67lKvz%mvT9^{!T6NyL5*;**x0ax zpUuxxxZ+uX%8gz6PJh>c1XLSQORhR75>?ugtQ~ZQQDM~^xO6ENBa9$U&bWAOH*pag zV1$*s0s@?bFcgK;IF$qA;5@iUAETdDj~ze9exbva3T!ssX;+eRqU9o*Jf%)73M|Be z%p}5G{i0kDZLk#V(d7k!em&h|Go#=){PC!sW)PNh*7BoZ5=jr1J+idyjYif#)iTa`%aKyI3}yDm2nP^OVb-YvWKPns?BRK}cV8cVJvt=N^p(UbL!q zkxkEC*$_wO=lMDUC81Tm-J|*W-WuKR8KEJ|KF!q{f2ARD%B;G#u4M!+QOIAaCJ^n) z@2@}F)nlj;ml+YXG#CpIVc$MnE#+1B>}7{cO!ppu$%YbO zyjS9Ln&6LH0JBJ&(QYT4V!CL5wqZEYB}E$7BVPtvNsG-bFVNTn`0#uOvHK&Vg-rkc z#zP_6h5ZnL_+x^;K}PEr7F;S9NiQq9d5#z+dg#ITQ)ji~70XsxxMD#PfvKn9sHx{5 zJq}d39-(xu#2=PAX<;%F60}tiR%|T$yp&*B=cv+?PSToD1)C9O|LoAAYj5kkQK&E{ z*m|&9iCY-hfIK3oKD(P93IvYzJEwzss($UTsmaYV1Z1~Gxh(5edIfnGEPSgBnnv#B$ZTMqJYn_%kp26~?vqaHRO_Vm1n*Ez11XrS`}N>d z;+%A`)iiXnwYc0ZKU~H;-1b-_#@3rj8YG>R?YU=&$BSI1PlrO#M+wL5K`NOuBJeF; z=DQ1r{W!~K5AROh*#-o}IEk7?Q~Nu?wVmw`Am5>y1`?&GHek%6*pV7c!vXS{kk zmsbbcj@KY(FTla1&?h7X#ySd;8XGzvi4xomw9!aK;55mEw?T;2hX}CYT6} z$m!Nj(J!-OYW``Lc}jhww-ZX1=w|nYps(*Sb3Jp{G0M4ii7xRP9!$4x#p+#-{GEy3 zGi=UTTf>5Ew!=!IB+$bPkH765DNT=CWI;I0v8Z*VcO-C^{(Lc@VQlaGSAg)eDi98_frD(PC|EbkABl%0y)7 zXESAww{}I~fh(FAhCV1GuJ!i@;44sEc^Z-NWPFmbfU1$yA#pmZ;f^L^gk%hHj7($; zZmN6!&^YO&u^l>WWu`3eMN(erV1LlvXbhCdP7RyeRh_J7@O5T0gWOK{I$^JkBY4s#St3|*dmsbPE`a$DBMv4CFG zClmnmL*N4QF|A2rCP>E=m)4bACzKYvJJ^fMw^_ovx-EdClbwy6z>##Cxej?m)1XYv zytqUSM)dE9^!F>rN*`=bS=JD2mndf;FT&c1_m^U#TQo6(gB&U`sQSdCi)evs?GBYT z{sv5r*rfUo=u{-K*xTtjSE9~kF_V5@)3FXz>f%{AZ$0`K@zROJ8KMT~z?awY8@>n< z1I-#-Vu)TPT-uLH*$`GfOuY$?q%?gbRbVcM$`2A4awG}qe}KP?s1DXgYC?!!X!zCZ}W-2UP$RBAj)cYgpzX~HMcp=o~ z{R3Ff>sSkQqq$pN)fXN*Ee7Fz;YYGcWE`|K+8G_?)av^pct55O6!J2 zI6@_iNVd#z0k!Cr8|qAtv6%G3-bT@^U9C}^l$eX(_@hK1Q6!$3MJ+oO|2Uw9qa)+F zhN%t&=gJ_-VC;UO!Q;4M{nYyERn%hWtczV!(A4Qku?x3CBFBeik(eRyAue}N{^15+ zpWDEG!m+x2>8E-Ni}5VDjKe*+akL&Ah>0C+j)`v*=;tTr@`d-%&uG&V-1;41tLIV> zTNJsN|F1K7&Y|t=^R?jJ0w|II!3$V`TT0=Z%89ryGA*z+p{I2w)XlSUEW61fOo{Zt zTCNAdChhW_sWkeG!iQje#%eP-w`QKLuy)GQr*)U4%rGhINVxk^6lr>=3yOK^|TxLnz$h|t|)Aq@Dq$f4O8jkLquv=RKi*o!_Y8_L7_L65YY_ji> zOz!%dTf5<{Xxcnq)2j#+l2P3d zR9$-`hW|z)Hv3Z0!V{Rva^C}p406dzl68OxufY?SQ=Y#TIg#;J3|8My(U4< zr*tLv%!ui@qCISpO)pv0Qd8GnkXI!Yu4RW9S|v6_3ZE-C#r&8X*-v8vjs8_~6Xq4v zx_S4s3#In*{!vd^KrN_Zp{Ck^nGKwu41mNY_DcEY4^j z-N3Z!o0{swM0J=O60n~e>GYpjwrn#P#GZh75)pNb>%ZuswX%P)P5iy^BA_FsJLU5f zR5jof_Jw3~vDp|tkK*Um|7q{Mzu8dOIBxXXb;VX<#9l$HBCQ!jMQMd9v1utmtgC44 z-4qE4sx4Y0Mr|RgMpD~tjT)^{t+do$tW`f? zCf45uQd?(k6v+crv)cN|e$m=Pix%kWq#=WQ3qfjD_d+;ZXR;Cb(Yx3q0O$JHCyI`N z`Ft~u0EO%c3^vNuCtgGjJlumZT6rIb`VcALWE72a(ziB7FXkDS#v%v%MrALL+_S<&x2 zjo8l(5!(^Hiei=}M#U6%E*7PfU#Z>Kli+0s&^eQRp|soP?~&*LH#s$ z1#@HtpSlneu3fo-K?(@x#M4#eXTY_^{fVa~^!{bHbAnDCQ)=V0pb8lt9Yw+fcAkT+ zbc6UDy5acZ25H<_`+C@3X`&ysS~|HO67jO#21Z$hlh6JC%E)$sQv?P3$S! zEOd9HfB=tIn%-*ZoQ8f$d225X?vS0T)(LFT-4wj1$Kd=K63d9oMGW;s{G9=sikQXt z5WPB&49&yw-mbLPW-Ff?gmqsTw+_3Eua|MqggWnmA~UGqt^>R$D@_3OU6I4|*|jw8 zxt_Y}n%uRU=~XE!*Q-kLa`=(Bq|c%91RmfM`Ruer!1lVevh&?>{>a5Zs{PZr z5C(N3nT1J;+6YV%hJ6R0CgndT&DCfX{CE$$X-9>wTP=J{JS;WV_l4Xtwx2{?BVt7r z5;EjSR{Uq|nFP~pDj%!f9n@IYDC#Pv)jkgxsQj7bvbZP@PH=hI#AZx}N|iCOw!TtI zcK*7F4}Iezd4Xh=LhYuUP#eWT*2`cpl}c4HIjQZ5oK^lg*Cy?t6>Cxp^t{XKu;SOU z+w+n0q5SzB(eYihH40E*UbeAy{#8or$$ zYJ}L(`56_@suL@Vh%Ro;EVA9*l-Yjt9~120l+`;=JKrLVF%|w9P90RT0neceTU65f zUeld$0LN_Pd@^NG*|4VsXjg%JWGLcy`=*M}_KDun^-9=eb|FJVLvhV58Bn>RwOLlF zpV%t|mE1H~{?qZ48pURVGI+t&tmK@|)VTS1H4oxW|;0dClx_;2f8BDM@LJuM(P zcp2#yP-Z`A*O&LFz>~?LZ2Xs zu^AV`s!1$Ta(NQgz}S#u>|1;37W^slu>i$_6ZApQb}2zgMCSC&X*i*(w%U|o9X%*l zq#(ull*>kHIFpBk-dC{1Z7hhsab~nKX5Oxzze?Uv*=cKi_Nk!7q8n_0D zzXJjW8)MSFXDc8BzEL+P%YNvno4V9$)jdlTLIZOKbe()A!$QeYFm*_#DDCp=ZN>Z2 zkM4s5w6XP19H-usND2u_wfi3#>P5tVwChRe7@)VhqgoHr-B)8Zxrr5Z6&W?(#5*v= zN3_&HS`pfH`c}cIYqc6^g80Jmg6tLGRm-PqEmr%zA|Oq;e2TI!Ndqh0@58;x_D&Be z`jp|^dd{nYHL<6dWtW4%%`NX1zvJWh+{N4POTWumM)!L7>FF~tgk}_>%M5Ut^PmklD{BH`<}kCOWr(riTIop zT;LjWlrUk;>lu##PM_l#JX-?;?7?6hL42$^_8N$7wD+~CsW)Q+T1bf9B&}>ye56vv5+@2^R{|k7^oDOn-?8kH1^$v|{=Fg>uN^>m0*EAs9cIRHoF7%g^L93p} z@E>Q#nW^RCh9yx1U~G(ilP%0yB}^MklTnq*GB<6N2}yT1yNDe#`I)n?;#Kx6w_IsZ z(JQx6kSY_*ia$p&VcE#e+&n!;nU4~qIw}55ShcUI`nQ;QUP}$Q>v0?N5>pi7&f-8e zc55bJx9Mlr6b!GY5H&d_f>-EP;OumnhMu-ZOceYm3O*=nS!gw2{VG!K$ZSFZ00MqG zb9A4jm>Y}`GbKL=1=`^)d3$+?So@YdnGrRW*O&sfL$j>G;nYZ7r3Qq>6;nQA3j|Px z>9mB0jbUYOiA!~K+4Yu2zR6dTc%YY2?-8?vNw2>7$NP69wl<7P@5L+k2h69JbzXA6 z2zJOA%hP0x<{$rJcwbTt{l{RAcB$<*$jCj6j}4b2J& zxDjvHHnX-zN$PIj%S-MGhdAZRLkI)^0WpRY#Fz9L2{ywMYPvHgDX2+ z)?7)AB}bW!puQnVCg@WxXwB#`CLA+;=V_B|Ur?LTi_@% diff --git a/docs/blog/complex-prog/complex-prog.jpeg b/docs/blog/complex-prog/complex-prog.jpeg deleted file mode 100644 index 6fdc2fce6dbfed52ed0388b0351e7671d32e67c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106820 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

    +qvF! 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�ugSGc)K>9q9!Hi+0Pz>O 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 E*^cu{tN;K2 diff --git a/docs/blog/complex-prog/graph1.jpeg b/docs/blog/complex-prog/graph1.jpeg deleted file mode 100644 index 4081e1707e37dde0931598a898ff46978272a84d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 172763 zcmb5W1z1$u8~?j0DM67Gq`Rd%1nI7!LApU&kQ4!>ySriN4gm#e2I&$+=~gKLiMt0p z$Md`Y=RWt|k!RShcvrvcGvBp_>)GqCzB@uoRaGGXFw7_LPUiBfG=e52L%lU1sNFy0~PfS+FgvhcQG+AF|n{8+{ePk!N$bA zPjDXx7Y`pF|L#3PA_6?32YC2+a3csvU>;-?bQBbHJS?>n;EX4dDRs9ufi$ zfQW;DgoAMX5qJauV9mfL{Cy##+(AS_ML+{%AA*g8zy3x7h+sufuIGWfNC*JpeWd#U zfN<^ukJq#Y-%z9j{`c{J0zv{XM4jTS>J6v@1jyOaFNNt=e6qsxybp%Bfs)Z^p>sowF$v=BWuKbadp|VieH1*KoXb@Kc(4m z!P8~Syg6|YMLJjUlEt)+Pf~k_ zPtz7~c7goh_u* z|N1d&H;fU91r!snXQc#x^KO6iJHt}fM3OGAOg|H;iT>>9rZ2Gh`trY2;tC7CcMA_$ ztF;CMXeN6OMx4+Kgj}}Oo`JoD5edG51p`DQ2L$;(Yb#CCduy>9bEi7@l zlz?oEHKXQNhi+5bYfH->D&iXjliHkC21hQbYoh?zBE%St=A+j~u5kmVw%=V{(trZ| z=B*7UZqM}5P_Kq1viwgaf6U&LaHpgatM!-BgN2udLe6zEQsUA~ovxj(&L%LRbiM7( zV7k%zMGkxdV9eDKyFwObO3zc}a?l=4ZM(t--HDTrpTXdD{dbxi;-8c|mL`(JtkFjB z2il)!rx%fB`OXOJN97K2*}FiGvWi<8t>G0#O2-ivlsrG3Yc?`8?QU@l2R2fx_ZAKE zUG_NCNL$=>szJN|PBbiosu*v9d=e<(Q2N4n4zm!UZh@1f6$2u2N@ieroJlFmD7+G3 zBCzO%VN_3AE^(@eVPxkO4^17;005vsmA(W1f+x90i#j13Hr7JhLZ3E@?p&$A9sKU( z8YoWISu?5^=(VqB;;lK#JWJNifv3*JkxJ$*Fln(WZBqi&xt{US{-X7oB0hj=_=2Mc ztmkdW5`(|N_5eHw9dh#obN-q0=TfaUs(6usTY_}$Elmp3!PaSEl?Joh`d}8&W)KHV z(iNemV&L5<+G9Ln*rx3s2NL^i7b8y!Tmd2QW zPQN_dHrSaC6@w*Ylo=fjtuN@nX9x;K6w7S6ABNZk%!iuY)tmP!(1@J-3H|^(u<;6Wrcjzek zfH#WaQg+X4;*;m`#@KSZwd=(kL`+uzY$Lcj@Zz-v!}myPS_So5&(_UKP$b-6Ce+kr z?tCBgc7z3h#{M02pa}MmW0BLeb_TBmw5XDYv*Pz_W5Vlu1qPi%oGQffOm8LUrUM=y zxD)p;D6bD3ZIe3a{F4MDA0YD={F`OS z=*2A!R)nwKWKFnL8p5ZXMvGhFIe)vry0J1iJ(zF|E>ljj1~~V10JHQVF1<=;*U!Zs z2mOb;B^b&dAda-WMuR|^Wq-|lpR4$d7wa$+TC=QUnc1eT4WP7wG!HR5@-z*GW2*wl z1deH$vm|t&ca$E5ZW>d4n`HI}-O1~7X68aa)1$z- zRWgb&_&5o&6HQk=k}25~rI7s`gAcpG*eTIZ*%2K4N*KpPTD$_mlNij~M^J3#C=a*~G@QlTD zt^xln;03@oFOZ4dx;u0Fn%LhW1pS4uTo7B9zVrPGVw!@-9bil_oteOmW&8S#g_>WyQ#`aYOCdAb_?o z+YbB8zlQvN6rqZj(Amr+Yqil%9PnaV<4KokqIK0nVB;C`Rc*?eJd$xrnG-=uwH&n6 ztn&`dPiSHbfV+W52}Yia7PY^f+#l3Ed-OfA>s;VBS7)^CHQ?u&WNaCLSc9)P9Q8f< z7i-P5n>8?zK3o%QI@aplTKO|3DhHt|@z6=;A(^2aAK`h z&euE&oZd{_$V90T`)LD~l8t6AcHD?}nE1-&h8`B|>$5z}!I189%SN=rN=~QY25e!0 z3$h=dWt%wwcg^fbY3-+f^q61SiAzdpw7O1=T<(zy@=b?wr=?c92sJ*s@r>YLTaI*i zB28N~`i9jSEYJlo2)9amzu*|D37?pzb@qV)Dv2)NpVskD>Mim&iLiHz-zlFL)(~ld zcrAu^GJCQ`0ti)^u9XYFq|ObhGG5Q;$gEF!qAv+5Z5!1y3e-KUGvwdRx|y{2%iJeS zg6kRC?T(+o&dW5#rg|Xl0i(BL)aE%O=;jL*8u> z+VCX+MADOj$`4y>E1G)dHb?J|X=P;`9k%=C7f7FvZg{DmX6<}9-G;kn1QnQ!m9c2b z$?7k*wDZGQRxWY8EKic9c(t~oq;i*{9d4kQsnDCMM}UMkYDB383qY4ruhd^S%#`rR zisau{1?)BqChECJ+98e^bY^8>d&WIQBKzu(ti4A!QX7Y1B6J?$xZo2bRzF1*4Bd*P z(o)Cg^~%AJVb+-FxpM0hdb2m8&pVd}mXq(9L9rpH$K;j?Z%^^$3L&n#+ekR)x(-;1 zCfQgUMxR2TiqOO)A^{Ugu?UX$xzY)|+Z3s~b-@(e{(vySV8%N^j{8gU{is)MpYWu`7 z?vW)%Yh!BK(_@dEzYt3INduxXa||-Jnd|3^??T^<0`=e7N_ezZ#!M_B#N zW@{)Q=lb1uXFVpWEbyKXxkfSbV7eXWAcmjaZcKSB=(@o@BP2bfLlI`7+i0hxcw#4x zeAiw^(MGgqr)5^JPMmVXY};+kOrwo!N+lA&P@dj)b>tkgQwRO~U3%NZRIa-%;cM)? zqc|J}zl%i-DoHv#86yt5qt+L#3e!8|{YBryJtW@P1CqpU&v0|o&yDFDmQewCWTcE_ zpM*Pw==C)l4m)7L(;jt4^|(bBKP%z3>QNx$JKy+A0VSS!K@|~)9N>P9&&iq7VD(XW zfnJXEdf&cR1eAs7IG2ExhuUWW+-ksPRITsKEpoS8UWmE2+T08`eJyzfic+;HqE@w@kyI!R(I6c$YRUG%5LG;XB=O!T+ z&rEHS**gKqRA=nU-o>7-En-&bg+F$|P1ks1BKdgv!ti?)Gq;;2T7L<1k|#MG2$oNa z3R+!b!QlrRq7%w(CcNOuGp+ETB{#(0K_#_}c$nVpDBNun*-aCrALhLnO7fT+U=>nd zSSos0QXN?jAZhNoI)@G5TucX4g6+tdSsCx#iq50s$_nhQb4(FDZ0@;fh^x=+UZ#)W zOuO*9i(y))fs)c|D~uJqk=HKcY1g@Hjn@T~&gH;42Q8n2 z(M)EJB#}dPU6ok~cU(Ap$Q*X4?@4zk{s5*GdmM3x)DB7f&f8hyjP!NR(v(4PB^!B= zxVl>|YxCq#QkAp|Y_2_DT7?BCkM`e&iu|H2MP-Ot;b38X|pYUZ#7yK7t6jN4CqCLV5NS7e*zOY-W`Y zefCcayv_7^ALf9WEE$|yV$&uSz~wRWaWZe*Q#95Dj@lR_@9UTc9>80YSGp)rmGE&! zYOBxw2-`SaB(zm3?$&L^r{mO_txUIUuFwvdfwP4T=ZVh7G+|X1mJ^kBwqC_r$eA1e zCIS||Zi}N9cDOtx-MP*vQ1G3%d`_sNmfi3P_F4eIC?t~+yx+9?xhN6AX5K+r*Cn}k zNCaS9nNSxI=m(nt6211D31z!Bju!m}yGrFx;;+(2-(=Ob@+oR(a;$!K37|f-ZHqmP zEB%~a(KwcapgVuE>aotHcMkgkUnaWq69n}q!;=%@wD{6npZIs`sxXg?E3jSD*#?LQ zz^M%mH-?|R(NLtLE#iugTci8oaGz>rpKRC)$%Lme$54T>Tvl^SPk^M9rX!z{)X~7* zP?x=Kam4s~;!FXfZ_0HO^rYZAR`*CxNw%+%AA|3|^_j5rI9zSgY&|@QzL6i_dmUMB zJbijPY3-4wm0U8cN_pY@>BZ>Nk%?5&Y5Uj?*wby(yp;q5{jiYIH$+=3z2~3bj{@c2 z1s399hw{f8{u@f%@WwcrwnH>$EdwY`b6Z{YnZ4YsDlpjWVM;+{AToh_Np5+6BDO3U4<&2$?J`gcM4=)W1n{%`-k2a5(oKg08TOAZu zZ2x_a<6=i(j=0+@*8+enmo~A(*k`huy(?q50m+`}g}gS6N5}e6(V^gnPlC+65$Z+T zfjSryvhc32JZx6)#0Bov+u}&#yuif=svSN{yw3;6B4>zQia~mkK;==i*%PSqQPmiJT)Xt;C4|K#-dyVD(~CTCYb|)E3?P)cc!f%GL#j zEtKxu`z6-?)<4hX-Tje>NCCwFzM}i--r{(u$*8`-| ztjyW;ZWmwGipapDSxCR;LuD)koV0KZ*y%v|NTD-Gj4Hf%pR5)Kd`eu*t$`^a^cG5& zKGC$QEH5Phz*O$qw<`#ztrV+E&7OFLjFM$Fk*-U5%x1_*WDRWFGK5g;h00Vtd!w znc3VZ@WrT8Ok-uNHvo`^sZyDW2)JdmDls9OYvKv_Q_fhZvkZ`tf>fF}5t`{LM@9m~R(2#=J0iX4KGOjJmPSM5 za09ajGxsR|Y^Co+ny&sq8;{E;7XE}qDDTSVft<^qh7=te<0fkhxh{SxRADdo7Iw{O z3zlZOSHQ3kkJJZUJZrC;GJTJ?HlDr|;Yk8Lr_cX5&UyZI6aj@)AXHg!J$A$4y!ph@ z%H=&kZQ1fsk-bGOdU*s?zy@}svQFSH)U*8B9Fe~#`*aj zb!wxhe2Gm!&`8VKUBg={PMk@a(i#Ux<(Fv2_o_z+O@{?-eLAin&;#hoqb8`E=_3}P zbOO$IPtJuo9;>8L_t0b0Xkw<(c_IZ7JRD(% z3_Yq)d8(jna1aD>AavEKSNA>B6&SB*#R7=AY+i;Dn>PL0@ZPAn*`j!t1sgQy!1}+`k_)1)y7L#Kd`N8IgE21n!iV8wunqB^d3)0(0Nqowm0u`5$3p737PBI z!1DJUd6f6x&Bim0a|2#sArL~CPD|Fi^}Klibn|7Cm2>Sw1mK6#n++9w|5s1_^Z0)T zz{S@8w{-rXfX;Fsl-K`x-N@`n$cQKa0xsU22lw$QxNx`$9&>Qg(DG1HgPJ-TsI()X zAnt_h_uNk*q=I~Q0j%9&BdJFW7MJbAF^Br65@vk zTw7dc9-&Ok(JiR`{+1$jJ&XpNt-RBB)GK8i)4IxdotS^J@A)k9I*+tlP9+bCRedd3 z#@Dp}qE$tO(KwYQ&devOc~#Y&B{$x%lr+eZ9mo0LBJ{*ZXR)i|wQ!yyC|tx5Fy(ke zR=xGN6XF;dcCCB#CJ2+niTo{Im4tf}Y08GBz+9Akoy_CSX?-NM;WGvTiYDpgvR4@D zyM6Es&lP1fcKgT~!ZM&|G5~H-%xXHic8|J;S!T*=O0-qoBY3i*W~m<<=T)L`^SgaS zrb3}`t4bx(82N?trN{+@fZSXZJj?R1i~{`kiu*z(k72Q8|FeOYx3$8>nfwiZ8X!z; zc^Z;qqy2ugBteo4ZZRHb_r&aAw$Z&;`rb;uZxgT>F0ChY65YL!?|3M&jdurM@c!em z3(4PNDCCyBWc(iJOwKl8PqYQSTY0Ivu7S|F`j2F8uC&b(DxGrQOQIv^Jd3Xq#h_OK zSD(6!kLj}1;&d~8Or@^@60&O`b%VPuO=nUlfE2@2Hev9-MV{>35UUkD&^CBCZ&Bit zY=V3`QhR{G_=pWWSQo~EWAPovvYzCsAW#@sqKU<>nAZkL)l9Yl_)&t8UEwLB%=iE9Z}_a)V1x+ zCq4MrK$k7KLFY79|LInqg{V)BH9k4TeZ`)fC&d6Gv+ZMyu*wJ_wQJz0^wRhU^~4W_ z{(i^DF9-K0CIiB@G$GiTJ}0~{NgffT>f32nXkI`)^3$cUUXqAJX7zT@%rqrY$tno< za1$V`KL33a_{q$wrdpk^v!-r#Zr7g2*Q-3>soxlR#V^CO;2l$M^~ow$tJ}DGEnc@t zI|!pUxjiB^CUK+fT~!o!lU;jwd2sV^OE*UJq<8*rAt$^T(!c(uGi}`Lu%OpI{weap zHplBxR_|GDT96z)WGV8Mu~AmTSQ&ORL44zhY_uG)+D{VJ_V} z)1=vZ=OF97+VculIVEulbd_u_6a4Xm;&G-55xvDhv60Fg$UQOQ*8xud_R^(RRKSx| z^J%4rO^^lj?%hjob%=(Lc zbBH~j^e~xp@v;9X`P?b4asMci*?Y*l0@-&&toO_+GB`&bnyJqR{4Q}o_X1AnoIW<6 z7QXwI^n8fV3}1foC~nDXKdo*8`h1Ar0-o0DZnZ>m=iRyx-ENlOXqWZ7eV8T&k0K?0 zUjqYr514aC%JaKf;MrMrskNZ`loRiN5gYa!Y%5C~It%XMjQzE9V?v}i*##mw)!LOb z4bSvX8MSlY#&eD*Ro_SHXWy0ukHx8_4eYaj(8*4LXLF1-yuf*8Ux%?nwQ+i3{aK2U zY8$$9CCYL#y#g^8k5 zU1>>marII4QdEIlyzX?Adw!&308Y~!G~bKP6gHU?ZA3Cs?^^N5>kv|5-lySi861~s zy`d)nPYHkEr(J0|zI|F*Q|hdt$S!D#{MfTf{S37w?Kl?C(g>b=M~0=}oolawkzggV zvzB3(d2h(1KFy@-Hs`;_ZXUwfNh|)b{%_3RV!$8=2Y=iq6VBj6r)RZzo3=10kN4P_ zljSIq{IAjPJ;TIj>K%>8*8n*dz3IR%uG{WJzTnX{Kymdcj^0eD!ETq*T@ zV6L==RnO-d2tIHUVdklL$oxf6rh-rL=bp8X&vE2Tq2PJvKTDJ=pBfE8fhhAHxviF_ z)>@g0VBkoOb78x7@LQsC`~kA?WQ{3LO@T>lcci2c3*_A*JiPF>rMGIt_pDTJLNmoT zRQYLxT8@$6PXf;%>Mu{9d&;#A7$%OHmSFNinJAdhfN**o26QUE4WWL1d%(BmIQffq?SvcAg?=iGk6by zoXVsSa`2$FQ3wC4ZlRCwJh-Rz4cr}{Or{maZSsIIef3}Z@uf49bcX392s^`0M|h-^ zg!%amDcKqZuxb=C7iyA0vjmhkshs-^;k?8&(v8JfkY{DJy4g;RX#T)i3hiocEep%VXc}8 z0Ovu)m_&@EVdb!&KEX(H|Az}VmipyrF9=Ncp{?F&)7^D38fJ1B!r6`(xSG;4@%8ar zf>$+>OsL-UMUuQ*DTXu9#Tgo%>Rx_xaMmy(@(@(_66*e}bYX^XWmPqlWLT6lGwzc+ zTa6Hk81(dvko^a$ab3_!h_!;#XaA7ny;AMCmx?Yh*xS?oUl*U?4AYyt0BmYJkS=HdLO$;W2HuQ8LKr>@oOW(l zio6mfAyPK>N5VG#`>FCa+li8_Km&|fxPe=usyTnJ`!Gz4WMHaXMnS)(;V)`= zsm(@AZj-u>74#ybN*nDil0`IfnsK5)sAU;&su~3bGhMA1GBi@6xfYkg0bEeiLX@%+n~YWkVSoB zo~FIdZtux@?^QzdUd^1YyyOVXD-fSfc==g58>dV4O1Gwujnjn8;7oPG%iSPHvt%g# z=8*sLznp{@`TdrjFk7#Irtn;$&oKsr$7OUy&{)S7A~e-oU`i&DiJEW|N!@ST6EL-m z52k9Xv}}F$7p5$_`th8pauAs9-kR4=an%2ZzRcRDr$o2>3bN&hH##~L!~TcChAX`o z@?uB?i%1hj87i*5aM+p{lRbqr7ccnzF(!k732v*Q5! zhBi-1L(*nM$e)UiG2U!~mhpQDV9ii7itghQ&TaD6r&6!h_kfDu<$~BOXy|U^d zuN5-rE_?c|g2{cY#=^`C1KcQuvv3l1Xc0G)KWr|b$uU(nRed~9>X!Ztpjf$^Q0Lrf z46YMwgi}*QmOP^8lUK9{D6j6YYiq(O4WzMT@yhT|+s)<&05;N`+&wVphRu$7G3b8X z;!|)Fks;}*;;3*i#4R|%zJX*k_G#vCmfOhaIq5n@w0;-CzHD}5L5g2cUMj4z_Ui)fvV*p)OO4_6#8nYc<)LWZ@xmSEM%hmwXexf>*?@h*OOVh^Fd7y zzp9`2cF#Crtj}K!_x1-Q)=?^t4_fzrU?(-Srakq-`21TzPS94je0&-T-7!0M5=F6~ zcM!we=zq129e0;`4q6_AW*38D)uD0TNtf}I>9TlHUCFF; z#gHnP>*Z3CnyDhcB7pN#G@*4BbaPj~Bc!h_=HSN-QT00V=rN-T;)tKuXv4YfAJY1O zVRQkWwJRgdIp@ zSDm?A*xP8`xU$g$n{%uD4QxE}2e z{(U|3l{&PhysL{3g4M`DKd}7U!C_*$g$l7^@0qYgZ3!_!>Le2jVsi9MT!V2oWhHae zeO_TUwb{W*JYLKNjVWGey|=loPor+Ivu3TWB+aR?Uk_g--KGxn_SkHxNAaeV& z_m3~`AkeLx+$q=F$}TG>GUJE;|6k_&njEzO=d)@JiiW;DM*g`SpF)XjU{l2=I^_xbp>&sewI1UPq_2#|@cs*^dV6ch7_j%0I z63XMeD3NhPeRj8{@%JC0^q3Ae66#qvFFp#7?|1(Qbh*HD-qbk;6>VI2ee?0lw8Vj^J+0&lJuI1OMY}5ZzV=rV$NFM2!x~HD z-ZPO$kp5Q|J%KY{>$-2=lz7B`Q)-XR`I(?EPlSfzPPwB9JQ9@AOe<4exL0*D zOn&Py7&l8-6$&=I)$6>K*CILgQOeL-sf)Iy!dkYmCQ&{=u5?~3?>B9_jgLx}QRgX_ z$dhxO(18{iSoIN_JgX)e`bWxhQDo;2>YG`xkl;Xn9px>B-ji8<(TS_1RZeCluOnvZ z-|F*Y`k2*6|MTN!Hf%o_u7v|TxI9ie#6(mDy#{0WYa#_zT4<2xIT5q z%-^vtM5H!*xumYkDT0V9%n@{T4TM|+U!!#kgAS1FBio;0q&T_I!9}mNvXw@8tyTt4 z*~Zu2Jc_JjI5$YhBcpBKrnPKmeHVZ5KMg~=~ zHO8e=5})N2W$JGEb7cUlmwu)6r$iZ5H7RGcgDp)^*yPNV${%q~tIs|G>ZZCM>wq4H z7l}5t>G3$P6#vy9DQ?4(e+D<)m+CNjg1!6b15q((2pE0cb}P&6_R+i;%}d7i z)QUMV_3=@xvEbBl2upSFiaUBN{*_N?vZKhFK95C^eTA99=Le1HEHioK=809Xax)ra z)~+J=lLAaS#;;%3^`D3M`+;3;5K2|%&ylfuq`l(uQ8|8B9rY5F>q;IqJowBU_)ux> zo&85a0XQ1!FbPR@WcrrtX%4n&4zzUW-e6rH!I(!m0g|dO#a}`M1wE>vCAid9U5b+0 zk?PAYnD}(IB=+tT_1dqTD<--GhFLcPpU&kAmLKmQ&Lo;nywJi3Oe~p%h>P>&-^z7K z7*S(3V@zrUu^JIa)-~)!#;p~CTaRlj3R`YS)C_0h*-~_2wXei)odmi2w0Wu_=(MGO zYftxZ}-9{Ku?5( z`V|G5CYF@cv#lAp>{k2Hlrtunf7>w8NiLMoF#1-BtCeP$XEyG7O@aSE^4uTn#A$yW zpT^OI!*VJA<^O8+?XywHx&Q$+y|t+Dd_vDGmw%_#F3W09@L4c*n+J1R`yw4aLJ z=zO(Z)J!pv{I*6Y!jsNShInO~mwA`>{<3E;WnG}nSV_!V)gG+?=+lb0DXC||t;x6g zAe>#%Yn}6nyK*bzrp!zgac7tK_8EeoDdr3qxsN@&2-ohu$|h5oOW7-rd*q`4s>JZE z#f!ROK!2gWyj;`Hwl$<4W~%&VS6gR5-aJ0i$B(5bXZ*Kd#i_%DoufwtQgi-s%)ti{ zefrHgy)J*aadQV|yHOfK4UftYO(l|Rz&832S||oRwAKpJS2E3|wBdd2)EmKKW~W4cIyD+U$M%Ze{3_>sj87k~L>}`#ir0C3 zfKt@)J+M&0uUY)%+RSXdlm9;y3&z)KQocjzZgaLlN%;(tC~PQQ;+@*4c?1?@h=+|? z8|}P%`52Rq(g~HteYu;z1pdJ@n$nT7+Lu}63(LD;Glj}@w3Fq}WxSYLzX8Y7P^D?s}o?&VSuO`jXpNFI9;XHT8^ zoa?eHiN;LX;@~{2fZF&~wcr~y=as2HI^}@{UKc#Jk0#5 zhjjzago`m{8nqr;vmIg2Zy6P?EP~;b3QKT8b?jnn$D|_Y-g}EW(}}Z;8To*+=ArF< zv)y1gz3PjUxfxZ@dnc~a#?(@lBUs!am)~%pX?yB+%d0iZd-#3!lCQ`l^Qxd7W|y!1 z=Iq!e>@f88Z|RqdEpKzqlLm8>H}uQ4g8adQKOhXR0a&=Dq0|TGJQp4XNpE7dnPd*Ke?8m>|}6AdrF5x zZl#Pf(z7q_>3U%ePY}lZXu_IDMsN+eqmk4VucahhYJ|0lyM8D$tqN)6OcOw^j!KVp_`PvRb$bZfFLW6j}bQqXUm9a zabr&!Y_fH`Y3}d3H^2u z;IWc~fvlU_9~H9AY}?MBNN~k=Gf=_vabmm0%xrVwLfUv_Z2TYQJTh-RZ^>FVrkgZ9 zo=$MozQ5R`)i*C%`*VKrwm>dyl!=-vOUwbz40gIvw&Hr+4WwwYHtDv%oq-E?4RqbOVo<&wX>O{^z*%kDSSW9%4Cq{FqCg;u&u+WISbiKKNNze|$Nb zof%wxOb)*+TUY!TyDgTG_g2bY5ShSN&r1qF=_~uKv1r^(=N#2d%~o~fpI>`iHKObh z3rrmT9{F15o0zJfSRAWT@nHsmcO}ZYmtsKnbW0;NnqRxj|Hd0KL(TV76MGjO6joWXYpZ_~hL%)+>63>j zH}!PVC26(s{qU%)Lv@O($m3&8Ta?gs*iKfq6!i&+jH*voe2VP0Rty(2*B#S>VZKAs zE#PN#KHO*SS`nPqj%x#InRQ8T*I8mre7DsvKx%E*cjQ!BXkilcX#C0rr$kn5(pq&; zH|(KM401>E)Dxzzge#7=QI&HZ(AUE|UBpxW0wG+4ygd~b;^^IRgS{;y;PNigujzaQ z4MbHIq0ysA!2JH|Mk%#V*~_tQ&SKR-o7MaIc(zm?d3!? z=hncs(s3wPm2&Ma%SX4STd6c+*MW_xKU6#)jkym}GE-BI9}8GZ+*tktz6Q!HO#R^q z()YFV?$6lOk*DkQ$|BzVWWmgtf3QRmKorry>f=QiBaU-`75Dt7$D2hNxNBTY-&r;oQ&G*ZpDF0AU)TYH7<+rB1z8(a$wo`e|izNElp%_ndS&$jYYbki6scB zqqmS68O6>n$bC_XH_Ot$MlO z?99*4CrqzBzLeW;A->ernk6+kouonXX&ly2r=?Yic+A6KPo=AoH{5tRB~XCL10t(8 z16k_O!^b5sB5N+H54*h$JWcK2f7Z^L2D@6P7N%p839W?0PQXRdn%-8-%O8Su?+ol_ z7o(uwV@*|HX!S2MDAEZBR9$#H`XA90uCu;++YV>WKF1&fn}s)yh=X?<+s|Q7J$GVA zI_@OvW?jJ(MT;EgXP*B+_?~PmI!JCp@?qeEF`GR~221YksWpj}bDELFDeRs18Jn$U{?}#EZ|M(m<^zK}I7_=^DtU$HCGb z-&1fqbHNt`>xj<@R85W@f2Vd*E>PKNu-!jMgQKX~t{lC=xp0Fhd>#uHV9U}o(MXTOL6MUznX!7Ra#Tjz_ zTL&}FZ8i{$#hlS06^uL`4}CtTR#VVK5!J_c6|_NJ2Ht=y)Jbr(CnU7j=KEW5X>cim1TomaVO!kxob_Syr zBUQ4gRI4DD%sx-boHj3By&3M%Yx0dRccBG0zEDsaov-p>SLutaXj(aWfOrjjIy?o* z)%HDiY_R%3DT5}Hf)!lf6nV(@&QVU7b|#O&$P``+TU4Qe(5}kwdBTtZl`o>P+{T zeV*GB@wL(wz0#`X*5CDvR8G{PX!~B3ZORgJ7Ap;{x3cJCJ{-gkT_%oih@q&fHFB%u z{o+I_|AFO|$6pQYkRCj3f5aG@>_TdN@%cknE=Ka5J2vI+YM$af(<|gU7y2)LI#Rko z_onhcP2B+Mg?-Xf3w=hT(v^r;AMpuHExDD_>f9;`+D<2RPMZuv0`%+{)aFlD2)sRe z`}b0Oo@cvYB+n)K3PA52KF`Rmx)(ueUGenNgJT(W*`siJxb`V&8F<1%ZTPGZVaGT* zs#AV3s&J($(!wP7O6lpiUTe+#8MEx^_Et>h^TYqBrXF)V&JH>$6et7Oa9#6Rfo}Zl z1Js&Wp<`E+M5lk`%D>0#YnQL>Ji&u@FU%;&qhvI^>!LKmpG$E?l%0DOV&%^IY;=lD&TN0g}Doy=z5tI>~n6Rk+K3MQCo0_js z(x0HdpUpUfYH&3gm>&n~7%jq2_iyoZh1r(5;OBfu72oLJvv!vy<7c4~zAhRHV}tE2 z&9!KKaCMSYXMeXrm70}7@^MIFmBK%QC8)9DQcnH`uME0;iRzf~mhEoJ^t4Fa=5Jtf z^m433srpR0djqxyu}8LEmm0^0i*YF~Vl(|wm(CkZqw+1vaJ*!GJUdg8p?;pdVp;HL z!m@adzd%i&Rr4`t9c9?!ABi?7uJSl{Q>D`O35+AB#PW|;`{!0;B%VDh#=&N6(Q&2@ zk}meF|K#lroGb8Z;N{(`e=bS*=NZpm1M1n}U43zXt8?1Rsw1xRYhe6uVlnWNrUVXv zfQWbp4H*Ry1-zb#1b#^w5eJ}r!0|-QB4&zH%=qT{p|V8)lKkrrx*fw&rC}`p#7Y$T#aH3*L1=5JA+q9NvCAVhfyr4FTc4o zsS=Uf&8;Hv@6hrBmG?hOQT1(|VUb0jj_^tD;Vo|7%c^A<$197xPisxA;Pw1h~%zpl7<3or!BmWX9cN-XEQ`*`@wCBL_47%r)Si zY1P3Ha39ya+4jL+Xm&k!O~$WJ@7S%=-yr?OYb>=Aeg2s>$h9g%Ppd7*iPZtarkwWu z62wz+j$h?REA9QNZ}oX$c0~jBda+FLr*b^IlUrAq65v5a?|2x%Q8bXWLHndr0eTPf z8W`KGFR%J`^qKmYQ?@4~QGP?~CD*;eD?+J4`Q!`U*q+LMzJ7JKYoNY;xp;ci`p6FB zY|z}5|FLuX0>aA}?CewHBvBU#UOF9lm|-ukfvj2O>qG_`Z}(t-)VzsS|B&&}hB*Mt zUNU(N>~Z~=9s-Ejz7mypbYAj?%BC@mH^z$lH=%0uPg&qFJ$2x?B7Ayp$S47e)}AOY zkFF`vvRL-{s&e!t!Rvc*?d*pPW7S3T)4PYw1#EkCB` zoxZ93*tJ2#QhbuM-Q)ipHL2Aukfxmem`vIK5g8JST5a;l`uZ8cKP11Cit`Hgu4WnFr$f7^-FY#DL-j~}YLNo>zjt@7VrRhC(VEJO@Ssh86d_tb((L=0f zbZ^Q?(g$BOZUf(0L^u0Vyi#;EeaW>x#J)oqF?nzMt7DT}Q|}vp-oS>s(KG4S9g#GP zC74pD?~`BDs0qLSbffijQDOU|)N?!ez7W%6jYq#zr#pGioX$}L z=>tXq~=zuW_tX|&Pn=_6>y<^I z0aND-7H7WRw{hwXFNl6|E~jyRBc_mefN$Jmb|&=$yomOLDEwozhfoef@%k1*`Y{dm z>!a5JG2L4>=C2ct#}dcyy+NXub?$R-tEi=~#bqpmd}4j~8G%}^NCMZ@F|&mv7j->n zD^e=@DnE1`!KILRV3P7kVZo~=6ou{N;ViSy(c@C1H>~z5|1O*7Azj8bYe0;&bh|Mrjr@9*^4KT4#IG~a=cXyj8 zUX(^JT&l#DHKR-&-rGJvESqgS1uo*>`tQF$+4!k_)W10T=DGUJNmFzJq_{<4`{}vI zYrUe1A!m=B@w-Q__fO6RQ!Qq5@Jd3o{&;1Ry;&pb2SyxdIw(iE=q1cC*o3n!1t536=52CELYV6 z;UibZkk7+WLZqp7!AmUqKuNmNM{mYQ%#N`YtF)IocXDb20|uzh_KzxRtb!2@`3hVy z3x_`y{!pUQKRNP;>>)PrK&*UqY=Iw4G_(2O}7Z& zvulq+`d>hXL|P8So-h`obH@;{-UFJQ%PSJqUOjxmcO~K_Aw`Q9&b5KA#T|_4j%%Q; zNU~JAy+HABg0F+mv6>&60QB1}p3a>GYWEmVP@QZ(33VH5Z*Q|$wkaq`O(at>E*y>d z5OA)i0@y9(k~tU5r(7BmMfd4{)6nIW#WpJVkPWL%G{F8OPVpivo~ilEOBe62kbJXk za>U@TQKon{6cP9{tfBnIA(5WTzQQYV`WPX`B42S1F(+Z;zH%XKnG=2dOGn&Uh_Ufe zkIs7IZOx9|OvOl@&e2p+_z6cgCFI>0rE!mrA2UtsqG)7%INs2j{(${|(e;)=aRrOI z=->>_;1b;3-6g@@o#5^k+=B&ohk@X3!94_mOK=zn5ZqmICwt#_&Z}4T{!Ue|>8f7x zX}6~M!i%8*52bRskRt6e@+@o`d@e7*w;|nR-R2Noh_2n)WH%2T+))=uL4bKlr7?UJ zvS63jtvs$=sO(RXY>8!R?E#l3Hcu}eZi%mu?uxnCH4aKCn-L7SiD1f+s$WpB4drxK$OasFYKA{K{Co3`-vZFo_WKBCU^Ttm9tXXg|CBHp6D#}ag zUqD^dStP{Y&SA*T2_e(;e`)$%Tj6 z30a^Y0*8Gp+JY8;D(W|@gxpU0;FB;skicD4##hl<9HsCBcyf6b{p_!4lFGp=8l$YsaUJX*%nZ!wcptU^HolSgv%Azk zLl+-;FWL}3+*EeXo(oXSsjzny1~bt9V#*=|dpQ%2zvYb8!1^Jx%H;GoMv5X;)zPi5 z5F6*b-~IXTZ|h586iO^4?EcJY4?}<+B_3{D5ncCKbi6XfZT%gfKq2pllwEA*9$%t? z74N+MKk_G=vl?l+Juue`2qiCpCNNaqUEM&sDD=Ev0G{aKQ$B19(%o!XaBfh}-Pb{2 z?&XvL6BWeTHL77@ve4itc4Pld+a~bRj&4JmXEvIPozoEug+ZS!+i6BIbL8QmX4ex7 zrP6iEdFfffC7c7M39t1>v7y1CHqmDQJiI=Jto9ZFK8m=%Y5ZD^OpW$OyF_J8+>ds3 z-u@IF9H^!){sj}JQXNlY=O+otWfdI{6Mj>tup5m}w*))qrEZw-r6450*VEa-m3x8? zJ~q{-Z+^}f*j1(}xMzg_n8RgX`0}v?-$^`6=ldi-zkygiF;8N?)P=~a&^Qn6jUC;o z45wM(#l-sX&#{mVK#17MOo>D8R z-(T=MMmnz&c(RP@X$2=k&!e4q*`cOc3oj_|gX8@YO36EIaS;k39u^-A_GRIZGmVYX zfMuk5-m?Un34`-aZJXZaChblhsxJkRrv-VXlA;(f1W#TOD00Q2=2pe8!k;BQ!>dr0 zBwTXeW?qJF(3ZP>aa8ZzxU+vd6w1v+&Cm8U&wt(`#yq5V{Vz;~sZbo6!wd@|%ZWJY ztP06i*oPbfdQ6qIQPeE^hYw*~>T57@t0UHP&3JQCOPmv1j4c¬rQ5ICgQqK6efm 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 tqPP)}n4~H$Gv>hI8g=1pK-9zW{*nG>ZTL diff --git a/docs/blog/complex-prog/graph2.png b/docs/blog/complex-prog/graph2.png deleted file mode 100644 index a0da5e64f5fe03f2fabf38cac4ae17a07a1a4b2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31535 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 diff --git a/docs/blog/complex-prog/graph3.jpeg b/docs/blog/complex-prog/graph3.jpeg deleted file mode 100644 index 50ffee66f4625c00bedbe331fedda40ca9cbeea0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61410 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 T+++VJ1&=akzWPh&&lmp - - - - - - - - - - - - - - - - - - -Простое сложное программирование | NewLang - - - - - - - - - - - - - - - - - - - - - - - - - -

    - -
    -
    -
    -
    - - -
    - - - - -
    -

    Простое сложное программирование

    - - - -

    КДПВ

    -

    В очередной раз увидел на Хабре статью про сложное дело под названием «программирование». -И то, что программирование действительно является делом не простым воспринимается как факт и обычно не требует какого либо подтверждения.

    -

    Но понятие «сложность» сродни термину «куча». -Для кого-то и пять кокосов это не куча, а кого-то съел один и «больше не хочется» - значит для него и единственного кокоса будет много.

    -

    Так и со сложностью ПО. Вроде бы увеличение сложности является для всех очевидным и наблюдается во всех сферах применения IT технологий, -да и сами языки программирования по мере своего развития становятся все сложнее, -а вот оценивать «сложность» с помощью численных метрик — дело заведомо неблагодарное, но и «нельзя управлять тем, что невозможно измерить …».

    -

    Обычно разговоры о «сложности» включают в себя только оценочные суждения без какой либо численной оценки. -А так как лично меня интересует вопрос сложности языков программирования, -то я решил посчитать сложность реализации компилятора gcc в каких нибудь условных попугаях. -Вдруг можно будет увидеть какие нибудь закономерности?

    -

    Выбор «попугаев» для измерения

    -

    Я не стал придумывать свои или вычислять эмпирические метрики программного кода, -и в качестве «попугая» решил взять самую простую метрику SLOC (англ. Source Lines of Code) — количество строк исходного текста компилятора, -которая очень легко вычисляется.

    -

    Правда, с её помощью можно будет оценивать сложность языка только при следующем допущении — сложность языка должна находиться в прямой зависимости от сложности его реализации, -если для простых синтаксических конструкций будет требовать меньше кода, чем для более сложных.

    -

    Конечно, использование метрики «количество строк исходного кода» имеет и свои недостатки, -т.к. она сильно зависит от используемого языка программирования, стиля оформления исходного кода и в общем случае не позволяет сравнивать несколько разных проектов между собой.

    -

    Но для численной оценки сложности кода в рамках одного проекта, метрика SLOC подходит хорошо.

    -

    Методика подсчета SLOC

    -

    Изначально попробовал использовать простой bash скрипт с поиском по маске и подсчетом числа строк в файлах исходника через wc -l. -Но через некоторое время стало понятно, что приходится изобретать очередной велосипед.

    -

    Ну вы поняли

    -

    Поэтому решил взять уже готовый. После быстрого поиска остановился на утилите SLOCCount, -которая умеет анализировать почти три десятка типов исходников.

    -

    Список типов файлов для автоматического анализа

    -
        1. Ada (.ada, .ads, .adb) 
    -    2. Assembly (.s, .S, .asm) 
    -    3. awk (.awk) 
    -    4. Bourne shell and variants (.sh) 
    -    5. C (.c) 
    -    6. C++ (.C, .cpp, .cxx, .cc) 
    -    7. C shell (.csh) 
    -    8. COBOL (.cob, .cbl) as of version 2.10 
    -    9. C# (.cs) as of version 2.11 
    -    10. Expect (.exp) 
    -    11. Fortran (.f) 
    -    12. Haskell (.hs) as of version 2.11 
    -    13. Java (.java) 
    -    14. lex/flex (.l) 
    -    15. LISP/Scheme (.el, .scm, .lsp, .jl) 
    -    16. Makefile (makefile) — not normally shown. 
    -    17. Modula-3 (.m3, .i3) as of version 2.07 
    -    18. Objective-C (.m) 
    -    19. Pascal (.p, .pas) 
    -    20. Perl (.pl, .pm, .perl) 
    -    21. PHP (.php, .php[3456], .inc) as of version 2.05 
    -    22. Python (.py) 
    -    23. Ruby (.rb) as of version 2.09 
    -    24. sed (.sed) 
    -    25. SQL (.sql) — not normally shown. 
    -    26. TCL (.tcl, .tk, .itk) 
    -    27. Yacc/Bison (.y) </code>
    -

    Причем, считает не просто количество строк исходного текста, но и умеет игнорировать комментарии, -исключает из подсчета дубли файлов (сравнивает их хеш суммы), а также выводит расчетную трудоемкость, -примерную оценку стоимости разработки анализируемого проекта и другие характеристики.

    -

    Меня изначально интересовал объем исходников на С/С++ и может быть еще на Ассемблере, если таких файлов окажется достаточно много. -Но после начала работы очень обрадовался, что не стал изобретать велосипед, а взял готовую тулзу, -т.к. она отдельно считала статистику исходных файлов синтаксического анализатора Yacc/Bison (.y), -который и определяет фактическую сложность парсера (читай сложность синтаксиса языка программирования).

    -

    Старые исходники gcc брал с https://gcc.gnu.org/mirrors.html, но перед запуском анализатора удалил каталоги других компиляторов (ada, fortran, java и т.д.), -чтобы они не попадали в итоговую статистику.

    -

    Результаты в попугаях

    -

    -

    Итоговая статистика

    -

    -

    Объем кода синтаксического анализатора Yacc/Bison

    -

    -

    Объем общей которой базы GCC (только для языков C и C++)

    -

    Выводы

    -

    К сожалению, синтаксический анализатор Yacc/Bison использовался только до 3 версии, а после его использование свелось на нет. -Поэтому оценить сложность синтаксиса С/С++ с помощью объема кода парсера можно лишь примерно до 1996-98 года, -после чего его стали постепенно выпиливать, т.е. чуть менее, чем за десять лет. -Но даже за этот период объем кодовой базы синтаксического анализатора вырос двукратно, что примерно соответствует по времени реализации стандарта C99.

    -

    Но даже если не учитывать код синтаксического анализатора, то объем общей кодовой базы так же коррелирует с внедрением новых стандартов C++: C99, С11 и C14.

    -

    На графике не видно выраженного пика для С+17 и следующих версий, но предполагаю, -что при текущем объеме кодой базы (более 4 миллионов строк только С и С++ кода), несколько тысяч строк, -необходимых для поддержки синтаксических конструкций новых стандартов просто незаметно.

    -

    Вывод первый - очевидный. Рост сложности инструментов разработки

    -

    Фактически на примере проекта GCC можно видеть постоянный и неотвратимый рост сложности рабочих инструментов программистов.

    -

    И как бы не говорили о деградации разработки в статье “Хорошие времена рождают слабаков”, -о системном кризисе программного обеспечения, который носит поколенческом характер, но мне кажется тут дело немного в другом.

    -

    Обновление персонала и как следствие — необходимость обучения новых сотрудников старым наработкам, -тут дело не сколько в передаче знаний, сколько в возможности эти знания усваивать.

    -

    Причем возможность усвоения знаний для разных поколений будет разная, но не из-за того, что предыдущее поколение было умнее, а у нового поколения не хватает толку в этом разобрать. -Просто изменяется окружение и усложняются рабочие инструменты, по сравнению с теми, которые были в ходу у предыдущего поколения.

    -

    Вывод второй — порог входа

    -

    Представьте, что нужно «сделать свой сайт». Естественно нужно определить, какую CMS для него использовать и какой брать хостинг. -И если с хостингом вопрос решается очень просто, конечно же в TimeWeb, да еще и с бонусом по ссылке, то при выборе CMS приходится подумать.

    -

    И если для простых сайтов существуют и простые решения, то для тех, кто не ищет легких путей существует CMS Drupal, -который примечателен тем, что имеет фантастически высокий порог входа для начала использования.

    -

    Сложность внедрения Drupal

    -

    Это я к чему? При использовании любого инструмента, как и языка программирования, существует некий минимальный уровень комфортного использования. -Причем этот уровень прямо пропорционально связан с размером той целевой аудитории, для которой он предназначен. -Точнее, размер возможной аудитории определяется в том числе и требованиями к уровню начальных знаний и квалификации потенциального пользователя.

    -

    Итоговый вывод — не утешительный

    -

    Если рассматривать увеличение сложности только самого ПО, то это одно дело. Вот к примеру:

    -

    Статистика ядра Linux с вики

    -
    17 сентября 1991: Linux версии 0.01 (10 239 строк кода).
    -14 марта 1994: Linux версии 1.0.0 (176 250 строк кода).
    -Март 1995: Linux версии 1.2.0 (310 950 строк кода).
    -9 июня 1996: Linux версии 2.0.0 (777 956 строк кода).
    -25 января 1999: Linux версии 2.2.0, изначально довольно недоработанный (1 800 847 строк кода).
    -4 января 2001: Linux версии 2.4.0 (3 377 902 строки кода).
    -18 декабря 2003: Linux версии 2.6.0 (5 929 913 строк кода).
    -23 марта 2009: Linux версии 2.6.29, временный символ Linux — тасманский дьявол Tuz (11 010 647 строк кода).
    -22 июля 2011: релиз Linux 3.0 (14,6 млн строк кода).
    -24 октября 2011: релиз Linux 3.1.
    -15 января 2012: релиз Linux 3.3 преодолел отметку в 15 млн строк кода.
    -23 февраля 2015: первый релиз-кандидат Linux 4.0 (более 19 млн строк кода).
    -7 января 2019: первый релиз-кандидат Linux 5.0 (более 26 млн строк кода).
    -

    А что делать, если сложность программного обеспечения накладывается на тенденцию постоянного усложнения самих рабочих инструментов? -Ведь постоянное развитие языков программирования неизбежно повышает порог входа для всех начинающих и только усугубляет проблему сложности разработки ПО.

    -

    Другими словами, не зависимо от того, как хорошо документирован код и как полно он покрыт тестами, -через некоторое время устаревают используемые инструменты, завершаются жизненные циклы внешних зависимостей, -и самое главное, приходят новые люди взамен тех, кто разработал или сумел разобраться в системе.

    -

    И у новых людей возникает необходимость разбираться в системе с самого начала, но в других начальных условиях. -И из-за этого, сложность изучения системы для всех новых людей будет выше просто по факту того, -что изменились внешние условия и усложнились рабочие инструменты, которыми приходится использовать новым сотрудникам.

    -

    Понятно, что чем дальше, тем проще уже не будет. Ведь область IT , это среда с самой высокой конкуренцией. -И как уж тут не вспомнить Льюиса Кэррола, что его крылатое выражение

    -
    -

    Нужно бежать со всех ног, чтобы только оставаться на месте, а чтобы куда-то попасть, надо бежать как минимум вдвое быстрее!

    -
    -

    Ведь это относится не только к Алисе в стране чудес, но и ко всем информационным технологиям в целом!

    -

    Первоначальная публикация

    - - - -
    - - -
    -
    -
    -
    -
    -
    - -
    -
    -
    - -
    - - - - - - \ No newline at end of file diff --git a/docs/blog/dsl-domain-specific-language-implementation-with-macros/index.html b/docs/blog/dsl-domain-specific-language-implementation-with-macros/index.html index ef6d2cf8..5093789e 100644 --- a/docs/blog/dsl-domain-specific-language-implementation-with-macros/index.html +++ b/docs/blog/dsl-domain-specific-language-implementation-with-macros/index.html @@ -31,7 +31,7 @@ - + @@ -133,31 +133,9 @@ Articles @@ -237,9 +215,17 @@

    DSL (domain-specific language) implementation with macros

    -

    https://habr.com/articles/720416/

    -

    image -This is a translation of my own article

    + + +
    +

    Attention!!!

    +

    This article contains a description of the NewLnag syntax of the previous version.

    +

    Publication source https://habr.com/articles/720416/

    + +
    + +

    image

    +

    This is a translation of my own article

    The release of NewLang language with a brand new “feature” is coming, a remodeled version of the preprocessor that allows you to extend the language syntax to create different DSL dialects using macros.

    What is it about?

    @@ -387,10 +373,10 @@

    Conclusion
  • - Previous + Previous
  • - Next + Next
  • diff --git a/docs/blog/index.html b/docs/blog/index.html index b363833f..ad587441 100644 --- a/docs/blog/index.html +++ b/docs/blog/index.html @@ -126,31 +126,9 @@ Articles @@ -190,7 +168,7 @@

    Tag Cloud
    -
    Posts in 2022
    -
      -
    • -
      -
      Релиз языка программрования NewLang 0.3
      -

      Monday, November 07, 2022 in Articles

      - - - - - - -

      -Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -NewLang — это язык программирования высокого уровня общего назначения. Основной особенностью языка является …

      -

      Read more

      -
      -
    • -
    • -
      -
      Релиз языка программрования NewLang 0.2
      -

      Friday, August 12, 2022 in Articles

      - - - - - - -

      -Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -NewLang - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические …

      -

      Read more

      -
      -
    • -
    • -
      -
      Релиз языка программрования NewLang
      -

      Friday, June 24, 2022 in Articles

      - - - - - - -

      -Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -NewLang - это язык программирования высокого уровня, в котором можно сочетать стандартные алгоритмические …

      -

      Read more

      -
      -
    • -
    • -
      -
      Новый язык программирования
      -

      Friday, February 18, 2022 in Articles

      - - - - - - -

      -Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -Более года назад я начал публикацию статей с описанием особенностей нового языка программирования. С тех пор …

      -

      Read more

      -
      -
    • -
    -
    Posts in 2021
    -
      -
    • -
      -
      Можно ли использовать декларативный и императивный стили написания программ одновременно?
      -

      Monday, July 26, 2021 in Articles

      - - - - - - -

      -Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -При разработке своего собственного языка программирования автор должен определиться, какими свойствами его …

      -

      Read more

      -
      -
    • -
    • -
      -
      Необычная концепция синтаксиса языка программирования
      -

      Monday, May 24, 2021 in Articles

      - - - - - - -

      -Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -Хочу представить на обсуждение читателей немного необычный концепт языка программирования, в котором …

      -

      Read more

      -
      -
    • -
    • -
      -
      Простое сложное программирование
      -

      Thursday, April 15, 2021 in Articles

      - - - - - - -

      -В очередной раз увидел на Хабре статью про сложное дело под названием «программирование». И то, что программирование действительно является делом не простым воспринимается как факт и обычно не требует какого либо подтверждения. -Но понятие …

      -

      Read more

      -
      -
    • -
    - -
    + diff --git a/docs/blog/index.xml b/docs/blog/index.xml index 4881ed51..2dab1dc7 100644 --- a/docs/blog/index.xml +++ b/docs/blog/index.xml @@ -15,7 +15,7 @@ - Blog: Релиз языка программрования NewLang 0.4 + Blog: Release of the programming language NewLang 0.4 http://localhost:1313/blog/release-v0.4/ Tue, 06 Jun 2023 00:00:00 +0000 @@ -23,111 +23,26 @@ - <p><img alt="КДПВ" src="http://localhost:1313/blog/langs.jpeg"></p> - - -<div class="pageinfo pageinfo-primary"> -<p>Внимание!!!</p> -<p>&ldquo;nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии.</p> -<p>Актуальную версию синтаксиса языка можно посмотреть <a href="http://localhost:1313/docs/">тут</a>.</p> - -</div> - -<p>ssssssssssssssssssssssssssssssssssssssssssssss</p> - - - - - - Blog: Нюансы разработки парсера для своего языка программирования - http://localhost:1313/blog/parser-nuances/ - Wed, 29 Mar 2023 00:00:00 +0000 - - http://localhost:1313/blog/parser-nuances/ - - - - <p><img alt="КДПВ" src="http://localhost:1313/blog/langs.jpeg"></p> -<p>Недавно прочитал на Хабре статью <a href="https://habr.com/post/723400/">Свой язык, или как я устал от ассемблера и С</a>, и невольно взглядом зацепился за один абзац:</p> -<blockquote> -<p>Я решил не сильно париться, поэтому использовал библиотеку parglare. Она очень легкая и удобная, всем рекомендую. Для описания синтаксиса парсер принимает строку в соответствующем формате, использует регулярные выражения (не надо осуждать регулярки, они всесильны!).</p> -</blockquote> -<p>В результате решил опубликовать статью на основе своих старых записей еще с тех времен, когда идея <a href="https://newlang.net/">NewLang</a> до конца еще не выкристаллизовалась, но уже хотелось писать реальный код и тестировать разные концепции.</p> -<p>Ведь в жизни практически любого программиста может наступить момент, когда ему в голову приходит светлая идея - разработать свой собственный язык программирования. Может быть и не ради захвата мира, наравне с C/C++, Python или хотя бы PHP, а в качестве личного пет-проекта, с которым он, длинными зимними вечерами будет оттачивать собственное мастерство.</p> -<p>А так как у любого языка (не только программирования), все начинается с анализа его грамматики, то самой первой задачей создателя будет выбор инструментов для синтаксического анализа исходного текста.</p> -<p>Это история — заметки на память о муках выбора связки лексер-парсер для разбора грамматики NewLang. А так же попытка описать и систематизировать выводы об особенностях разных анализаторов с которыми пришлось поработать при выборе парсера для разбора грамматики у своего языка программирования.</p> -<h3 id="используемые-термины">Используемые термины.<a class="td-heading-self-link" href="#%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d0%b5%d0%bc%d1%8b%d0%b5-%d1%82%d0%b5%d1%80%d0%bc%d0%b8%d0%bd%d1%8b" aria-label="Heading self-link"></a></h3> -<p>Чтобы было понятно, о чем в дальнейшем пойдет речь.</p> -<blockquote> -<p>Лексер — компьютерная программа или библиотека, в задачи которой входит разделить входной поток данных на отдельные, не связанные между собой отдельные фрагменты, которые принято называть токенами или лексемами.</p> -<p>Парсер — на основе последовательности токенов выполняется синтаксический анализ, например строит абстрактное синтаксическое дерево (AST).</p> -</blockquote> -<h2 id="заход--1---flex--bison">Заход № 1 - Flex + Bison<a class="td-heading-self-link" href="#%d0%b7%d0%b0%d1%85%d0%be%d0%b4--1---flex--bison" aria-label="Heading self-link"></a></h2> -<p><a href="https://github.com/westes/flex">GitHub - westes/flex: The Fast Lexical Analyzer - scanner generator for lexing in C and C++</a> -<a href="https://www.gnu.org/software/bison/">Bison - GNU Project - Free Software Foundation</a></p> -<p>После прочтения умных книжек я начал с классики Flex + Bison. Это старые и давно отработанные приложения с широчайшими возможностями по настройке с помощью которых можно описать синтаксис и получить исходные файлы лексера и парсера для языка практически с любой грамматикой.</p> -<p>К сожалению, у этих старичков очень большой порог входа и тяжелая наследственность. Чего только стоит определение собственного класса лексера через <code>#define</code>, а так же отсутствие нормальной поддержки С++. Вынужденные танцы с бубном для пасинга отдельной строки, когда не требуется анализировать файл целиком и прочие не всегда очевидные проблемы и разные не понятные условности.</p> -<p>Другими словами, через несколько недель безуспешных мучений я решил посмотреть альтернативы, а так как начальный файл лексики после экспериментов с Flex + Bison кое-как уже был сделан, то следующая связка была Flex + lemon.</p> -<h2 id="заход--2---flex--lemon">Заход № 2 - Flex + Lemon<a class="td-heading-self-link" href="#%d0%b7%d0%b0%d1%85%d0%be%d0%b4--2---flex--lemon" aria-label="Heading self-link"></a></h2> -<p><a href="https://www.sqlite.org/lemon.html">The Lemon LALR(1) Parser Generator</a></p> -<p>Тут все оказалось до примитивности просто и понятно. Реально очень быстрый старт с боевыми примерами, очень наглядный и понятный способ записи правил (по сравнению с Bison). Все хорошо кроме одного, хорошее быстро заканчивается, если приходится анализировать более одной строки.</p> -<p>По сути, Lemon с Bison, это как Инь и Янь. Lemon простой и удобный для работы с одной строкой (для этого он и создавался), а Bison супер-пупер-мега комбайн для парсинга файлов любых размеров.</p> -<p>Поэтому, поиски связки лексер + парсер продолжились и после прочтения очередной статьи, что парсеры языков можно делать на регулярках, решил посмотреть, что есть в этом направлении:</p> -<h2 id="заход--3-парсер-на-регулярках-re2c">Заход № 3 парсер на регулярках re2c<a class="td-heading-self-link" href="#%d0%b7%d0%b0%d1%85%d0%be%d0%b4--3-%d0%bf%d0%b0%d1%80%d1%81%d0%b5%d1%80-%d0%bd%d0%b0-%d1%80%d0%b5%d0%b3%d1%83%d0%bb%d1%8f%d1%80%d0%ba%d0%b0%d1%85-re2c" aria-label="Heading self-link"></a></h2> -<p>Из описания <a href="https://re2c.org/">re2c</a>:</p> -<blockquote> -<p>По сути, на этой штуке можно писать лексические анализаторы прямо на коленке за несколько минут.</p> -</blockquote> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic">/*!re2c -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYPEEK = &#34;*cursor&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYSKIP = &#34;++cursor;&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYBACKUP = &#34;marker = cursor;&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYRESTORE = &#34;cursor = marker;&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYBACKUPCTX = &#34;ctxmarker = cursor;&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYRESTORECTX = &#34;cursor = ctxmarker;&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYRESTORETAG = &#34;cursor = ${tag};&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYLESSTHAN = &#34;limit - cursor &lt; @@{len}&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYSTAGP = &#34;@@{tag} = cursor;&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYSTAGN = &#34;@@{tag} = NULL;&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYSHIFT = &#34;cursor += @@{shift};&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYSHIFTSTAG = &#34;@@{tag} += @@{shift};&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> */</span> -</span></span></code></pre></div><p>Показалось, что это самый удобный способ указания шаблонов для парсера! Достаточно описать в комментариях нужные шаблоны, напустить на исходный файл компилятор регулярок и все готово! Но нет, действительно, это только показалось.</p> -<p>Ведь для простеньких парсеров или регулярных выражений <strong>re2c</strong> может быть и действительно хорош, но отлаживать синтаксис большого языка на регулярках слишком хлопотное занятие.</p> -<p>После этого решил с ним не заморачиваться и посмотреть альтернативы классическим лексерам и парсерам.</p> -<h2 id="заход--4---flex-flexcpp--bisoncpp">Заход № 4 - flex (flexcpp) + bisoncpp<a class="td-heading-self-link" href="#%d0%b7%d0%b0%d1%85%d0%be%d0%b4--4---flex-flexcpp--bisoncpp" aria-label="Heading self-link"></a></h2> -<p>Тогда как у традиционных flex + bison поддержка С++ реализована <del>через одно место</del> на уровне - работает и не трогай, то решил посмотреть их альтернативную реализация <a href="https://gitlab.com/fbb-git/flexcpp">flexcpp</a> + <a href="https://gitlab.com/fbb-git/bisoncpp">bisoncpp</a> с нативной поддержкой С++.</p> -<p>Первое впечатление было, то что доктор прописал!</p> -<p>Синтаксис записи лексики хоть немного и отличается от классической, но это не принципиально. Зато есть нативная и логичная поддержка С++ без оберток и выкрутасов, и как дополнительный плюс - более удобный синтаксис указания правил в парсере. Но и тут не обошлось без шероховатостей.</p> -<p>В шаблонах правил bisoncpp не поддерживает юникод (хотя сам лексер-парсер с ним справляется на ура), и совсем не понятная ситуация с поддержкой. Как я понял, разработчиком является вроде бы один человек, но пообщаться с ним насчет ошибок при обработке русских символов так и не получилось.*</p> -<p>Потом еще одно непонятное поведение вылезло в другом месте. В результате решил отказаться от недружелюбной поддержки и посмотреть, какие есть еще варианты парсеров.</p> -<hr> -<p>*) Через два года мой тикет был закрыт с комментарием, что поддерживаются только ascii символы.</p> -<h2 id="заход--5---неродной-парсер-antlr">Заход № 5 - неродной парсер ANTLR<a class="td-heading-self-link" href="#%d0%b7%d0%b0%d1%85%d0%be%d0%b4--5---%d0%bd%d0%b5%d1%80%d0%be%d0%b4%d0%bd%d0%be%d0%b9-%d0%bf%d0%b0%d1%80%d1%81%d0%b5%d1%80-antlr" aria-label="Heading self-link"></a></h2> -<p>От использования <a href="https://www.antlr.org/">ANTLR</a> (от англ. ANother Tool for Language Recognition — «ещё одно средство распознавания языков») — генератора нисходящих анализаторов для формальных языков, я решил сразу отказать из-за того, что он написан на Java,.</p> -<p>В этом нет никаких религиозных предпочтений, так как я искал генератор парсеров, который можно было бы сделать встроенным прямо в среду выполнения, а в случае с ANTLR и JRE это было бы затруднительно.</p> -<p>Таким образом я опять вернулся к старичкам Flex и Bison, с которых все и начиналось.</p> -<h2 id="заход--6-последний---возвращение-к-flex--bison">Заход № 6, последний - возвращение к Flex + Bison<a class="td-heading-self-link" href="#%d0%b7%d0%b0%d1%85%d0%be%d0%b4--6-%d0%bf%d0%be%d1%81%d0%bb%d0%b5%d0%b4%d0%bd%d0%b8%d0%b9---%d0%b2%d0%be%d0%b7%d0%b2%d1%80%d0%b0%d1%89%d0%b5%d0%bd%d0%b8%d0%b5-%d0%ba-flex--bison" aria-label="Heading self-link"></a></h2> -<p>Все описанные выше эксперименты заняли в общем итоге несколько месяцев, в результате которых были написаны килобайты исходного кода и тестовых примеров, прочитано десятки статей и как результат - возврат к изначальной связке Flex + Bison, но уже с солидным багажом опыта в применении различных вариантов лексеров-парсеров.</p> -<p>Но самое главное, с пониманием того, что же в результате хочется получить, и очень большой базой тестовых примеров синтаксиса.</p> -<h2 id="выводы-на-память">Выводы на память<a class="td-heading-self-link" href="#%d0%b2%d1%8b%d0%b2%d0%be%d0%b4%d1%8b-%d0%bd%d0%b0-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d1%8c" aria-label="Heading self-link"></a></h2> -<p>В итоге для себя решил следующее: если нужен простенький шаблонизатор, то идеальный вариант <strong>re2c</strong> (если почему-то не подходит <strong>regexp</strong>). Если требуется анализировать синтаксис сложнее обычных регулярок, но в одну строку, то идеальной будет связка flex+lemon, а если нужна серьезная артиллерия, то тут однозначно flex + bison.</p> -<p>От связки flexcpp + bisoncpp отказался совсем. Что с поддержкой — не понятно, синтаксис от классики отличается не очень сильно (хотя тоже нужно ломать голову), а обход выявленных косяков не стоят того синтаксического сахара.</p> -<p>И по итогам множества экспериментов с разными вариантами синтаксиса удалось сформулировать пару важных архитектурных моментов, которые могут очень сильно упростить жизнь создателям языком программирования:</p> -<h2 id="стратегия-обработки-ошибок-синтаксиса">Стратегия обработки ошибок синтаксиса<a class="td-heading-self-link" href="#%d1%81%d1%82%d1%80%d0%b0%d1%82%d0%b5%d0%b3%d0%b8%d1%8f-%d0%be%d0%b1%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b8-%d0%be%d1%88%d0%b8%d0%b1%d0%be%d0%ba-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81%d0%b0" aria-label="Heading self-link"></a></h2> -<p>Обычно принято обрабатывать синтаксические ошибки непосредственно в парсере и для этого есть определенный резон — в этом случае нет необходимости в каких либо дальнейших действиях, нужна только полностью описанная корректная грамматика.</p> -<p>Но если грамматика языка очень сложная (привет C++), и её описание становится сложной задачей, то можно отказался и от анализа ошибок синтаксиса непосредственно в парсере! То есть, лучше сделать максимально широкую лексику (даже с теми вариантами, которые являются для языка ошибочными), но ловить эти ошибки уже при анализе AST!</p> -<p>В этом случае, поддерживать описание грамматики языка становится значительно проще (меньше синтаксических правил, проще их формальное описание и т.д.), а самое главное, при описании грамматики не нужно думать про lval или rval, где можно указывать ссылку, а где нет — т. е. можно указывать все и везде, а вот анализ допустимости использования конкретных терминов будет выполняться позднее при анализе AST.</p> -<p><em>Отказа от полного анализа грамматики языка на уровне лексера — парсера и перенос проверки корректности синтаксических конструкций на этап разбора синтаксического дерева позволяет в разы, если не на порядки сократить и значительно упростить описание грамматических правил!</em></p> -<p>Подобное допущение очень полезно на начальном этапе создания языка (можно сосредоточиться на общей концепции, вместо постоянных правок в грамматике), а так же значительно упростить в будущем поддержку и/или расширение синтаксиса.</p> -<h2 id="макросы-и-модификация-грамматики-в-runtime">Макросы и модификация грамматики в Runtime<a class="td-heading-self-link" href="#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b8-%d0%bc%d0%be%d0%b4%d0%b8%d1%84%d0%b8%d0%ba%d0%b0%d1%86%d0%b8%d1%8f-%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b0%d1%82%d0%b8%d0%ba%d0%b8-%d0%b2-runtime" aria-label="Heading self-link"></a></h2> -<p>Какими бы мощными не были flex+bison, но у этой связки есть одна архитектурная проблема. Логика flex и bison построена на конечных автоматах и изменить грамматику языка во время выполнения приложения невозможно, тем более Bison сам вызывает лексер для получения очередной порции данных и ему очень непросто подсунуть измененные данные прямо во время работы. А так хотелось сделать возможность раскрытия макросов и модификации синтаксиса за один проход анализатора!</p> -<p>Для этого пришлось переделать логику работы flex+bison, чтобы парсер получал данные из лексера не напрямую из yylex, а через функцию — прокси. Эта промежуточная функция, складывает считанные лексемы во внутренний буфер. Данные в буфере анализируется на предмет наличия макросов и только после их раскрытия, лексемы отдаются в парсер из вершины буфера по одной за раз. Подробнее о макросах NewLang можно почитать <a href="http://localhost:1313/blog/2023/03/01/%D0%B2%D0%B0%D1%80%D0%B8%D0%B0%D0%BD%D1%82-%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8-dsl-domain-specific-language-%D1%81-%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E-%D0%BC%D0%B0%D0%BA%D1%80%D0%BE%D1%81%D0%BE%D0%B2/">тут</a>.</p> -<h2 id="самое-главное-при-разработке-грамматики">Самое главное при разработке грамматики!<a class="td-heading-self-link" href="#%d1%81%d0%b0%d0%bc%d0%be%d0%b5-%d0%b3%d0%bb%d0%b0%d0%b2%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%b8-%d1%80%d0%b0%d0%b7%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b5-%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b0%d1%82%d0%b8%d0%ba%d0%b8" aria-label="Heading self-link"></a></h2> -<p>Но самый важный совет мне подсказал друг, который некогда участвовал в проекте по разработке парсера для языка программирования. И в правильности его совета - <strong>пиши тесты для грамматики</strong> - я убеждался уже множество раз. Даже так, <strong>ПИШИ ТЕСТЫ ДЛЯ ГРАММАТИКИ</strong>.</p> -<p>Тесты для грамматики языка гораздо более важная вещь, чем любой из используемых инструментов. Только тесты позволяют убедиться в том, что новая фича в языке не сломала старые наработки. А если все же сломала, то в первую очередь нужно добавить новый тест, который бы фиксировал сломавшийся сценарий и только после этого можно будет со спокойной душой продолжать эксперименты с новыми грамматическими конструкциями.</p> -<p>И удачи всем языкописателям!</p> -<p><a href="https://habr.com/companies/timeweb/articles/724146/">Ссылка на первую публикаци</a></p> + <h2 id="new-features-and-changes-in-the-syntax-of-newlang">New features and changes in the syntax of NewLang<a class="td-heading-self-link" href="#new-features-and-changes-in-the-syntax-of-newlang" aria-label="Heading self-link"></a></h2> +<ul> +<li>Reworked the definition of object types using <a href="https://newlang.net/docs/syntax/naming/">prefix naming (sigils)</a></li> +<li>Interrupting the execution flow and returning can now be done for <a href="https://newlang.net/docs/ops/throw/">named code blocks</a>.</li> +<li>Simplified the syntax for importing <a href="https://newlang.net/docs/types/native/">native variables and functions (C/C++)</a></li> +<li>Stabilized the syntax for <a href="https://newlang.net/docs/ops/create/#comprehensions">initializing tensor, dictionary, and function argument values</a> with initial data.</li> +<li>Added built-in macros for writing code using keywords in a <a href="https://newlang.net/docs/syntax/dsl/">DSL style</a></li> +</ul> +<h2 id="new-compiler-features-nlc">New compiler features (nlc)<a class="td-heading-self-link" href="#new-compiler-features-nlc" aria-label="Heading self-link"></a></h2> +<ul> +<li>Completely redesigned the macroprocessor.</li> +<li>Reworked the compiler architecture with division into parser, macroprocessor, syntax analyzer, interpreter, and code generator.</li> +</ul> +<h2 id="miscellaneous">Miscellaneous<a class="td-heading-self-link" href="#miscellaneous" aria-label="Heading self-link"></a></h2> +<ul> +<li>The documentation <a href="http://newlang.net">website</a> has been translated to <a href="https://gohugo.io/">Hugo</a> and made bilingual.</li> +<li>Instead of binary builds, a section <a href="https://newlang.net/playground/">Playground and example code</a> has been added to the website for small experiments.</li> +<li>Transition to clang-16 has been completed (transition to clang-17 and newer is planned after full implementation of coroutines and support for extended floating-point number formats).</li> +<li>The number of project contributors has increased to more than one!</li> +</ul> @@ -141,9 +56,17 @@ - <p><a href="https://habr.com/articles/720416/">https://habr.com/articles/720416/</a></p> -<p><img alt="image" src="https://habrastorage.org/webt/r9/4d/tu/r94dtuimvtiiuntx5xpunndaetq.jpeg"> -<a href="https://habr.com/company/timeweb/blog/719332/">This is a translation of my own article</a></p> + + +<div class="pageinfo pageinfo-primary"> +<p>Attention!!!</p> +<p>This article contains a description of the NewLnag syntax of the previous version.</p> +<p>Publication source <a href="https://habr.com/articles/720416/">https://habr.com/articles/720416/</a></p> + +</div> + +<p><img alt="image" src="https://habrastorage.org/webt/r9/4d/tu/r94dtuimvtiiuntx5xpunndaetq.jpeg"></p> +<p><a href="https://habr.com/company/timeweb/blog/719332/">This is a translation of my own article</a></p> <p>The release of <strong><a href="https://newlang.net/">NewLang</a></strong> language with a brand new &ldquo;feature&rdquo; is coming, a remodeled version of the preprocessor that allows you to extend the language syntax to create different DSL dialects using macros.</p> <h3 id="what-is-it-about">What is it about?<a class="td-heading-self-link" href="#what-is-it-about" aria-label="Heading self-link"></a></h3> <blockquote> @@ -292,2106 +215,5 @@ while( true ) { - - Blog: Релиз языка программрования NewLang 0.3 - http://localhost:1313/blog/release-v0.3/ - Mon, 07 Nov 2022 00:00:00 +0000 - - http://localhost:1313/blog/release-v0.3/ - - - - <p><img alt="КДПВ" src="http://localhost:1313/blog/langs.jpeg"></p> - - -<div class="pageinfo pageinfo-primary"> -<p>Внимание!!!</p> -<p>Данная статья содержит описание синтаксиса NewLnag предыдущей версии.</p> -<p>Актуальную версию синтаксиса языка можно посмотреть <a href="http://localhost:1313/docs/">тут</a>.</p> - -</div> - -<p>NewLang — это язык программирования высокого уровня общего назначения. Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан на строгой системе грамматических правил. За счет использования макросов, синтаксис языка легко расширяется до более привычного вида на основе ключевых слов.</p> -<p>NewLang находится в процессе активного развития. Это третий публичный <a href="https://github.com/rsashka/newlang/releases/tag/v0.3.0">релиз</a> в который добавлены новые существенные возможности по сравнению с предыдущей версией.</p> -<h2 id="зачем-нужен-newlang">Зачем нужен <em>NewLang</em>?<a class="td-heading-self-link" href="#%d0%b7%d0%b0%d1%87%d0%b5%d0%bc-%d0%bd%d1%83%d0%b6%d0%b5%d0%bd-newlang" aria-label="Heading self-link"></a></h2> -<p>У всех современных языков программирования происходит постоянное развитие (усложнение) синтаксиса по мере выхода новых версий. Это является своего рода платой за появление новых возможностей и воспринимается пользователями как естественное явление.</p> -<p>Но одновременно является и серьезной проблемой, так как с выходом версий добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки и поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.</p> -<p>У <em>NewLang</em> сложность языковых конструкций ограничена естественным образом за счет разделения синтаксиса языка на две части - это упрощает его изучение и использование.</p> -<p><em>Основной синтаксис</em> — для написания программ в объектно-ориентированном (императивном) и декларативном стилях, который основан не на зарезервированных ключевых словах, а на системе строгих <a href="http://localhost:1313/docs/syntax/">грамматических правил</a>. Имеется возможность расширения основного синтаксиса за счет использования макросов. <em>Расширенный синтаксис</em> — программные вставки на языке реализации (С/С++), когда основного синтаксиса становится недостаточно.</p> -<p>Еще одно неудобство современных языков в том, что большинство из них были созданы до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек. Это же касается и вычислений с неограниченной точностью, которые так же требуют применения дополнительных библиотечных функций.</p> -<p>У <em>NewLang</em> тензорные вычисления и рациональные числа неограниченной точности доступны «из коробки». Они поддерживаются на уровне синтаксиса для записи литералов соответствующих типов, а простые арифметические типы данных являются скалярами (тензорами нулевой размерности). Реализация тензорных вычислений сделана на базе библиотеки <a href="https://pytorch.org/">libtorch</a>, а рациональные числа с использованием <a href="https://github.com/openssl/openssl/blob/master/crypto/bn/README.pod">OpenSSL</a>.</p> -<h2 id="новые-глобальные-фичи-и-изменения-в-синтаксисе">Новые глобальные фичи и изменения в синтаксисе:<a class="td-heading-self-link" href="#%d0%bd%d0%be%d0%b2%d1%8b%d0%b5-%d0%b3%d0%bb%d0%be%d0%b1%d0%b0%d0%bb%d1%8c%d0%bd%d1%8b%d0%b5-%d1%84%d0%b8%d1%87%d0%b8-%d0%b8-%d0%b8%d0%b7%d0%bc%d0%b5%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b2-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81%d0%b5" aria-label="Heading self-link"></a></h2> -<h3 id="простые-чистые-функции-удалены">Простые чистые функции удалены<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%be%d1%81%d1%82%d1%8b%d0%b5-%d1%87%d0%b8%d1%81%d1%82%d1%8b%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d1%83%d0%b4%d0%b0%d0%bb%d0%b5%d0%bd%d1%8b" aria-label="Heading self-link"></a></h3> -<p>Раньше я пытался использовать синтаксис предикатов из Пролога, в котором проверки условий записываются через запятую. Но эта идея оказалась провальной, а сами операторы просто ужасными (тестировал разные варианты, но каждый раз получал много отрицательных отзывов), поэтому сейчас решил полностью от них отказаться.</p> -<p>Они получались не только сложными для восприятия, но и по факту не нужными, так как легко заменялись обычной функцией с комбинации обычных логических операций.</p> -<h3 id="зафиксирован-синтаксис-операторов-проверки-условияdocsopsif-и-цикловdocsopswhile">Зафиксирован синтаксис операторов проверки <a href="http://localhost:1313/docs/ops/if/">условия</a> и <a href="http://localhost:1313/docs/ops/while/">циклов</a>.<a class="td-heading-self-link" href="#%d0%b7%d0%b0%d1%84%d0%b8%d0%ba%d1%81%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d0%be%d0%b2-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b8-%d1%83%d1%81%d0%bb%d0%be%d0%b2%d0%b8%d1%8fdocsopsif-%d0%b8-%d1%86%d0%b8%d0%ba%d0%bb%d0%be%d0%b2docsopswhile" aria-label="Heading self-link"></a></h3> -<p>Изменен и упрощен синтаксис операторов проверки условия (импликации) и цикла, для которых оставлено только по одному варианту. Проверка условия записывается в виде оператора математического следования <strong>&ndash;&gt;</strong>, а цикл с помощью оператора <strong>&lt;-&gt;</strong>.</p> -<p>Но для упрощения записи можно пользоваться макросами, тогда в этом случае операции проверки условий и циклы превращаются в классические</p> -<pre tabindex="0"><code>\if(...){ - ... -} \elif(...) { - ... -} \else { - ... -}; -</code></pre><p>или</p> -<pre tabindex="0"><code> \while( ... ){ - ... -}; -</code></pre><h3 id="конструкция-else-у-операторов-цикла">Конструкция else у операторов цикла<a class="td-heading-self-link" href="#%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%86%d0%b8%d1%8f-else-%d1%83-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d0%be%d0%b2-%d1%86%d0%b8%d0%ba%d0%bb%d0%b0" aria-label="Heading self-link"></a></h3> -<p>Теперь оператор цикла <strong>while</strong> поддерживает конструкцию <a href="http://localhost:1313/docs/ops/while/"><strong>else</strong></a>, которая выполняется если условие входа в цикл не было выполнено. <em>Это поведение отличается от аналогичных конструкций в языке Python, у которого секция <strong>else</strong> выполняется всегда, кроме прерывания цикла по break.</em></p> -<p>Ветка <strong>else</strong> у оператора цикла записывается так же как и ветка иначе в условном операторе, т. е.</p> -<pre tabindex="0"><code>[ cond ] &lt;-&gt; { - ... -}, [_] --&gt; { - ... -}; -</code></pre><p>Или тоже самое, но с использованием макросов:</p> -<pre tabindex="0"><code>\while(cond) { - ... -} \else { - ... -}; -</code></pre><h3 id="пространства-имен">Пространства имен<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%be%d1%81%d1%82%d1%80%d0%b0%d0%bd%d1%81%d1%82%d0%b2%d0%b0-%d0%b8%d0%bc%d0%b5%d0%bd" aria-label="Heading self-link"></a></h3> -<p>В синтаксис NewLang добавлены <a href="http://localhost:1313/docs/syntax/namespace/">пространства имен</a>, в стиле очень похожим на С++. Имена разделяются двойным двоеточием, а для определение пространства имен, его нужно указать перед открывающейся фигурной скобкой.</p> -<pre tabindex="0"><code>ns { - name { - var := 0; # Имя переменной будет ns::name::var - ::var := 1; # Переменная из глобального пространства имен - } -} -</code></pre><h3 id="программные-модули">Программные модули<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%bd%d1%8b%d0%b5-%d0%bc%d0%be%d0%b4%d1%83%d0%bb%d0%b8" aria-label="Heading self-link"></a></h3> -<p>Реализована концепция программных модулей - которая повторяет концепцию иерархического расположения файлов в структуре каталогов файловой системы, как в языках Python и Java.</p> -<p>Имя модуля начинается на префикс <strong>@</strong>, а структура каталогов указывается через точку. Причем концепции программных модулей и пространства имен объединены, и полное имя переменой из предыдущего абзаца будет <code>@root.dir.module::ns::name::var</code>, где <strong>root</strong> и <strong>dir</strong> это каталоги в файловой системе, а <strong>module</strong> — имя файла.</p> -<h3 id="объектно-ориентированное-программирование">Объектно ориентированное программирование<a class="td-heading-self-link" href="#%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%bd%d0%be-%d0%be%d1%80%d0%b8%d0%b5%d0%bd%d1%82%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> -<p>Реализована часть концепции ООП и добавлена поддержка <a href="http://localhost:1313/docs/types/class/">определения классов</a> и их наследование, которая сейчас выглядит следующим образом:</p> -<pre tabindex="0"><code>:NewClass := :Class() { # Новый тип (класс) - field := 1; - method() := {}; -}; -obj := :NewClass(); # Экземпляр класса -</code></pre><p>Неожиданно для самого себя понял, что имея полный набор вариантов проверок при создании объектов (<strong>::=</strong> - создать новый объект, <strong>:=</strong> - создать новый или присвоить значение существующему, <strong>=</strong> - только присвоить значение, а если объект не существует будет ошибка), концепция переопределения наследуемых функций не требует вообще никаких ключевых слов:</p> -<pre tabindex="0"><code>:NewClass2 := :NewClass() { # Новый класс на базе существующего - field ::= 2; # Будет ошибка, т. к. поле field уже есть в базовом классе - method() = {}; # Аналог override, т.к. method должен существовать в базовом классе -}; -</code></pre><h3 id="прерывания-возврат-и-обработка-ошибок">Прерывания, возврат и обработка ошибок<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b5%d1%80%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%b2%d0%be%d0%b7%d0%b2%d1%80%d0%b0%d1%82-%d0%b8-%d0%be%d0%b1%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b0-%d0%be%d1%88%d0%b8%d0%b1%d0%be%d0%ba" aria-label="Heading self-link"></a></h3> -<p>Изменена, а точнее полностью переделана идеология возвратов из функций и обработки ошибок. -Теперь она чем-то похожа на подход, примененный в Ruby. Любая последовательность команд заключенные в фигурные скобки (в том числе тело функции), рассматривается как блок кода у которого нет специального оператора аналога <strong>return</strong>, который возвращает какое либо значение. -Просто любой блок кода всегда возвращает последнее вычисленное значение (это чем то похоже на оператор «запятая» в языках C/C++).</p> -<p>Для того, чтобы прервать выполнение кода используются две разные команды - прерывания, которые условно можно назвать <em>положительным</em> и <em>отрицательным</em> результатом. Что примерно соответствует семантике их записи. -&ldquo;Отрицательное&rdquo; прерывание записывается в виде двух минусов, а &ldquo;положительное&rdquo; прерывание в виде двух плюсов, т.е. <strong>--</strong> или <strong>++</strong>.</p> -<p>По умолчанию данные операции возвращают пустое значение. Чтобы прерывание вернуло результат, возвращаемые данные нужно записывать между парой соответствующих символов, -т.е. <strong>--</strong> 100 <strong>--</strong>, что является близким аналогом оператора <code>return 100;</code> в других языках программирования, а <strong>++</strong>«Строка»<strong>++</strong> - аналогом <code>return «Строка»;</code>.</p> -<p>Хотя более точным аналогом этих операторов будет все таки не <strong>return</strong>, а <strong>throw</strong>, -т.к. эти команды не только прерывают выполнение последовательности команд в блоке, но их еще можно «ловить». -Для этого используется блок кода с соответствующей семантикой, <strong>{+</strong> … <strong>+}</strong> - блок кода, -который перехватывает положительные прерывания и <strong>{-</strong> … <strong>-}</strong> - блок кода, который перехватывает прерывания, созданные операторами <strong>&ndash;</strong>.</p> -<p>Подобная концепция (в явном виде не разделять возвраты из функций и обработку исключений), -хоть и выглядит немного необычной, но позволяет реализовывать несколько очень полезных финтов, -которые сложно реализуемые в обычных языках программирования.</p> -<p>Например, возврат из нескольких вложенных функций без необходимости обрабатывать результат возврата каждой из них. -В этом примере функция <em>Test</em> перехватывает &ldquo;положительные&rdquo; прерывания из вложенных функций:</p> -<pre tabindex="0"><code> Test0(arg) := { \if($arg==0) \return(&#34;DONE - 0&#34;); «FAIL» }; - Test1(arg) := { \if($arg==1) \return(&#34;DONE - 1&#34;); Test0($arg); }; - Test(arg) := {+ \if($arg &gt;= 0) Test1($arg); $arg; +}; - - Test(0); # Вернет «DONE — 0» возврат из вложенной функции Test0 - Test(1); # Вернет «DONE — 1» возврат из вложенной функции Test1 - Test(2); # Вернет «FAIL» возврат из вложенной функции Test0 - Test(-2); # Вернет -2 — возврат из функции Test -</code></pre><p>Есть еще блок <code>{* … *}</code>, который перехватывает оба типа прерываний. Такой блок кода поддерживает типизацию возвращаемого значения, что позволяет в явном виде указывать типы данных, которые нужно перехватывать. -Например, <code>{* ... *} :Type1</code> — будет перехвачено прерывание вида <code>++ :Type1 ++</code> или <code>--:Type1--</code>, что позволяет очень гибко формировать логику работы программы.</p> -<p>Блоки кода с перехватом исключений также поддерживают оператор иначе (<em>\else</em>) который, по аналогии с оператором <em>\else</em> в циклах, выполняется только тогда, если прерывания не произошло.</p> -<p>Можно указать сразу несколько типов, которые нужно перехватывать:</p> -<pre tabindex="0"><code> {* - .... - *} &lt;:Type1, :Type2, :Type3&gt;; -</code></pre><h2 id="бинарная-сборка-под-windws">Бинарная сборка под Windws:<a class="td-heading-self-link" href="#%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%b0%d1%8f-%d1%81%d0%b1%d0%be%d1%80%d0%ba%d0%b0-%d0%bf%d0%be%d0%b4-windws" aria-label="Heading self-link"></a></h2> -<p>В текущем релизе версия clang повышена 15, а вызовы нативных функций опять реализованы с помощью libffi, что в итоге позволило собрать бинарную сборку не только под Linux, но и под Windows. И теперь чтобы поиграться с REPL read-eval-print loop можно скачать уже готовый бинарник.</p> -<h2 id="подробная-информация-о-языке">Подробная информация о языке:<a class="td-heading-self-link" href="#%d0%bf%d0%be%d0%b4%d1%80%d0%be%d0%b1%d0%bd%d0%b0%d1%8f-%d0%b8%d0%bd%d1%84%d0%be%d1%80%d0%bc%d0%b0%d1%86%d0%b8%d1%8f-%d0%be-%d1%8f%d0%b7%d1%8b%d0%ba%d0%b5" aria-label="Heading self-link"></a></h2> -<ul> -<li><a href="http://localhost:1313/docs/syntax/">Синтаксис <em>NewLang</em></a></li> -<li><a href="http://localhost:1313/docs/types/">Подробное описание типов данных</a></li> -<li><a href="http://localhost:1313/docs/ops/">Операторы и управляющие конструкции</a></li> -<li><a href="http://localhost:1313/docs/_print/">Вся документация по <em>NewLang</em> на одной странице</a></li> -</ul> -<h2 id="обратная-связь">Обратная связь<a class="td-heading-self-link" href="#%d0%be%d0%b1%d1%80%d0%b0%d1%82%d0%bd%d0%b0%d1%8f-%d1%81%d0%b2%d1%8f%d0%b7%d1%8c" aria-label="Heading self-link"></a></h2> -<p>Если у вас появятся предложения по развитию нового или улучшению уже существующего функционала <em>NewLang</em>, <a href="https://github.com/rsashka/newlang/discussions">пишите</a>.</p> -<h2 id="примеры-кода">Примеры кода<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80%d1%8b-%d0%ba%d0%be%d0%b4%d0%b0" aria-label="Heading self-link"></a></h2> -<pre tabindex="0"><code>#!../output/nlc --eval -# Определение функции hello -hello(str) := { - # Импорт стандартной C функции - printf := :Pointer(&#39;printf(format:FmtChar, ...):Int32&#39;); - # Вызов C функции с проверкой типов аргументов по строке формата - printf(&#39;%s&#39;, $str); - # Возврат значения из функции hello - $str; -}; - -hello(&#39;Привет, мир!&#39;); # Вызвать функцию&lt;/code&gt; -</code></pre><p>Вывод (первая строка выводится с помощью printf, а вторая — возвращаемое значение функции hello):</p> -<pre tabindex="0"><code> Привет, мир! - Привет, мир! -</code></pre><p>Пример скрипта для вычисления факториала 1000</p> -<pre tabindex="0"><code>#!../output/nlc --eval - -fact := 1\1; # Рациональное число без ограничения точности -mult := 1000..1..-1?; # Сделать из диапазона итератор для множителей от 1000 до 2 -[mult ?!] &lt;-&gt; { # Цикл, пока не закончатся данные итератора - # Получить текущий множитель и перейти на следующий элемент итератора - fact *= mult !; -}; -fact # Вывести итоговый результат -</code></pre><p>Вывод:</p> -<spoiler title="Много цифр"> -402387260077093773543702433923003985719374864210714632543799910429938512398629 -020592044208486969404800479988610197196058631666872994808558901323829669944590 -997424504087073759918823627727188732519779505950995276120874975462497043601418 -278094646496291056393887437886487337119181045825783647849977012476632889835955 -735432513185323958463075557409114262417474349347553428646576611667797396668820 -291207379143853719588249808126867838374559731746136085379534524221586593201928 -090878297308431392844403281231558611036976801357304216168747609675871348312025 -478589320767169132448426236131412508780208000261683151027341827977704784635868 -170164365024153691398281264810213092761244896359928705114964975419909342221566 -832572080821333186116811553615836546984046708975602900950537616475847728421889 -679646244945160765353408198901385442487984959953319101723355556602139450399736 -280750137837615307127761926849034352625200015888535147331611702103968175921510 -907788019393178114194545257223865541461062892187960223838971476088506276862967 -146674697562911234082439208160153780889893964518263243671616762179168909779911 -903754031274622289988005195444414282012187361745992642956581746628302955570299 -024324153181617210465832036786906117260158783520751516284225540265170483304226 -143974286933061690897968482590125458327168226458066526769958652682272807075781 -391858178889652208164348344825993266043367660176999612831860788386150279465955 -131156552036093988180612138558600301435694527224206344631797460594682573103790 -084024432438465657245014402821885252470935190620929023136493273497565513958720 -559654228749774011413346962715422845862377387538230483865688976461927383814900 -140767310446640259899490222221765904339901886018566526485061799702356193897017 -860040811889729918311021171229845901641921068884387121855646124960798722908519 -296819372388642614839657382291123125024186649353143970137428531926649875337218 -940694281434118520158014123344828015051399694290153483077644569099073152433278 -288269864602789864321139083506217095002597389863554277196742822248757586765752 -344220207573630569498825087968928162753848863396909959826280956121450994871701 -244516461260379029309120889086942028510640182154399457156805941872748998094254 -742173582401063677404595741785160829230135358081840096996372524230560855903700 -624271243416909004153690105933983835777939410970027753472000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000\1 -</spoiler> -<h2 id="как-посмотреть">Как посмотреть?<a class="td-heading-self-link" href="#%d0%ba%d0%b0%d0%ba-%d0%bf%d0%be%d1%81%d0%bc%d0%be%d1%82%d1%80%d0%b5%d1%82%d1%8c" aria-label="Heading self-link"></a></h2> -<ul> -<li><a href="https://github.com/rsashka/newlang/releases/download/v0.3.0/nlc_win_64.zip">Бинарная сборка и тесты под Windows</a></li> -<li><a href="https://github.com/rsashka/newlang/releases/download/v0.3.0/nlc_lin_64.tar.xz">Бинарная сборка и тесты под Ubuntu</a></li> -<li>Для запуска бинарных сборок потребуются разделяемые библиотеки libLLVM-15 и libtorch (<a href="https://github.com/rsashka/newlang/releases/download/v0.3.0/nlc_dll.zip">архив с библиотеками для Windows</a>), (<a href="https://github.com/rsashka/newlang/releases/download/v0.3.0/nlc_so.tar.xz">архив с библиотеками для Ubuntu</a>).</li> -<li>Так же все можно собрать напрямую из исходников по инструкции в <a href="https://github.com/rsashka/newlang">репозитории</a></li> -</ul> - - - - - - Blog: Релиз языка программрования NewLang 0.2 - http://localhost:1313/blog/release-v0.2/ - Fri, 12 Aug 2022 00:00:00 +0000 - - http://localhost:1313/blog/release-v0.2/ - - - - <p><img alt="КДПВ" src="http://localhost:1313/blog/langs.jpeg"></p> - - -<div class="pageinfo pageinfo-primary"> -<p>Внимание!!!</p> -<p>Данная статья содержит описание синтаксиса NewLnag предыдущей версии.</p> -<p>Актуальную версию синтаксиса языка можно посмотреть <a href="http://localhost:1313/docs/">тут</a>.</p> - -</div> - -<p><em>NewLang</em> - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения.</p> -<p>Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка).</p> -<p><em>NewLang</em> находится в процессе активного развития и это второй публичный релиз в котором добавлены существенные новые возможности и произошли некоторые изменения по сравнению с <a href="https://habr.com/company/timeweb/blog/673176/">предыдущей версией</a>.</p> -<h2 id="особенности-языка">Особенности языка:<a class="td-heading-self-link" href="#%d0%be%d1%81%d0%be%d0%b1%d0%b5%d0%bd%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d1%8f%d0%b7%d1%8b%d0%ba%d0%b0" aria-label="Heading self-link"></a></h2> -<ul> -<li>Возможность работы как в режиме интерпретатора, так и компилятора*.</li> -<li>Динамическая и статическая типизация с возможностью указания типов в явном виде.</li> -<li>Статическая типизация является условно строгой (автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных, например, целое число может быть автоматически преобразовано в вещественное или рациональное, но не наоборот).</li> -<li>Автоматическое управление памятью.</li> -<li>ООП в виде явного наследования классов и «утиная» типизация.</li> -<li>На уровне синтаксиса поддержка нескольких типов функций (обычные и чистые функции без побочных эффектов).</li> -<li>Необязательные и именованные параметры функций.</li> -<li>Возможны вставки кода на языке реализации (С/С++)*.</li> -<li>Простая интеграция с уже существующими программными библиотеками (в том числе импорт нативных переменных и функций из С/С++).</li> -<li>Имеется REPL read-eval-print loop — «цикл: чтение — вычисление — вывод».</li> -</ul> -<h2 id="новые-глобальные-фичи">Новые глобальные фичи:<a class="td-heading-self-link" href="#%d0%bd%d0%be%d0%b2%d1%8b%d0%b5-%d0%b3%d0%bb%d0%be%d0%b1%d0%b0%d0%bb%d1%8c%d0%bd%d1%8b%d0%b5-%d1%84%d0%b8%d1%87%d0%b8" aria-label="Heading self-link"></a></h2> -<ul> -<li>Добавлены макросы. Теперь можно делать собственные языковые диалекты и использовать более привычную запись алгоритмических конструкций с использование ключевых слов. -Например, цикл</li> -</ul> -<pre tabindex="0"><code>[ cond ] &lt;-&gt; { - тело цикла -}; -</code></pre><p>можно записать в более привычный нотации</p> -<pre tabindex="0"><code>\while (cond) { - тело цикла -}; -</code></pre><ul> -<li>Добавлены итераторы для перебора элементов словарей или для запросов к другим контейнерам (например, к базам данных). На уровне базового синтаксиса поддерживается фильтрация данный, включая функциональный аналог LINQ за счет применения функций обратного вызова в качестве условия фильтра.</li> -<li>Добавлен новый тип данных — рациональные числа с неограниченной точностью. Они записываются в виде обыкновенной дроби, у которой разделитель бекслеш, например единицу можно записать <code>1\1</code>, а число 0.5 как <code>1\2</code>.</li> -<li>Реализован оператор распаковки словаря <strong>…</strong> (многоточие), который можно использовать чтобы передать несколько аргументов при вызове функции или для присвоения значения сразу нескольким переменным.</li> -<li>Теперь оператор присвоения поддерживает установку значений сразу нескольким переменным. С правой стороны от оператора присвоения может находится одно или несколько значений или оператор распаковки словаря. Причем словарь может быть указан и с левой стороны от оператора присвоения и таким образом можно записать самый простой способ перебора всех его элементов, когда в цикле первый элемент словаря сохраняется в переменную <em>item</em>, а из самого словаря удаляется:</li> -</ul> -<pre tabindex="0"><code>[ dict ] &lt;-&gt; { - item, dict := ... dict; -}; -</code></pre><h2 id="изменения-в-синтаксисе">Изменения в синтаксисе:<a class="td-heading-self-link" href="#%d0%b8%d0%b7%d0%bc%d0%b5%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b2-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81%d0%b5" aria-label="Heading self-link"></a></h2> -<ul> -<li>Изменена запись циклов. Вместо двух разных типов с предусловием и постусловие, теперь используется единая форма записи, а тип цикла определяется взаимным расположением условия и его тела.</li> -<li>Изменены названия арифметических и некоторых других типов данных на более логичные. В именах арифметических типов теперь указан их размер (Int8, Int16 … Float32, Float64 и т.д.).</li> -<li>Многострочные комментарии стали вложенными</li> -</ul> -<h2 id="подробная-информация-о-языке">Подробная информация о языке:<a class="td-heading-self-link" href="#%d0%bf%d0%be%d0%b4%d1%80%d0%be%d0%b1%d0%bd%d0%b0%d1%8f-%d0%b8%d0%bd%d1%84%d0%be%d1%80%d0%bc%d0%b0%d1%86%d0%b8%d1%8f-%d0%be-%d1%8f%d0%b7%d1%8b%d0%ba%d0%b5" aria-label="Heading self-link"></a></h2> -<ul> -<li><a href="http://localhost:1313/docs/syntax/">Основные правила синтаксиса:</a></li> -<li><a href="http://localhost:1313/docs/types/">Встроенные типы данных:</a></li> -<li><a href="http://localhost:1313/docs/ops/">Операторы и управляющие конструкции:</a></li> -</ul> -<h2 id="примеры-кода">Примеры кода<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80%d1%8b-%d0%ba%d0%be%d0%b4%d0%b0" aria-label="Heading self-link"></a></h2> -<spoiler title="Привет, мир!"> -``` -#!../output/nlc --eval -<h1 id="определение-функции-hello">Определение функции hello<a class="td-heading-self-link" href="#%d0%be%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-hello" aria-label="Heading self-link"></a></h1> -<p>hello(str) := {</p> -<pre><code># Импорт стандартной C функции -printf := :Pointer('printf(format:FmtChar, ...):Int32'); - -# Вызов C функции с проверкой типов аргументов по строке формата -printf('%s', $str); - -# Возврат значения из функции hello - $str; -</code></pre> -<p>};</p> -<p>hello(&lsquo;Привет, мир!&rsquo;); # Вызвать функцию</p> -<pre tabindex="0"><code>Вывод (первая строка выводится с помощью printf, а вторая - возвращаемое значение функции hello): -</code></pre><pre><code>Привет, мир! -Привет, мир! -</code></pre> -<pre tabindex="0"><code class="language-</spoiler>" data-lang="</spoiler>"> -&lt;spoiler title=&#34;Пример скрипта для вычисления факториала 1000&#34;&gt; -</code></pre><p>#!../output/nlc &ndash;eval</p> -<p>@fact := 1\1; # Рациональное число без ограничения точности -@mult := 1000..1..-1?; # Сделать из диапазона итератор для множителей от 1000 до 2 -[mult ?!] &lt;-&gt; { # Цикл, пока не закончатся данные итератора -# Получить текущий множитель и перейти на следующий элемент итератора -fact *= mult !; -}; -fact # Вывести итоговый результат</p> -<pre tabindex="0"><code>Вывод: -</code></pre><p>402387260077093773543702433923003985719374864210714632543799910429938512398629 -020592044208486969404800479988610197196058631666872994808558901323829669944590 -997424504087073759918823627727188732519779505950995276120874975462497043601418 -278094646496291056393887437886487337119181045825783647849977012476632889835955 -735432513185323958463075557409114262417474349347553428646576611667797396668820 -291207379143853719588249808126867838374559731746136085379534524221586593201928 -090878297308431392844403281231558611036976801357304216168747609675871348312025 -478589320767169132448426236131412508780208000261683151027341827977704784635868 -170164365024153691398281264810213092761244896359928705114964975419909342221566 -832572080821333186116811553615836546984046708975602900950537616475847728421889 -679646244945160765353408198901385442487984959953319101723355556602139450399736 -280750137837615307127761926849034352625200015888535147331611702103968175921510 -907788019393178114194545257223865541461062892187960223838971476088506276862967 -146674697562911234082439208160153780889893964518263243671616762179168909779911 -903754031274622289988005195444414282012187361745992642956581746628302955570299 -024324153181617210465832036786906117260158783520751516284225540265170483304226 -143974286933061690897968482590125458327168226458066526769958652682272807075781 -391858178889652208164348344825993266043367660176999612831860788386150279465955 -131156552036093988180612138558600301435694527224206344631797460594682573103790 -084024432438465657245014402821885252470935190620929023136493273497565513958720 -559654228749774011413346962715422845862377387538230483865688976461927383814900 -140767310446640259899490222221765904339901886018566526485061799702356193897017 -860040811889729918311021171229845901641921068884387121855646124960798722908519 -296819372388642614839657382291123125024186649353143970137428531926649875337218 -940694281434118520158014123344828015051399694290153483077644569099073152433278 -288269864602789864321139083506217095002597389863554277196742822248757586765752 -344220207573630569498825087968928162753848863396909959826280956121450994871701 -244516461260379029309120889086942028510640182154399457156805941872748998094254 -742173582401063677404595741785160829230135358081840096996372524230560855903700 -624271243416909004153690105933983835777939410970027753472000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000\1</p> -<pre tabindex="0"><code class="language-</spoiler>" data-lang="</spoiler>"> -## Как посмотреть? -- [Загрузить собранный REPL и тесты (пока только под Ubuntu)](https://github.com/rsashka/newlang/releases/download/v0.2.0/nlc_bin.tar.xz) -- Для запуска бинарных файлов потребуются разделяемые библиотеки libLLVM-13 и libtorch: [архив только с нужными библиотеками](https://github.com/rsashka/newlang/releases/download/v0.2.0/nlc_so.tar.xz). -- Так же все можно собрать напрямую из исходников по инструкции в [репозитории](https://github.com/rsashka/newlang) -</code></pre> - - - - - Blog: Релиз языка программрования NewLang - http://localhost:1313/blog/release-v0.1/ - Fri, 24 Jun 2022 00:00:00 +0000 - - http://localhost:1313/blog/release-v0.1/ - - - - <p><img alt="КДПВ" src="http://localhost:1313/blog/langs.jpeg"></p> - - -<div class="pageinfo pageinfo-primary"> -<p>Внимание!!!</p> -<p>Данная статья содержит описание синтаксиса NewLnag предыдущей версии.</p> -<p>Актуальную версию синтаксиса языка можно посмотреть <a href="http://localhost:1313/docs/">тут</a>.</p> - -</div> - -<p><strong>NewLang</strong> - это язык программирования высокого уровня, в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения.</p> -<p>Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка).</p> -<p>Новое по сравнению с <a href="https://habr.com/company/timeweb/blog/651999/">прошлым выпуском</a>:</p> -<ul> -<li>Реализованы все основные алгоритмические конструкции: проверка условий, различные варианты циклов, сравнение по образцу, прерывание последовательности команд и возврат данных, обработка ошибок и т.д.</li> -<li>Переработан основной синтаксис для отдельных языковых конструкций.</li> -<li>Реализованы большинство операций с переменными, включая операторы раскрытие списков и тензоров.</li> -<li>Серьезно переработана система встроенных типов, реализованы функции для их преобразования и для определения данных (последнее можно назвать data comprehensions).</li> -<li>Добавлены новые тесты и пр.</li> -</ul> -<cut /> -<h1 id="зачем-нужен-newlang">Зачем нужен <em>NewLang</em>?<a class="td-heading-self-link" href="#%d0%b7%d0%b0%d1%87%d0%b5%d0%bc-%d0%bd%d1%83%d0%b6%d0%b5%d0%bd-newlang" aria-label="Heading self-link"></a></h1> -<p>У всех современных языков программирования происходит постоянное развитие (читай усложнение) синтаксиса по мере выхода новых версий. Это является своего рода, платой за появление новых возможностей и воспринимается пользователями как естественное явление.</p> -<p>Но одновременно является и серьезной проблемой, т.к. с выходом новых версий добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки и трудоемкости поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.</p> -<p>У <em>NewLang</em> сложность языковых конструкций естественно ограничена за счет разделения синтаксиса языка на две части, что упрощает его изучение и использование.</p> -<p><em>Основной синтаксис</em> — для написания программ в объектно-ориентированном (императивном) и декларативном стилях, который основан не на зарезервированных ключевых словах, а на строгих грамматических правилах и <em>Расширенный синтаксис</em> — когда основного синтаксиса становится недостаточно, или требуется использовать языковую конструкцию языка реализации.</p> -<p>Еще одно неудобство современных мейнстримовых языков, большинство из них были созданы до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек, а не встроены в основной синтаксис языка и систему базовых типов.</p> -<p>У <em>NewLang</em> тензорные вычисления доступны «из коробки» (используется библиотека <a href="https://pytorch.org/">libtorch</a>), а обычные числа являются скалярами (тензорами нулевой размерности).</p> -<h1 id="синтаксис-newlang">Синтаксис NewLang<a class="td-heading-self-link" href="#%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81-newlang" aria-label="Heading self-link"></a></h1> -<p>При разработке синтаксиса я старался придерживаться уже сложившихся в IT индустрии правил, чтобы не генерировать множественных смыслов, которые будут зависеть от контекста.</p> -<p><strong>Основы</strong></p> -<ul> -<li>Операторы разделяются точкой с запятой «;».</li> -<li>Отступы и переводы строк игнорируются (очень хотелось иметь возможность автоматического форматирование кода).</li> -<li>Многострочные комментарии в исходном коде соответствуют стилю С/С++ и должны располагаться между символами /* и */. Вложенность многострочных комментариев не поддерживается.</li> -<li>Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash.</li> -<li>Последовательность команд, которая должна выполняться как единое целое, заключается в фигурные скобки «{}».</li> -<li>Программные вставки расширенного синтаксиса на языке реализации заключается в фигурные скобки со знаком процента %{ /* тут может быть любой код на C/C++*/ %}, как в лексерах lex и flex.</li> -</ul> -<h1 id="создания-объектов-и-присвоения-новых-значений">Создания объектов и присвоения новых значений<a class="td-heading-self-link" href="#%d1%81%d0%be%d0%b7%d0%b4%d0%b0%d0%bd%d0%b8%d1%8f-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%be%d0%b2-%d0%b8-%d0%bf%d1%80%d0%b8%d1%81%d0%b2%d0%be%d0%b5%d0%bd%d0%b8%d1%8f-%d0%bd%d0%be%d0%b2%d1%8b%d1%85-%d0%b7%d0%bd%d0%b0%d1%87%d0%b5%d0%bd%d0%b8%d0%b9" aria-label="Heading self-link"></a></h1> -<p>Для создания объектов и присвоения им новых значений в NewLang используется сразу три разных оператора:</p> -<ul> -<li><strong>::=</strong> используется только для создания новых объектов, а если объект с таким именем уже существует, то генерируется ошибка.</li> -<li><strong>:=</strong> используется для тех же целей, но если объект с таким именем уже существует, то ошибки не происходит, а новое значение присваивается уже существующему объекту.</li> -<li><strong>=</strong> применяется только для присвоения значения уже существующим объектам, и если объект с указанным именем отсутствует, то тоже происходит ошибка выполнения.</li> -</ul> -<p>Использование трех разных операторов для создания/изменения объектов позволяет более гибко контролировать подобные операции и выявлять логические ошибки в коде на более раннем этапе.</p> -<pre tabindex="0"><code>var ::= 1.0; # Создать новую переменную var без указания типа -var = 100; # Присвоить новое значение уже существующей переменной -printf := @import(&#39;printf(format:Format, ...):Int&#39;); /* Создать новый или переопределить объект printf, который будет результатом выполнения глобальной функции @import */ -</code></pre><h1 id="идентификаторы-объектов-и-модификаторы">Идентификаторы объектов и модификаторы<a class="td-heading-self-link" href="#%d0%b8%d0%b4%d0%b5%d0%bd%d1%82%d0%b8%d1%84%d0%b8%d0%ba%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%be%d0%b2-%d0%b8-%d0%bc%d0%be%d0%b4%d0%b8%d1%84%d0%b8%d0%ba%d0%b0%d1%82%d0%be%d1%80%d1%8b" aria-label="Heading self-link"></a></h1> -<p>В качестве идентификаторов можно использовать буквы, цифры и знаки подчеркивания в любых комбинациях, при условии, что первый символ идентификатора не является цифрой.</p> -<p>В NewLang существует возможность указания области видимости и времени жизни объекта с помощью модификатора — специального символа перед именем переменной. Это может показаться немного похожим на венгерскую нотацию, но в отличие от нее, модификатор не имеет отношения к типу объекта и не является частью имени идентификатора. К тому же в качестве модификаторов используется строго определённые символы, назначение которых определено заранее.</p> -<ul> -<li><strong>$</strong> - в начале имени обозначает локальную переменную, время жизни которой ограничено текущей областью видимости и при её завершении локальная переменная уничтожается.</li> -<li><strong>@</strong> - обозначает глобальную переменную, а сам объект сохраняет свое состояние даже после выхода из текущей области видимости.</li> -<li><strong>:</strong> - двоеточие вначале имени используется в качестве модификатора для указания типа.</li> -</ul> -<p>Семантика обращения к аргументам функций очень похоже на работу с аргументами в bash скриптах, где $1 или $arg — порядковый номер или имя аргумента (происходит обращение к локальным переменным в текущей области видимости).</p> -<h3 id="использование-модификаторов-является-обязательным-только-в-двух-случаях">Использование модификаторов является обязательным только в двух случаях:<a class="td-heading-self-link" href="#%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%bc%d0%be%d0%b4%d0%b8%d1%84%d0%b8%d0%ba%d0%b0%d1%82%d0%be%d1%80%d0%be%d0%b2-%d1%8f%d0%b2%d0%bb%d1%8f%d0%b5%d1%82%d1%81%d1%8f-%d0%be%d0%b1%d1%8f%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d1%8b%d0%bc-%d1%82%d0%be%d0%bb%d1%8c%d0%ba%d0%be-%d0%b2-%d0%b4%d0%b2%d1%83%d1%85-%d1%81%d0%bb%d1%83%d1%87%d0%b0%d1%8f%d1%85" aria-label="Heading self-link"></a></h3> -<ul> -<li>При создании нового типа данных, так как типы всегда создаются в глобальной области видимости, а их символьные имена должны быть уникальными.</li> -<li>При обращении к объектам NewLang внутри программных вставок кода на языке реализации, так как они используется как маркеры при поиске идентификаторов NewLang в коде С/С++.</li> -</ul> -<p>В остальных случаях, для обращения к переменным указывать их модификаторы необязательно. И если при обращении к объекту модификатор не указан, то сперва ищется локальная переменная, а потом глобальная с таким же именем. Причем, локальная переменная будет перекрывать глобальную.</p> -<p>Так же следует иметь в виду, что компилятор может генерировать код для прямого обращения к локальным объектам уже на этапе компиляции, тогда как для обращения к глобальным объектам, или если модификатор области видимости отсутствует, компилятор вынужден каждый раз встраивать runtime вызов функции поиска объекта в глобальной таблице символов.</p> -<h1 id="система-типов">Система типов<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0-%d1%82%d0%b8%d0%bf%d0%be%d0%b2" aria-label="Heading self-link"></a></h1> -<p>Так как система типов языка динамическая, то явное указание типа не влияет на размер переменной и является только своего рода логическим ограничением на возможность присвоения переменной значения другого типа.</p> -<p>Информация о типах используется при проверке их совместимости, когда существующему объекту присваивается значение другого типа. Такая операция возможна только когда типы совместимы между собой и допускают автоматическое приведение. Это справедливо как во время парсинга/компиляции исходного теста, так и во время выполнения в режимах интерпретатора и/или скомпилированного файла.</p> -<h2 id="простые-типы">Простые типы<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%be%d1%81%d1%82%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b" aria-label="Heading self-link"></a></h2> -<h3 id="арифметические-значения">Арифметические значения<a class="td-heading-self-link" href="#%d0%b0%d1%80%d0%b8%d1%84%d0%bc%d0%b5%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5-%d0%b7%d0%bd%d0%b0%d1%87%d0%b5%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h3> -<p>Арифметические типы данных являются тензорами — массивами чисел одного типа с произвольным количеством измерений и одинаковым размером столбцов в каждом. Единичное число тоже тензор нулевого размера.</p> -<p>Поддерживаются только знаковые целые числа, т.к. в беззнаковых числах особая нужда отсутствует, а проблем с ними можно найти очень много на ровном месте.</p> -<p>Проблемы беззнаковых чисел (из интернета):</p> -<blockquote> -<p>Во-первых, вычитание двух беззнаковых чисел, например 3 и 5. 3 минус 5 равно 4294967294, т.к. -2 не может быть представлено как беззнаковое число. Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных значений со знаком и без знака. С++ может свободно преобразовывать числа со знаком и без знака, но не проверяет диапазон, чтобы убедиться, что вы не переполняете свой тип данных. -В C++ всё же есть несколько случаев, когда можно (или необходимо) использовать беззнаковые числа. Во-первых, числа без знака предпочтительнее при работе с битами. Во-вторых, использование беззнаковых чисел связанных с индексацией массивов.</p> -</blockquote> -<p>Но это не мой случай, так как индекс может быть отрицательным и даже не числом, а диапазоном или многоточием.</p> -<p>З.Ы. И даже зная об этом, все равно умудрился недавно словить баг с отрицательными индексами у словарей!</p> -<p>Имена встроенных арифметических типов говорят сами за себя: Char, Short, Int, Long, Float, Double, ComplexFloat, ComplexDouble. Отдельным типом идет логический тип Bool, который может принимать значения только 0 или 1 (false/true соответственно), и в зависимости от выполняемой операции может быть отнесен к целочисленным типам, так и не входить в их состав (данный подход интерпретации логического типа данных был взят из библиотеки Torch).</p> -<pre tabindex="0"><code>// Treat bool as a distinct &#34;category,&#34; to be consistent with type promotion -// rules (e.g. `bool_tensor + 5 -&gt; int64_tensor`). If `5` was in the same -// category as `bool_tensor`, we would not promote. Differing categories -// implies `bool_tensor += 5` is disallowed. -// -// NB: numpy distinguishes &#34;unsigned&#34; as a category to get the desired -// `bool_tensor + 5 -&gt; int64_tensor` behavior. We don&#39;t, because: -// * We don&#39;t want the performance hit of checking the runtime sign of Scalars. -// * `uint8_tensor + 5 -&gt; int64_tensor` would be undesirable. -</code></pre><p>В будущем планируется добавить классы чисел для длинной арифметики и дробей, для чего зарезервированы названия типов BigNum, Currency и Fraction.</p> -<p>Доступ к элементам тензора происходит по целочисленному индексу, который начинается с 0. Для многомерного тензора, индексы элемента перечисляются в квадратных скобках через запятую. Поддерживается доступ к элементам через отрицательный индекс, который обрабатывается точно так же, как в Python (-1 последний элемент, -2 предпоследний и т.д.).</p> -<p>Литерал тензор в тексте программы записывается в квадратных скобках с обязательной завершающей запятой, т.е. [1, 2,] — это литерал одномерный тензор из двух чисел. После закрывающей скобки тип тензора может быть указан в явном виде. Если тип не указан, то он выводится автоматически на основании указанных данных и выбирается минимально возможный байтовый размер, который позволяет сохранить все значения без потери точности.</p> -<p><em>Примеры:</em></p> -<pre tabindex="0"><code>$var_char := 123; # Тип Char выводится автоматически -$var_short := 1000; # Тип Short выводится автоматически -$var_bool := [0, 1, 0, 1,]; # Тензор из 4 элементов. Тип Bool выводится автоматически -$tensor[10,10]:Int := 1; # Тензор Int размером 2x2 инициализированный 1 -$scalar := $tensor[5,5]; # Присвоить скаляру значение указанного элемента тензора -</code></pre><h2 id="строки">Строки<a class="td-heading-self-link" href="#%d1%81%d1%82%d1%80%d0%be%d0%ba%d0%b8" aria-label="Heading self-link"></a></h2> -<p>Поддерживаются два типа строк, StrWide — символьные (широкие) и StrChar — байтовые. Различия между ними заключается в типе единичного элемента. У символьных строк единичным элементом является широкий символ <em>wchar_t</em>, а у байтовой строки единичным элементом является один байт (точнее <em>char</em>, т.е. байт со знаком). Символьные строки литералы в исходном тексте записывается в «двойных кавычках», а байтовые строки в &lsquo;одинарных кавычках&rsquo;.</p> -<p>Количество элементов символьной строки возвращается в широких символах, а размер байтовой строки в байтах, поэтому и обращение к элементу строки по индексу происходит соответственно либо к символу, либо к байту.</p> -<p>Важный момент. К любой переменной можно обратиться так же, как к функции (записав после её имени круглые скобки). Результатом этой операции будет создание копии/клона объекта. Причем некоторые типы (словари, классы и символьные строки) можно использовать в качестве шаблона при создании копии объекта с модифицированными свойствами, если новые и/или изменяемые значения указать в скобках, как аргументы при вызовах функций. Так, если при создании копии в скобках указать набор новых данных, то результирующая копия будет содержать уже измененные данные.</p> -<p><em>Например:</em></p> -<pre tabindex="0"><code>$template := &#34;${name} $1&#34;; # Обычная строка -$result := $template(&#34;шаблон&#34;, name = &#34;Строка&#34;); # result = &#34;Строка шаблон&#34; -</code></pre><h2 id="системные">Системные<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%8b%d0%b5" aria-label="Heading self-link"></a></h2> -<h3 id="pointer---указатель-на-системную-область-памяти">:Pointer - указатель на системную область памяти<a class="td-heading-self-link" href="#pointer---%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%83%d1%8e-%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8" aria-label="Heading self-link"></a></h3> -<p>Так как любой программе приходится взаимодействовать с внешним миром, то по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип <em>Pointer</em>. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. Но можно вывести его значение, например для отладки.</p> -<h3 id="plain---указатель-на-представление-данных-в-бинарном-виде">:Plain - указатель на представление данных в бинарном виде<a class="td-heading-self-link" href="#plain---%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d0%bf%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%be%d0%bc-%d0%b2%d0%b8%d0%b4%d0%b5" aria-label="Heading self-link"></a></h3> -<p>Для взаимодействия с внешними библиотеками требуется еще и обмен данными. И для этих целей служит тип данных <em>Plain</em> - который также является указателем, но на двоичное представление данных в единой области памяти. Конечно, если их можно представить в виде единого фрагмента.</p> -<h2 id="составные-типы-данных">Составные типы данных:<a class="td-heading-self-link" href="#%d1%81%d0%be%d1%81%d1%82%d0%b0%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85" aria-label="Heading self-link"></a></h2> -<h3 id="словарь">Словарь<a class="td-heading-self-link" href="#%d1%81%d0%bb%d0%be%d0%b2%d0%b0%d1%80%d1%8c" aria-label="Heading self-link"></a></h3> -<p>Словарь (:Dictionary) — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии (он похож и на tuple и на структуру одновременно). Словари от тензоров отличаются тем, что являются только одномерными массивами, но каждый элемент может содержать произвольное количество элементов любого типа, в том числе и другие словари.</p> -<p>Доступ к элементам словарей происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. Индекс также начинается с 0 и как у тензоров и тоже может быть отрицательным.</p> -<p>Литерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, т. е. (,) — пустой словарь, (1, 2= «2», name=3,).</p> -<h3 id="перечисление-структура-и-объединение">Перечисление, структура и объединение<a class="td-heading-self-link" href="#%d0%bf%d0%b5%d1%80%d0%b5%d1%87%d0%b8%d1%81%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d0%b8-%d0%be%d0%b1%d1%8a%d0%b5%d0%b4%d0%b8%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> -<p><em>:Enum</em>, <em>:Struct</em> и <em>:Union</em> — это такие же словари, только на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера.</p> -<h3 id="классы">Классы<a class="td-heading-self-link" href="#%d0%ba%d0%bb%d0%b0%d1%81%d1%81%d1%8b" aria-label="Heading self-link"></a></h3> -<p>Класс (реализован частично) — тип данных, с помощью которого реализуется один из принципов ООП — наследование. При создании экземпляра класса создается новая переменная, у которой сохраняется информацию о своем родителе и которая наследует от него свойства и методы. Тип данных <em>:Class</em> аналогичен словарю, но все свойства обязаны иметь имена (хотя доступ к свойствам класса по индексу так же возможен).</p> -<h2 id="функции">Функции<a class="td-heading-self-link" href="#%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h2> -<p>Синтаксис NewLang поддерживать несколько типов функций (а в будущем и методов классов): обычные функции, чистые функции и простые чистые функции.</p> -<p>Для всех типов функций поддерживаются аргументы по умолчанию. При создании функции, её аргументы указываются как в Python, т.е. вначале идут обязательные аргументы, потом аргументы со значениями по умолчанию, где имя аргумента отделяется от его значения по умолчанию знаком равно <strong>=</strong>. Если функция допускает обработку произвольного количества аргументов, то последним в списке параметров указывается многоточие <strong>&hellip;</strong> (три точки подряд) .</p> -<h3 id="обычная-функция">Обычная функция<a class="td-heading-self-link" href="#%d0%be%d0%b1%d1%8b%d1%87%d0%bd%d0%b0%d1%8f-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8f" aria-label="Heading self-link"></a></h3> -<p>Обычная функция — такие функции являются именно обычными функциями в понимании С/С++. Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д.</p> -<p>Внутри обычной функции можно обращаться к локальным и глобальным объектам, и они могут содержаться вставки на языке реализации*, например, для вызова функций из внешних библиотек.</p> -<p>Вставки на языке реализации оформляются в виде %{ %} и могут содержать любой текст на С/С++, а прямо из него можно обращаться к локальным и глобальным объектам NewLang так же, как и в обычном синтаксисе, указывая первым символом имени соответствующий модификатор (<em>$</em> для локальных объектов и <em>@</em> для глобальных).</p> -<p>Технически, такая программная вставка просто переносится трансплайтером непосредственно в исходный текст генерируемого файла, а все идентификаторы NewLang специальным образом декорируются (добавляются специальные маркеры для их идентификации), после этого исходный текст подается на вход обычному компилятору С++. Для локальных объектов трансплайтер может генерировать код для прямого доступа к объекту на этапе компиляции, а для работы с глобальными объектами вынужден использовать runtime вызовы функции поиска в таблице символов.</p> -<hr> -<p>*) - Программные вставки на языке реализации обрабатываются только во время компиляции</p> -<p><em>Например:</em></p> -<pre tabindex="0"><code>print(str) := { - %{ - printf(&#34;%s&#34;, static_cast&lt;const char *&gt;($str)); /* Прямой вызов С функции */ - %} -}; -</code></pre><h3 id="чистые-функции">Чистые функции<a class="td-heading-self-link" href="#%d1%87%d0%b8%d1%81%d1%82%d1%8b%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h3> -<p>Чистая функция — это тоже обычная функция, только в том смысле, какой в него вкладывает функциональное программирование. Создания чистой функции происходит с помощью оператора <strong>:-</strong>, а сам оператор заимствован из языка Пролог. У чистой функции отсутствует доступ к контексту и глобальным переменным, поэтому она может обрабатывать только те данные, которые были ей переданы в качестве аргументов.</p> -<p>Программные вставки на языке реализации внутри чистых функций не запрещены и могут использоваться, например, для отладки. Но делается это на страх и риск разработчика. Именно он отвечает за их «чистоту», например при вызове функций из внешних библиотек.</p> -<pre tabindex="0"><code>Sum(arg1, arg2) :- {$arg1+$arg2;}; # Вернуть сумму аргументов -</code></pre><h3 id="простые-чистые-функции">Простые чистые функции<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%be%d1%81%d1%82%d1%8b%d0%b5-%d1%87%d0%b8%d1%81%d1%82%d1%8b%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h3> -<p>Простые чистые функции — отдельный класс чистых функций, которые предназначены только для вычисления логического результата (т.е. они являются предикатами) и их отличает упрощенная формой записи. Тело простой чистой функции состоит из последовательности операторов, которые разделяются запятыми и заканчиваются, как и любое выражение, точкой с запятой. Все операторы простой чистой функции всегда приводятся к булевому значению, а итоговый результат функции вычисляется по одной из возможных логических операций: И, ИЛИ и исключающее ИЛИ.</p> -<p><em>Например:</em></p> -<pre tabindex="0"><code>func_and(arg1, arg2) :&amp;&amp;= arg1==3, arg2 &gt; 0; # Простая чистая функция Логическое И -func_or(arg1, arg2) :||= arg1==3, arg2 &gt; 0; # Простая чистая функция Логическое ИЛИ -func_xor(arg1, arg2) :^^= arg1==3, arg2 &gt; 0; # Простая чистая функция Исключающее ИЛИ -</code></pre><h2 id="специальные-типы-данных">Специальные типы данных:<a class="td-heading-self-link" href="#%d1%81%d0%bf%d0%b5%d1%86%d0%b8%d0%b0%d0%bb%d1%8c%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85" aria-label="Heading self-link"></a></h2> -<h3 id="пусто-none">Пусто (:None)<a class="td-heading-self-link" href="#%d0%bf%d1%83%d1%81%d1%82%d0%be-none" aria-label="Heading self-link"></a></h3> -<p><strong>:None</strong> (пусто) — не содержит значения (точнее имеет одно значение None) и совместим с любым другим типом данных. Указывается в тексте программы как один подчерк «_». None имеют не инициализированные переменные и при попытке чтения из такой переменной возникает ошибка.</p> -<p>Тип переменной может быть явно указан или выведен автоматически из присваиваемого значения. Присвоить новое значение уже инициализированной переменной можно только для совместимого типа, так как неявное преобразование типов не допускаются.</p> -<pre tabindex="0"><code>$var := _; # Создать не инициализированную переменную -$var2 := var; # Ошибка!!! Нельзя прочитать неинициализированную переменную var -$var = 1000; # У переменной будет тип Short (минимальный размер для хранения значения) -$var = 0,5; # Ошибка!!! Short ← Float не совместимы -$var = _; # Очистить значение переменной -$var = 0,5; # Теперь можно, т. к. None совместим с любым типом -</code></pre><h3 id="диапазон-range">Диапазон (:Range)<a class="td-heading-self-link" href="#%d0%b4%d0%b8%d0%b0%d0%bf%d0%b0%d0%b7%d0%be%d0%bd-range" aria-label="Heading self-link"></a></h3> -<p>Диапазон — специальный тип данных, являющейся приблизительным аналогом типа «генератор» в Python. К диапазону можно обращаться как к итератору и он будет поочередно выдавать элементы в указанном интервале с заданным шагом. Диапазон в тексте программы указывается как два или три элемента через две точки, например 1..5 — диапазон от единицы до пяти с шагом по умолчанию 1. В качестве параметров диапазона можно указывать не только литералы, но и имена переменных. Например, <em>0,1..$stop..0,1</em> — диапазон от 0,1 до значения, указанного в переменной $stop с шагом 0,1.</p> -<p>Диапазон для целых чисел можно использовать в качестве индекса у тензоров (точнее, у любых объектов, которые допускают доступ к своим элементам по индексу, т.е. тензоры, словари и текстовые строки). Фактический, это поведение аналогично <em>slice</em> в языке Python и <em>array[1:5]</em> в Python означает тоже самое, что и <em>array[1..5]</em> в NewLang.</p> -<p>В качестве индекса у тензоров еще можно указать произвольное количество измерений с помощью многоточия, т.е.</p> -<pre tabindex="0"><code>$tensor[…, 0] = 0; # Обнулить все первые элементы в каждом измерении. -</code></pre><h2 id="преобразование-типов">Преобразование типов<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b5%d0%be%d0%b1%d1%80%d0%b0%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d1%82%d0%b8%d0%bf%d0%be%d0%b2" aria-label="Heading self-link"></a></h2> -<h3 id="явное-приведение-типов">Явное приведение типов<a class="td-heading-self-link" href="#%d1%8f%d0%b2%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%b8%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5-%d1%82%d0%b8%d0%bf%d0%be%d0%b2" aria-label="Heading self-link"></a></h3> -<p>Несмотря на динамическую типизацию языка, если тип переменной указан явно, то автоматическое приведение типов не выполняется, и чтобы присвоить переменой значение не совместимого типа, требуется явное преобразование.</p> -<p>Так как символьные названия типов относятся к деталям реализации, то явное преобразование в конкретный тип данных производится с помощью вызова функции с именем типа, т.е. :Bool(), :StrWide(), :Long() и т.д.</p> -<p>Для преобразования любого типа данных в строку ещё можно использовать оператор конкатенации строк, которой преобразует любой тип данных в строковое представление. Но, так как строковых типов два (байтовые и широкие строки), то тип строки определяется первым аргументом в операторе конкатенации/сцепления <strong>++</strong>. Также преобразовать любое значение в строковое можно с помощью строки-шаблона.</p> -<pre tabindex="0"><code>&#34;&#34; ++ 123; # &#34;123&#34; - Строка широких символов -&#39;&#39; ++ 123; # &#39;123&#39; - Байтовая строка - -val := 12345; # Число -&#34;$1&#34;(val); # Будет строка &#34;12345&#34; -</code></pre><p>Так как тензоры могут иметь больше одного значения, то и в качестве аргументов могут принимать их произвольное количество, а итоговым результатом будет тензор, в котором все переданные данные преобразованы к требуемому типу автоматически.</p> -<p><em>Примеры:</em></p> -<pre tabindex="0"><code>&gt; tstr := :Tensor(&#34;Тест&#34;); # Создать тензор из строки широких символов -[1058, 1077, 1089, 1090,]:Int - -&gt; t2 := :Tensor[2,2](&#34;Тест&#34;); # Тоже самое, но тензор указанной размерности -[ - [1058, 1077,], [1089, 1090,], -]:Int - -&gt; :StrWide(tstr) # Создать символьную строку из тензора -Тест - -&gt; :Double(t2) # Изменить тип данных тезора без изменения размерности -[ - [1058, 1077,], [1089, 1090,], -]:Double - -&gt; t3 := :Char[4]( t2 ) # Изменить размерность тензора и его тип (в данном случае с частичной потерей данных) -[34, 53, 65, 66,]:Char - - -&gt;:Tensor( (1,2,3,) ); # Тензор из словаря -[1, 2, 3,]:Char - -&gt;:Tensor( &#39;first second&#39; ) # Байтовая строка в тензор -[102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char - -&gt;:Tensor( (first=&#39;first&#39;, space=32, second=&#39;second&#39;,) ) # Получаем тензор из словаря с такими же данными -[102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char - -&gt;:Double[10,2]( 0, ...) # Тензор заданного формата с нулями, где многоточие повторяет последние указанные данные до получения тензора требуемого размера -[ - [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], -]:Double - -&gt;:Int[3,2]( ... rand() ...) # Тензор со случайными данными, где между многоточиями указана функция, которую следует вызывать каждый раз при получении нового элемента тензора -# Пришлось придумывать новую конструкцию, т.к. многоточие перед именем, это оператор раскрытия словаря, а многоточие после имени, это повторение последнего значения до конца заданной размерности. -[ - [1804289383, 846930886,], [1681692777, 1714636915,], [1957747793, 424238335,], -]:Int - -&gt;:Int[5,2]( 0..10 ); # Создание тензора из диапазона -[ - [0, 1,], [2, 3,], [4, 5,], [6, 7,], [8, 9,], -]:Int - -&gt;:Tensor( 0..0.99..0.1 ); # Или даже так -[0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,]:Double -</code></pre><h1 id="операторы-и-управляющие-конструкции">Операторы и управляющие конструкции<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d0%b8-%d1%83%d0%bf%d1%80%d0%b0%d0%b2%d0%bb%d1%8f%d1%8e%d1%89%d0%b8%d0%b5-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h1> -<h2 id="операторы">Операторы:<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b" aria-label="Heading self-link"></a></h2> -<p>Все операторы имеют парный аналог с присвоением значения:</p> -<ul> -<li><strong>+</strong> и <strong>+=</strong> - сложение арифметических типов данных;</li> -<li><strong>-</strong> и <strong>-=</strong> - вычитание арифметических типов данных;</li> -<li><strong>/</strong> и <strong>/=</strong> - деление (результат число с плавающей точкой);</li> -<li><strong>//</strong> и <strong>//=</strong> - целочисленное деление с округлением к меньшему числу (как в Python);</li> -<li><em>*</em> и <em>*=</em> - умножение;</li> -<li><em>**</em> и <strong>**=</strong> - возведение в степень (он же используется и для повторения текстовых строк);</li> -<li><strong>++</strong> и <strong>++=</strong> - конкатенация строк с автоматическим приведением аргументов к стоковому типу (символ инкремента специально используется вместо одиночного плюса для того, чтобы в явном виде разделить конкатенацию строк и операторы арифметического сложения).</li> -</ul> -<h2 id="операторы-сравнения">Операторы сравнения:<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d1%81%d1%80%d0%b0%d0%b2%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h2> -<ul> -<li><strong>&lt;</strong>, <strong>&gt;</strong>, <strong>&lt;=</strong>, <strong>&gt;=</strong> - классические для сравнения скаляров</li> -<li><strong>==</strong> и <strong>!=</strong> - операторы сравнения с автоматическим приведением совместимых типов для любых объектов</li> -<li><strong>===</strong> и <strong>!==</strong> - оператор точного сравнения для любых объектов (автоматического приведения типов не выполняется)</li> -</ul> -<h2 id="проверки-типа-имени-класса-объекта">Проверки типа (имени класса объекта):<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b8-%d1%82%d0%b8%d0%bf%d0%b0-%d0%b8%d0%bc%d0%b5%d0%bd%d0%b8-%d0%ba%d0%bb%d0%b0%d1%81%d1%81%d0%b0-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%b0" aria-label="Heading self-link"></a></h2> -<p>Для оператора проверки имени класса объекта используется символ тильда <strong>~</strong>. Он немного похож на оператор <em>instanceof</em> в Java. Левым операндом должен быть проверяемый объект, а правым — проверяемый тип, который можно указать строкой литералом, переменной строкового типа или именем проверяемого класса непосредственно. Результатом операции будет истина, если правый операнд содержит название класса проверяемого объекта или он присутствует в иерархии наследования.</p> -<pre tabindex="0"><code>name := &#34;class&#34;; # Строковая переменная с именем класса -var ~ name; -var ~ :class; # Имя типа -var ~ &#34;class&#34;; # Строка литерал с именем типа -</code></pre><h2 id="утиная-типизация">Утиная типизация<a class="td-heading-self-link" href="#%d1%83%d1%82%d0%b8%d0%bd%d0%b0%d1%8f-%d1%82%d0%b8%d0%bf%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f" aria-label="Heading self-link"></a></h2> -<p>Оператор утиной типизации, два символа тильны <strong>~~</strong> — приблизительный аналог функции isinstance() в Python, который для простых типов сравнивает непосредственную совместимость типа левого операнда по отношению к правому. А для словарей и классов в левом операнде проверяется наличие всех имен полей, присутствующих у правого операнда, т.е.:</p> -<pre tabindex="0"><code>(field1=«value», field2=2,) ~~ (); # Истина (т. е. левый операнд словарь) -(field1=«value», field2=2,) ~~ (field1=_); # Тоже истина (т. к. поле field1 присутствует у левого операнда) -(field1=«value», field2=2,) ~~ (not_found=_); # Ложь, т.к. поле not_found у левого операнда отсутствует -</code></pre><p>Строгая утиная типизация <strong>~~~</strong> — для простых типов сравнивается идентичности типов без учета совместимости, а для составных типов происходит сравнение всех свойств с помощью оператора строгого равенства. Для данной операции, пустой тип совместим только с другим пустим типом.</p> -<h1 id="управляющие-конструкции">Управляющие конструкции<a class="td-heading-self-link" href="#%d1%83%d0%bf%d1%80%d0%b0%d0%b2%d0%bb%d1%8f%d1%8e%d1%89%d0%b8%d0%b5-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h1> -<p>К управляющим конструкциям языка NewLang относятся условный оператор, два вида циклов, оператор оценки выражения, оператор прерывания последовательности выполнения команд и перехват прерывания. Операторы проверки условий всегда указываются в квадратных скобках, а последовательность команд для выполнения - в фигурных.</p> -<h2 id="условный-оператор">Условный оператор<a class="td-heading-self-link" href="#%d1%83%d1%81%d0%bb%d0%be%d0%b2%d0%bd%d1%8b%d0%b9-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80" aria-label="Heading self-link"></a></h2> -<p>В качестве оператора проверки условия используется синтаксическая конструкция, соответствующая по смыслу термину «следует», т.е. тире и угловая скобка <strong>-&gt;</strong> или с двумя тире для большей наглядности <strong>&ndash;&gt;</strong>. Такая запись условного оператора очень похожа на математическую и легко объединяется в последовательности для проверки множественных условий вида «else if».</p> -<p>В общем случае условный оператор имеет вид: <code>[ условие ] -&gt; действие;</code> или <code>[ условие ] -&gt; {действие};</code> или <code>[ условие1 || условие2 ] --&gt; {действие}, [_] --&gt; {действие иначе};</code></p> -<p>Для наглядности записанный с отступами:</p> -<pre tabindex="0"><code>[ условие1 ] -&gt; { действие1 }, - [ условие2 ] -&gt; действие2, - [ условие3 ] -&gt; действие3, - [_] -&gt; {действие_иначе}; -</code></pre><h2 id="оценка-выражения">Оценка выражения<a class="td-heading-self-link" href="#%d0%be%d1%86%d0%b5%d0%bd%d0%ba%d0%b0-%d0%b2%d1%8b%d1%80%d0%b0%d0%b6%d0%b5%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h2> -<p>Синтаксическая конструкция с помощью которой реализуется аналог оператора switch выглядит следующим образом:</p> -<pre tabindex="0"><code>[ $var ] ==&gt; { - [1] -&gt; { code }; # Выполнится проверка условия $var == 1 - [1, 2] -&gt; { code }; # Выполнится проверка условия ($var == 1 || $var == 2) - [_] -&gt; { code default }; # Ветка условия иначе -}; -</code></pre><p>Причем в качестве оператора для оценки могут быть использован любые имеющиеся операторы сравнения на равенство:</p> -<ul> -<li><strong>==&gt;</strong> - проверка на равенство с приведением типов;</li> -<li><strong>===&gt;</strong> - проверка на точное равенство;</li> -<li><strong>~&gt;</strong> - проверка типа (имени класса);</li> -<li><strong>~~&gt;</strong> - утиная типизация;</li> -<li><strong>~~~&gt;</strong> - строгая утиная типизация.</li> -</ul> -<p>И если в качестве оператора сравнения использовать оператор утиной типизации, то оценка выражения превращается в классический Pattern Matching:</p> -<pre tabindex="0"><code>$value := (f1=1, f2=&#34;2&#34;,); -[ $value ] ~~~&gt; { - [ (f1=_, ), (f1=_, f2=0, ) ] -&gt; { code }; # Поле f2 отсутствует или число - [(f1=_, f2=&#34;&#34;,), (f1=_, f2=&#39;&#39;,)] -&gt; { code }; # Поле f2 строка - [_] -&gt; { code default }; # Код по умолчанию -}; -</code></pre><h2 id="операторы-циклов">Операторы циклов<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d1%86%d0%b8%d0%ba%d0%bb%d0%be%d0%b2" aria-label="Heading self-link"></a></h2> -<p>Для указания операторов циклов используются управляющие <strong>-&raquo;</strong> или <strong>&ndash;&raquo;</strong> (с двумя стрелками по направлению от проверки условия к телу цикла). И в зависимости от расположения условия и тела цикла, он может быть с предусловием (<em>while</em>) или постусловием (<em>do while</em>). Хотя пока эти синтаксические конструкции не &ldquo;отлежались&rdquo; и их можно считать временными из-за того, что их легко перепутать с условным оператором, и, возможно, имеет смысл заменить разные операторы цикла одной единственной конструкцией вида: <strong>&lt;&ndash;&gt;</strong> или <strong>&laquo;-&raquo;</strong>, которая сильнее отличается от оператора следования.</p> -<p>Но в настоящий момент циклы реализованы вот так:</p> -<pre tabindex="0"><code>[условие while] -&gt;&gt; { - тело цикла while -}; - -{ - тело цикла do while -} &lt;&lt;-- [условие do while]; -</code></pre><p>Реализация цикла foreach на примере суммирования всех элементов словаря (или одномерного тензора):</p> -<pre tabindex="0"><code>summa := 0; -dict := (1,2,3,4,5,); -[ dict ] --&gt;&gt; { # Условие цикла, пока есть данные - item, dict := ... dict; # Результат оператора раскрытия словаря - первый его элемент перемещается в item - summa += item; # Вычисление суммы всех элементов словаря -}; -</code></pre><h2 id="операторы-прерывания-возврата">Операторы прерывания (возврата)<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d0%bf%d1%80%d0%b5%d1%80%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%b2%d0%be%d0%b7%d0%b2%d1%80%d0%b0%d1%82%d0%b0" aria-label="Heading self-link"></a></h2> -<p>В качестве оператора прерывания/возврата используется два символа минус <strong>&ndash;</strong>. Оператор позволяет прервать выполнение последовательности команд и/или вернуть данные из текущей функции/блока кода и является самым близким аналогом оператора <strong>return</strong> и <strong>throw</strong> одновременно. Для того чтобы вернуть данные, их необходимо указать между двумя операторами прерывания, т.е. <code>--100--; # Вернуть указанное значение</code>. Если возвращаемое значение не указано явно, то будет возвращено значение <em>None</em>.</p> -<h2 id="следование-блок-кодалямбда-функция">Следование (блок кода/лямбда функция)<a class="td-heading-self-link" href="#%d1%81%d0%bb%d0%b5%d0%b4%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%b1%d0%bb%d0%be%d0%ba-%d0%ba%d0%be%d0%b4%d0%b0%d0%bb%d1%8f%d0%bc%d0%b1%d0%b4%d0%b0-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8f" aria-label="Heading self-link"></a></h2> -<p>Алгоритмическая конструкция, которая отвечает последовательное выполнение нескольких команд/операторов и возвращающая результат выполнения последнего из них. Также, результатом выполнения может быть значение, которое возвращается с помощью оператора прерывания (возврата). Это очень похоже на классическую лямбда функцию, только она выполняется сразу во время определения, а в переменную сохраняется уже результат её выполнения.</p> -<p>Следование без перехвата прерывания оформляется в виде последовательности обычных и фигурных скобок, т.е. <code>(){ run code };</code> или тоже самое, но сохраняет результата выполнения в переменной: <code>$result := (){ run(); code() };</code>. Но если внутри такой функции будет выполнен оператор прерывания, то она никогда вернет управления и не сохранит возвращаемое значение в переменой <em>$result</em>!</p> -<p>Чтобы перехватывать прерывания, в том числе и возвращаемые значения, необходимо использовать конструкция следования с перехватом прерываний, которая оформляется в виде последовательности обычных и <strong>двойных</strong> фигурных скобок, т.е. <code>$error := (){{ run(); error();code() }};</code>. Такая конструкция перехватывает все возвраты и прерывания, если они возникают во время выполнения последовательности команд. В этом случае любой результат будет сохранен в переменной <em>$error</em> как при нормальном завершении, так и в случае возникновения ошибки.</p> -<p>Для более тонкой настройки перехвата прерываний следует использовать типизированную конструкцию, когда в явном виде указывается, какие типы прерываний следует перехватывать. <code>$runtime := (){{ run(); error(); code() }}:ErrorRuntime;</code>. Такая конструкция вернет результат только в случае успешного завершения (когда с помощью оператора прерывания возвращается не типизированное значение, например, <code>--&quot;Строка&quot;--;</code>), или при создании прерывания с указанием конкретного типа <strong>&ndash;:ErrorRuntime(&ldquo;Описание ошибки&rdquo;)&ndash;;</strong>. А вот при возникновении любого другого типизированного прерывания, значение перехвачено не будет и все отработает как самый первый вариант, т.е. без перехвата прерывания и без сохранения возвращаемого значения в переменную.</p> -<h2 id="стратегия-обработки-ошибок">Стратегия обработки ошибок<a class="td-heading-self-link" href="#%d1%81%d1%82%d1%80%d0%b0%d1%82%d0%b5%d0%b3%d0%b8%d1%8f-%d0%be%d0%b1%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b8-%d0%be%d1%88%d0%b8%d0%b1%d0%be%d0%ba" aria-label="Heading self-link"></a></h2> -<p>Обработка ошибок состоит из комбинации двух элементов: оператора прерывания выполнения с указанием типа возвращаемого значения и алгоритмической конструкции следование с возможностью перехвата прерывания заданного типа.</p> -<p>Это немного отличается от классического варианта обработки исключений, который в обычных языках программирования обычно оформляется ключевыми словами try… catch… finally с различными вариациями. Ведь основная цель подобных синтаксических конструкций — выделить участок кода, где возможно возникновение ошибки, перехватить и обработать правильный тип данных (исключений), т.к. <strong>NewLang</strong> не делает различий между операторами возврата и генерации исключения.</p> -<h3 id="подход-к-обработке-исключений-следующий">Подход к обработке исключений следующий:<a class="td-heading-self-link" href="#%d0%bf%d0%be%d0%b4%d1%85%d0%be%d0%b4-%d0%ba-%d0%be%d0%b1%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b5-%d0%b8%d1%81%d0%ba%d0%bb%d1%8e%d1%87%d0%b5%d0%bd%d0%b8%d0%b9-%d1%81%d0%bb%d0%b5%d0%b4%d1%83%d1%8e%d1%89%d0%b8%d0%b9" aria-label="Heading self-link"></a></h3> -<p>Программный код, который может привести к ошибке, заключается в двойные фигурные скобки, а результат выполнения такого блока кода присваивается переменной. После этого анализируется возвращенное значение, например, оператором сравнения по образцу:</p> -<pre tabindex="0"><code>$result := (){{ # начало аналога блока try - $value := call_or_exception1(); - [условие1] -&gt; { -- :Error -- }; - [условие2] -&gt; { -- $value -- }; - $value := call_or_exception2(); -}}; # конец аналога блока try - -[$result] ~&gt; { # Для сравнения по образцу использовать оператор проверки типа (имени класса) - [:ErrorParser] -&gt; {Код обработки ошибок парсера}; - [:ErrorRunTime] -&gt; {Код обработки ошибок времени выполнения}; - [:Error] -&gt; { Код обработки остальных ошибок }; - [_] -&gt; { Обработка нормальных данных $value без ошибок }; -}; -</code></pre><h2 id="сборка-repl-из-исходников-пока-только-под-linux">Сборка REPL из исходников (пока только под Linux)<a class="td-heading-self-link" href="#%d1%81%d0%b1%d0%be%d1%80%d0%ba%d0%b0-repl-%d0%b8%d0%b7-%d0%b8%d1%81%d1%85%d0%be%d0%b4%d0%bd%d0%b8%d0%ba%d0%be%d0%b2-%d0%bf%d0%be%d0%ba%d0%b0-%d1%82%d0%be%d0%bb%d1%8c%d0%ba%d0%be-%d0%bf%d0%be%d0%b4-linux" aria-label="Heading self-link"></a></h2> -<h3 id="подготовка-репозитория">Подготовка репозитория<a class="td-heading-self-link" href="#%d0%bf%d0%be%d0%b4%d0%b3%d0%be%d1%82%d0%be%d0%b2%d0%ba%d0%b0-%d1%80%d0%b5%d0%bf%d0%be%d0%b7%d0%b8%d1%82%d0%be%d1%80%d0%b8%d1%8f" aria-label="Heading self-link"></a></h3> -<ul> -<li><a href="https://github.com/rsashka/newlang"><u>Скачать исходники</u></a></li> -<li>Скачать и развернуть архив <a href="https://pytorch.org/">libtorch</a> в каталоге <em>contrib</em> (PyTorch Build: Stable (1.10.*) -&gt; Your OS: Linux -&gt; Package: LibTorch -&gt; Language: C++ / Java -&gt; Compute Platform: CPU -&gt; Download here (cxx11 ABI): -<a href="https://download.pytorch.org/libtorch/cpu/libtorch-cxx11-abi-shared-with-deps-1.10.2%2Bcpu.zip">libtorch-cxx11-abi-shared-with-deps-1.10.2+cpu.zip</a>)</li> -<li>Активировать и скачать исходники субмодулей (<code>git submodule init &amp;&amp; git submodule update</code>)</li> -<li>В каталоге <em>contrib</em> запустить файл <code>build.sh</code> для сборки библиотеки libffi</li> -<li>В каталоге <em>core</em> запустить файл <code>compile_syntax.sh</code> для генерации файлов парсера и лексического анализатора. Также может потребоваться установка утилит <em>flex</em> и <em>bison</em>. Если что, у меня установлены flex 2.6.4 и bison (GNU Bison) 3.7.4</li> -</ul> -<h3 id="собрать">Собрать<a class="td-heading-self-link" href="#%d1%81%d0%be%d0%b1%d1%80%d0%b0%d1%82%d1%8c" aria-label="Heading self-link"></a></h3> -<ul> -<li>Юнит-тесты (newlang_test): в каталоге <em>core</em> выполнить команду <code>make CONF=UnitTest</code>*</li> -<li>Интерпретатор (nlc): в каталоге <em>core</em> выполнить команду <code>make CONF=Debug</code>*</li> -</ul> -<hr> -<p>*) - Сборка проекта выполняется обычной утилитой make, но сборочные файлы генерируются автоматически в давно устаревшей версии NetBeans 8.2, т.к. это единственная универсальная среда разработки с поддержкой Makefile &ldquo;из коробки&rdquo;, тогда как в текущей версии Apache NetBeans полноценная поддержка разработки на С/С++ вообще отсутствует. Начал постепенный переход на использование редактора VSCodium (аналога VSCode, в котором вычищена телеметрия от Microsoft) и генерацию скриптов сборки с помощью сmake, но этот процесс пока не завершен.</p> -<h1 id="планы-на-будущее">Планы на будущее<a class="td-heading-self-link" href="#%d0%bf%d0%bb%d0%b0%d0%bd%d1%8b-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5" aria-label="Heading self-link"></a></h1> -<p>Текущая версия языка значительно обогатилась возможностями, но все еще является тестовой платформой для проверки декларируемых концепций и основного синтаксиса. Если говорить о планах, то в настоящий момент роадмап развития NewLang следующий:</p> -<ul> -<li>Реализовать макросы для более привычного использования языка (за счет использования DSL);</li> -<li>Добавить в арифметические типы длинные числа и дроби;</li> -<li>Сделать какую-нибудь логическую игру (крестики нолики, судоку или что-то похожее) с алгоритмическим выбором следующего хода и его вычислением с помощью машинного обучения;</li> -<li>Написать еще больше разных примеров для оценки синтаксиса;</li> -<li>Зафиксировать синтаксис с учетом полученного опыта и обратной связи;</li> -<li>Восстановить работоспособность компилятора для генерации исполняемых файлов;</li> -<li>Сделать очередную большую чистку кода;</li> -<li>Переработать и задокументировать получившуюся семантику языка с учетом всех возможностей и выпустить первую полнофункциональную версию NewLang.</li> -</ul> - - - - - - Blog: Новый язык программирования - http://localhost:1313/blog/newlang/ - Fri, 18 Feb 2022 00:00:00 +0000 - - http://localhost:1313/blog/newlang/ - - - - <p><img alt="КДПВ" src="http://localhost:1313/blog/langs.jpeg"></p> - - -<div class="pageinfo pageinfo-primary"> -<p>Внимание!!!</p> -<p>Данная статья содержит описание синтаксиса NewLnag предыдущей версии.</p> -<p>Актуальную версию синтаксиса языка можно посмотреть <a href="http://localhost:1313/docs/">тут</a>.</p> - -</div> - -<p>Более года назад я начал публикацию статей с описанием особенностей нового языка программирования. -С тех пор утекло много воды, было протестировано множество идей, в итоге несколько раз все поменялось кардинальным образом -и сейчас представляю на суд читателей описание предфинальной версии языка и его особенностей.</p> -<p>Данная статья предназначена в первую очередь для проверки основных концепций нового языка программирования, а также для получения обратной связи от читателей Хабра. -Ведь согласно наблюдению <a href="https://habr.com/post/539674/">Хабр-ума палата</a>, не замыленный взгляд со стороны очень сильно помогает в проработке новых идей.</p> -<p>Этот проект очень долго был без собственного названия и в публикациях назывался просто и абстрактно &ldquo;новый язык&rdquo;. -Но после нескольких статей, временное название &ldquo;новый язык&rdquo; постепенно превратилось в имя собственное <em>NewLang</em>, -которое я и решил в конечном итоге оставить (что еще раз подтверждает поговорку, что нет ничего более постоянного, чем что-то временное).</p> -<p><strong>NewLang</strong> - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические конструкции -с декларативным программированием и тензорными вычислениями для задач машинного обучения.</p> -<p>Основной особенностью языка является легкий, логичный и непротиворечивый синтаксис, который основан не на использовании зарезервированных ключевых слов, -а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка). -Основные свойства и особенности языка:</p> -<ul> -<li>Возможность работы как в режиме интерпретатора, так и компилятора.</li> -<li>Динамическая и статическая типизация с возможностью указания типов в явном виде.</li> -<li>Статическая типизация является условно строгой (автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных, например, целое число может быть автоматически преобразовано в вещественное, но не наоборот)</li> -<li>Автоматическое управление памятью.</li> -<li>ООП в виде явного наследования классов и <a href="https://ru.wikipedia.org/wiki/%D0%A3%D1%82%D0%B8%D0%BD%D0%B0%D1%8F_%D1%82%D0%B8%D0%BF%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F">утиная</a> типизация.</li> -<li>На уровне синтаксиса поддержка нескольких типов функций (обычные и <a href="https://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D1%82%D0%BE%D1%82%D0%B0_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8">чистые функции без побочных эффектов</a>).</li> -<li>Необязательные и именованные параметры функций.</li> -<li>Возможны вставки кода на языке реализации (С/С++).</li> -<li>Простая интеграция с уже существующими программными библиотеками (в том числе импорт нативных переменных и функций из С/С++).</li> -<li>Имеется REPL <a href="https://ru.wikipedia.org/wiki/REPL">read-eval-print loop — «цикл: чтение — вычисление — вывод»</a>.</li> -</ul> -<h2 id="зачем-нужен-newlang">Зачем нужен NewLang?<a class="td-heading-self-link" href="#%d0%b7%d0%b0%d1%87%d0%b5%d0%bc-%d0%bd%d1%83%d0%b6%d0%b5%d0%bd-newlang" aria-label="Heading self-link"></a></h2> -<p>У всех современных языков программирования происходит постоянное развитие (читай усложнение) синтаксиса по мере выхода новых версий. -Это является своего рода, платой за появление новых возможностей и воспринимается пользователями как естественное явление.</p> -<p>Но одновременно является и серьезной проблемой, т.к. с выходом новых версий добавляются новые ключевые слова и синтаксические конструкции, -что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки -и трудоемкости поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.</p> -<p>У NewLang сложность языковых конструкций естественно ограничена за счет разделения синтаксиса языка на две части, -что упрощает его изучение и использование. <em>Основной синтаксис</em> — для написания программ в объектно-ориентированном (императивном) -и декларативном стилях, который основан не на зарезервированных ключевых словах, а на строгих грамматических правилах -и <em>Расширенный синтаксис</em> — когда основного синтаксиса становится недостаточно, или требуется использовать языковую конструкцию языка реализации.</p> -<p>Еще одно неудобство современных мейнстримовых языков, большинство из них были созданы до начала эпохи машинного обучения, -поэтому тензорные вычисления у них выполнены в виде отдельных библиотек, а не встроены в основной синтаксис языка и систему базовых типов. -У <em>NewLang</em> тензорные вычисления доступны «из коробки» (используется библиотека <a href="https://pytorch.org/">libtorch</a>), -а арифметические типы данных являются скалярами (тензорами нулевой размерности).</p> -<h3 id="основной-синтаксис">Основной синтаксис<a class="td-heading-self-link" href="#%d0%be%d1%81%d0%bd%d0%be%d0%b2%d0%bd%d0%be%d0%b9-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81" aria-label="Heading self-link"></a></h3> -<p>Основной синтаксис <em>NewLang</em> - простой и логичный за счет того, что он построен исключительно на грамматических правилах -и не использует каких либо зарезервированных ключевых слов, а все буквенно-символьные последовательности рассматриваются как идентификаторы -в которых можно использовать любые не-ASCII символы.</p> -<blockquote> -<p>Идеализированная цель отказа от ключевых слов, приблизить чтение исходного текста программы к чтению обычного текста за счет использования знаков препинания при описании логики работы алгоритма.</p> -</blockquote> -<blockquote> -<p>Конечно <em>запятая</em> человек может вычленять ключевые управляющие слова языка и <em>слеш</em> или учитывать форматирование программы <em>запятая</em> -чтобы на их основе понимать синтаксические конструкции <em>запятая</em> хотя при обычном чтении мы привыкли опираться именно на семантику -знаков препинания <em>точка</em> мы конечно можем писать знаки препинания и обычным текстом <em>точка</em> но согласитесь <em>запятая</em> что тогда -<em>открытая скобка</em> например <em>запятая</em> вот такой вот текст <em>закрытая скобка</em> будет очень не удобно читать <em>точка</em></p> -</blockquote> -<p>Названия встроенных типов или имена служебных функций системной библиотеки определяются конкретной реализацией языка, -поэтому не являются зарезервированными ключевыми словами и при необходимости могут быть переопределены, например, -для создания собственного, предметно-ориентированного диалекта (<a href="ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%B4%D0%BC%D0%B5%D1%82%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D1%8F%D0%B7%D1%8B%D0%BA">DSL - domain-specific language</a>), если в этом возникнет необходимость. -Но сама структура программы и логика выполняемого алгоритма все равно останутся понятны всем, кто знаком с правилами основного синтаксиса NewLang.</p> -<p><strong>Пример скрипта Hello world! на NewLang</strong></p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic">#!./nlc --eval </span> -</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Определение функции hello</span> -</span></span><span style="display:flex;"><span> hello<span style="color:#ce5c00;font-weight:bold">(</span>str<span style="color:#ce5c00;font-weight:bold">)</span> :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87">printf</span> :<span style="color:#ce5c00;font-weight:bold">=</span> @import<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#39;printf(format:Format, ...):Int&#39;</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Импорт стандартной C функции</span> -</span></span><span style="display:flex;"><span> printf<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#39;%s\n&#39;</span>, <span style="color:#000">$str</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Вызов C функции с проверкой типов аргументов по строке формата</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> hello<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#39;Привет, мир!&#39;</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Вызвать функцию</span> -</span></span></code></pre></div><p>Вывод: Привет, мир!</p> -<h3 id="расширенный-синтаксис">Расширенный синтаксис<a class="td-heading-self-link" href="#%d1%80%d0%b0%d1%81%d1%88%d0%b8%d1%80%d0%b5%d0%bd%d0%bd%d1%8b%d0%b9-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81" aria-label="Heading self-link"></a></h3> -<p>Расширенный синтаксис — это возможность вставить в текст программы NewLang исходный код на языке реализации. -Сейчас это С/С++, что позволяет использовать любые возможности этого мощного языка программирования.</p> -<p>Обработка расширенного синтаксиса происходит на этапе компиляции приложения, а взаимодействие между основным и расширенным синтаксисами происходит за счет совместного использования идентификаторов, -которое полностью прозрачно для пользователя и подчиняется единым грамматическим правилам основного синтаксиса.</p> -<h3 id="еще-немного-примеров">Еще немного примеров:<a class="td-heading-self-link" href="#%d0%b5%d1%89%d0%b5-%d0%bd%d0%b5%d0%bc%d0%bd%d0%be%d0%b3%d0%be-%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80%d0%be%d0%b2" aria-label="Heading self-link"></a></h3> -<p>Любая последовательность вычислений возвращает результат выполнения последнего оператора. -Поэтому выполнение одной команды или последовательности команд всегда возвращает какой-либо результат, -а оператор возврата из функции необязателен, так как результатом будет значение последнего вычисленного выражения.</p> -<p><strong>Создание переменных</strong></p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> scalar :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#0000cf;font-weight:bold">42</span> -</span></span><span style="display:flex;"><span> <span style="color:#0000cf;font-weight:bold">42</span> -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> tensor :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">[</span>1,2,3,4,5,<span style="color:#ce5c00;font-weight:bold">]</span> <span style="color:#8f5902;font-style:italic"># Тип тензора выводится автоматически</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>1, 2, 3, 4, 5,<span style="color:#ce5c00;font-weight:bold">]</span>:Char -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> str :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#4e9a06">&#39;$1 string&#39;</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$1</span> string -</span></span></code></pre></div><p><strong>Арифметические операции</strong></p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> tensor * <span style="color:#0000cf;font-weight:bold">2</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>2, 4, 6, 8, 10,<span style="color:#ce5c00;font-weight:bold">]</span>:Short -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> tensor * <span style="color:#0000cf;font-weight:bold">20</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>20, 40, 60, 80, 100,<span style="color:#ce5c00;font-weight:bold">]</span>:Short -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> tensor * 0.5 -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>0.5, 1, 1.5, 2, 2.5,<span style="color:#ce5c00;font-weight:bold">]</span>:Double -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> tensor / <span style="color:#0000cf;font-weight:bold">2</span> <span style="color:#8f5902;font-style:italic"># Результат деления — число с плавающей точкой</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>0.5, 1, 1.5, 2, 2.5,<span style="color:#ce5c00;font-weight:bold">]</span>:Double -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> tensor // <span style="color:#0000cf;font-weight:bold">2</span> <span style="color:#8f5902;font-style:italic"># Целочисленное деление без остатка</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>0, 1, 1, 2, 2,<span style="color:#ce5c00;font-weight:bold">]</span>:Char&lt;/source&gt; -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> tensor % <span style="color:#0000cf;font-weight:bold">2</span> <span style="color:#8f5902;font-style:italic"># Целочисленный остаток от деления</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>1, 0, 1, 0, 1,<span style="color:#ce5c00;font-weight:bold">]</span>:Char&lt;/source&gt; -</span></span></code></pre></div><p><strong>Строковые операции</strong></p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#000">str</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#4e9a06">&#39;сцепеление строк &#39;</span> ++ str<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> сцепеление строк <span style="color:#000">$1</span> string -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> str<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#39;строка как шаблон&#39;</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> сцепеление строк строка как шаблон string -</span></span></code></pre></div><h3 id="преобразование-тензоров">Преобразование тензоров<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b5%d0%be%d0%b1%d1%80%d0%b0%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d1%82%d0%b5%d0%bd%d0%b7%d0%be%d1%80%d0%be%d0%b2" aria-label="Heading self-link"></a></h3> -<p>В эпоху машинного обучения тензоры являются основными элементами вычислений, -поэтому для конвертирования <em>данных</em> в тензоры используется отдельная синтаксическая конструкция, -состоящая из двойных квадратных скобок <strong>[[</strong> <em>данные</em> <strong>]]</strong>. Подробнее про особенности преобразования типов можно прочитать далее.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> tstr :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">[[</span><span style="color:#4e9a06">&#34;Тест&#34;</span><span style="color:#ce5c00;font-weight:bold">]]</span> <span style="color:#8f5902;font-style:italic"># Создать тензор из строки широких символов</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>1058, 1077, 1089, 1090,<span style="color:#ce5c00;font-weight:bold">]</span>:Int -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> t2 :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">[[</span> <span style="color:#4e9a06">&#34;Тест&#34;</span> <span style="color:#ce5c00;font-weight:bold">]]</span>:Int<span style="color:#ce5c00;font-weight:bold">[</span>2,2<span style="color:#ce5c00;font-weight:bold">]</span> <span style="color:#8f5902;font-style:italic"># Тоже самое, но тензор двухмерный</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>1058, 1077,<span style="color:#ce5c00;font-weight:bold">]</span>, <span style="color:#ce5c00;font-weight:bold">[</span>1089, 1090,<span style="color:#ce5c00;font-weight:bold">]</span>, -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">]</span>:Int&lt;/source&gt; -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> StrWide<span style="color:#ce5c00;font-weight:bold">(</span>tstr<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#8f5902;font-style:italic"># Конвертировать тензор обратно в строку</span> -</span></span><span style="display:flex;"><span> Тест -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> Double<span style="color:#ce5c00;font-weight:bold">(</span>t2<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#8f5902;font-style:italic"># Изменить тип данных тезора</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>1058, 1077,<span style="color:#ce5c00;font-weight:bold">]</span>, <span style="color:#ce5c00;font-weight:bold">[</span>1089, 1090,<span style="color:#ce5c00;font-weight:bold">]</span>, -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">]</span>:Double -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> t3 :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">[[</span> t2 <span style="color:#ce5c00;font-weight:bold">]]</span>:Char<span style="color:#ce5c00;font-weight:bold">[</span>4<span style="color:#ce5c00;font-weight:bold">]</span> <span style="color:#8f5902;font-style:italic"># Преобразовать тип данных тензора и его размерность</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>34, 53, 65, 66,<span style="color:#ce5c00;font-weight:bold">]</span>:Char -</span></span></code></pre></div><h2 id="синтаксис-newlang">Синтаксис NewLang:<a class="td-heading-self-link" href="#%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81-newlang" aria-label="Heading self-link"></a></h2> -<p>При разработке синтаксиса я старался придерживаться уже сложившихся правил, чтобы не создавать множественных смыслов, -зависящих от контекста. <del>И одновременно «объять необъятное»</del></p> -<h3 id="основы">Основы<a class="td-heading-self-link" href="#%d0%be%d1%81%d0%bd%d0%be%d0%b2%d1%8b" aria-label="Heading self-link"></a></h3> -<ul> -<li>Операторы разделяются точкой с запятой «;».</li> -<li>Отступы и переводы строк игнорируются (очень хотелось иметь возможность автоматического форматирование кода).</li> -<li>Многострочные комментарии в исходном коде соответствуют стилю С/С++ и должны располагаться между символами /* и */. Вложенность многострочных комментариев не поддерживается.</li> -<li>Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash.</li> -<li>Последовательность выполняемых команд, которая должна выполняться как единое целое, заключается в фигурные скобки «{}».</li> -<li>Программные вставки расширенного синтаксиса на языке реализации заключается в фигурные скобки со знаком процента <strong>%{</strong> <em>/* тут может быть любой код на C/C++*/</em> <strong>%}</strong>.</li> -</ul> -<h3 id="создания-объектов-и-присвоения-новых-значений">Создания объектов и присвоения новых значений<a class="td-heading-self-link" href="#%d1%81%d0%be%d0%b7%d0%b4%d0%b0%d0%bd%d0%b8%d1%8f-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%be%d0%b2-%d0%b8-%d0%bf%d1%80%d0%b8%d1%81%d0%b2%d0%be%d0%b5%d0%bd%d0%b8%d1%8f-%d0%bd%d0%be%d0%b2%d1%8b%d1%85-%d0%b7%d0%bd%d0%b0%d1%87%d0%b5%d0%bd%d0%b8%d0%b9" aria-label="Heading self-link"></a></h3> -<p>Для создания объектов и присвоения им новых значений в NewLang используется сразу три разных оператора.<br> -Оператор «<strong>::=</strong>» используется только для создания новых объектов, а если объект с таким именем уже существует, то генерируется ошибка.<br> -Оператор «<strong>:=</strong>» используется для тех же целей, но если объект с таким именем уже существует, то ошибки не происходит, -а новое значение присваивается уже существующему объекту.<br> -И последний оператор «<strong>=</strong>» применяется только для присвоения значения уже существующим объектам, и если объект с указанным именем отсутствует, то тоже происходит ошибка.</p> -<p>Использование трех разных операторов для создания/изменения объектов позволяет более гибко контролировать подобные операции и выявлять логические ошибки в коде на более раннем этапе.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span> <span style="color:#000">var</span> <span style="color:#ce5c00;font-weight:bold">::=</span> <span style="color:#0000cf;font-weight:bold">1.0</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#a40000">#</span> <span style="color:#a40000">Создать</span> <span style="color:#a40000">новую</span> <span style="color:#a40000">переменную</span> <span style="color:#000">var</span> <span style="color:#a40000">без</span> <span style="color:#a40000">указания</span> <span style="color:#a40000">типа</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">var</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#0000cf;font-weight:bold">100</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#a40000">#</span> <span style="color:#a40000">Присвоить</span> <span style="color:#a40000">новое</span> <span style="color:#a40000">значение</span> <span style="color:#a40000">уже</span> <span style="color:#a40000">существующей</span> <span style="color:#a40000">переменной</span> -</span></span><span style="display:flex;"><span> <span style="color:#f57900">printf</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#a40000">@</span><span style="color:#000">import</span><span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">&#39;</span><span style="color:#000">printf</span><span style="color:#000;font-weight:bold">(</span><span style="color:#f57900">format</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">Format</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000;font-weight:bold">...)</span><span style="color:#ce5c00;font-weight:bold">:</span><span style="color:#000">Int</span><span style="color:#a40000">&#39;</span><span style="color:#000;font-weight:bold">);</span> <span style="color:#8f5902;font-style:italic">/* Создать новый или переопределить -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> объект printf, который будет результатом выполнения глобальной функции @import */</span> -</span></span></code></pre></div><h3 id="идентификаторы-объектов-и-модификаторы">Идентификаторы объектов и модификаторы<a class="td-heading-self-link" href="#%d0%b8%d0%b4%d0%b5%d0%bd%d1%82%d0%b8%d1%84%d0%b8%d0%ba%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%be%d0%b2-%d0%b8-%d0%bc%d0%be%d0%b4%d0%b8%d1%84%d0%b8%d0%ba%d0%b0%d1%82%d0%be%d1%80%d1%8b" aria-label="Heading self-link"></a></h3> -<p>В качестве идентификаторов можно использовать буквы, цифры и знаки подчеркивания в любых комбинациях, при условии, -что первый символ идентификатора не является цифрой.</p> -<p>В NewLang существует возможность указания области видимости и времени жизни объекта с помощью модификатора — специального символа перед -именем переменной. Это может показаться немного похожим на венгерскую нотацию, но в отличие от нее, -модификатор не имеет отношения к типу объекта и не является частью имени идентификатора. -К тому же в качестве модификаторов используется строго определённые символы, назначение которых определено заранее.</p> -<p>Так, символ «<strong>$</strong>» в начале имени обозначает локальную переменную, время жизни которой ограничено текущей областью видимости и при её завершении локальная переменная уничтожается. -Символ «<strong>@</strong>» обозначает глобальную переменную, а сам объект сохраняет свое состояние даже после выхода из текущей области видимости. -Так же обозначаются и имена типов данных, например, при создания новых типов, а в качестве модификатора используется символа двоеточия «<strong>:</strong>»</p> -<p>Семантика обращения к аргументам функций очень похоже на работу с аргументами в bash скриптах, где <strong>$1</strong> или <strong>$arg</strong> — порядковый номер -или имя аргумента (происходит обращение к локальным переменным в текущей области видимости).</p> -<p>Использование модификаторов является обязательным только в двух случаях: -- При создании нового типа данных, так как типы всегда создаются в глобальной области видимости, а их символьные имена должны быть уникальными -- При обращении к объектам NewLang внутри программных вставок кода на языке реализации, так как они используется как маркеры при поиске идентификаторов NewLang в коде С/С++.</p> -<p>В остальных случаях, для обращения к переменным указывать их модификаторы не обязательно. -И если при обращении к объекту модификатор не указан, то сперва ищется локальная переменная, а потом глобальная с таким же именем. -Причем, локальная переменная будет перекрывать глобальную.</p> -<p>Так же следует иметь в виду, что компилятор может генерировать код для прямого обращения к локальным объектам уже на этапе компиляции, -тогда как для обращения к глобальным объектам, или если модификатор области видимости отсутствует, компилятор вынужден каждый раз встраивать runtime вызов функции поиска объекта в таблице символов.</p> -<h2 id="система-типов">Система типов<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0-%d1%82%d0%b8%d0%bf%d0%be%d0%b2" aria-label="Heading self-link"></a></h2> -<p>Так как система типов языка динамическая, то явное указание типа не влияет на размер переменной и является только своего рода логическим ограничением на возможность присвоения переменной значения другого типа.</p> -<p>Информация о типах используется при проверке их совместимости, когда существующему объекту присваивается значение другого типа. -Такая операция возможна только когда типы совместимы между собой и допускают автоматическое приведение. -Это справедливо как во время парсинга/компиляции исходного теста, так и во время выполнения в режимах интерпретатора и/или скомпилированного файла.</p> -<h3 id="арифметические-типы">Арифметические типы:<a class="td-heading-self-link" href="#%d0%b0%d1%80%d0%b8%d1%84%d0%bc%d0%b5%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b" aria-label="Heading self-link"></a></h3> -<p>Арифметические типы данных являются тензорами - массивами чисел одного типа с произвольным количеством измерений и одинаковым размером столбцов в каждом. -Единичное число тоже тензор нулевого размера.</p> -<p>Поддерживаются только знаковые целые числа, т.к. в беззнаковых числах особая нужда отсутствует, а проблем с ними можно найти очень много на ровном месте.</p> -<p><strong>Проблемы беззнаковых чисел (из интернета)</strong></p> -<blockquote> -<p>Во-первых, вычитание двух беззнаковых чисел, например 3 и 5. 3 минус 5 равно 4294967294, -т.к. -2 не может быть представлено как беззнаковое число. Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных -значений со знаком и без знака. С++ может свободно преобразовывать числа со знаком и без знака, -но не проверяет диапазон, чтобы убедиться, что вы не переполняете свой тип данных.</p> -<p>В C++ всё же есть несколько случаев, когда можно (или необходимо) использовать беззнаковые числа. -Во-первых, числа без знака предпочтительнее при работе с битами. Во-вторых, использование беззнаковых чисел связаных с индексацией массивов.</p> -</blockquote> -<p>Но это мой случай, так как индекс может быть отрицательным и даже не числом, а диапазоном или многоточием. -З.Ы. И даже зная об этом, все равно умудрился недавно словить баг с отрицательными индексами у словарей!</p> -<p>Имена встроенных арифметических типов говорят сами за себя: Char, Short, Int, Long, Float, Double, ComplexFloat, ComplexDouble. -Отдельным типом идет логический тип Bool, который может принимать значения только 0 или 1 (false/true соответственно), -и в зависимости от выполняемой операции может быть отнесен к целочисленным типам, так и не входить в их состав.</p> -<p><em>(данный подход интерпретации логического типа данных был взят из библиотеки Torch)</em></p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">// Treat bool as a distinct &#34;category,&#34; to be consistent with type promotion -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">// rules (e.g. `bool_tensor + 5 -&gt; int64_tensor`). If `5` was in the same -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">// category as `bool_tensor`, we would not promote. Differing categories -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">// implies `bool_tensor += 5` is disallowed. -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">// -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">// NB: numpy distinguishes &#34;unsigned&#34; as a category to get the desired -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">// `bool_tensor + 5 -&gt; int64_tensor` behavior. We don&#39;t, because: -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">// * We don&#39;t want the performance hit of checking the runtime sign of Scalars. -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">// * `uint8_tensor + 5 -&gt; int64_tensor` would be undesirable. -</span></span></span></code></pre></div><p>В будущем планируется добавить классы чисел для длинной арифметики и дробей, для чего зарезервированы названия типов BigNum, Currency и Fraction.</p> -<p>Доступ к элементам тензора происходит по целочисленному индексу, который начинается с 0. -Для многомерного тензора, индексы элемента перечисляются в квадратных скобках через запятую. -Поддерживается доступ к элементам через отрицательный индекс, который обрабатывается точно так же, -как в Python (-1 последний элемент, -2 предпоследний и т.д.).</p> -<p>Литерал тензор в тексте программы записывается в квадратных скобках с обязательной завершающей запятой, т.е. [1, 2,] - это литерал одномерный тензор из двух чисел. -После закрывающей скобки тип тензора может быть указан в явном виде. Если тип не указан, то он выводится автоматически на основании указанных данных и выбирается минимально возможный байтовый размер, -который позволяет сохранить все значения без потери точности.</p> -<p>Примеры:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#000">$var_char</span> :<span style="color:#ce5c00;font-weight:bold">=</span> 123<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Тип Char выводится автоматически</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$var_short</span> :<span style="color:#ce5c00;font-weight:bold">=</span> 1000<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Тип Short выводится автоматически</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$var_bool</span> :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">[</span>0, 1, 0, 1,<span style="color:#ce5c00;font-weight:bold">]</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Тензор из 4 элементов. Тип Bool выводится автоматически</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$tensor</span><span style="color:#ce5c00;font-weight:bold">[</span>10,10<span style="color:#ce5c00;font-weight:bold">]</span>:Int :<span style="color:#ce5c00;font-weight:bold">=</span> 1<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Тензор Int размером 2x2 инициализированный 1</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$scalar</span> :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">$tensor</span><span style="color:#ce5c00;font-weight:bold">[</span>5,5<span style="color:#ce5c00;font-weight:bold">]</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Присвоить скаляру значение указанного элемента тензора</span> -</span></span></code></pre></div><h3 id="строковые-типы-данных">Строковые типы данных:<a class="td-heading-self-link" href="#%d1%81%d1%82%d1%80%d0%be%d0%ba%d0%be%d0%b2%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85" aria-label="Heading self-link"></a></h3> -<p>Поддерживаются два типа строк, StrWide - символьные (широкие) и StrChar — байтовые. Различия между ними заключается в типе единичного элемента. -У символьных строк единичным элементом является широкий символ wchar_t, а у байтовой строки единичным элементом является один байт (точнее char, т. е. байт со знаком). -Символьные строки литералы в исходном тексте записывается в «двойных кавычках», а байтовые строки в &lsquo;одинарных кавычках&rsquo;.</p> -<p>Количество элементов символьной строки возвращается в широких символах, а размер байтовой строки в байтах, поэтому и обращение к элементу строки по индексу происходит соответственно либо к символу, либо к байту.</p> -<p>Важный момент. К любой переменной можно обратиться так же, как к функции (записав после её имени круглые скобки). -Результатом этой операции будет создание копии/клона объекта. Причем некоторые типы (словари, классы и символьные строки) можно использовать в качестве шаблона -при создании копии объекта с модифицированными свойствами, если новые и/или изменяемые значения указать в скобках, как аргументы при вызовах функций. -Так, если при создании копии в скобках указать набор новых данных, то результирующая копия будет содержать уже измененные данные.</p> -<p>Например:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#000">$template</span> :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#4e9a06">&#34;</span><span style="color:#4e9a06">${</span><span style="color:#000">name</span><span style="color:#4e9a06">}</span><span style="color:#4e9a06"> </span><span style="color:#000">$1</span><span style="color:#4e9a06">&#34;</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Обычная строка</span> -</span></span><span style="display:flex;"><span><span style="color:#000">$result</span> :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">$template</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;шаблон&#34;</span>, <span style="color:#000">name</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#4e9a06">&#34;Строка&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># result = &#34;Строка шаблон&#34;</span> -</span></span></code></pre></div><h3 id="составные-типы-данных">Составные типы данных:<a class="td-heading-self-link" href="#%d1%81%d0%be%d1%81%d1%82%d0%b0%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85" aria-label="Heading self-link"></a></h3> -<h4 id="словарь">Словарь<a class="td-heading-self-link" href="#%d1%81%d0%bb%d0%be%d0%b2%d0%b0%d1%80%d1%8c" aria-label="Heading self-link"></a></h4> -<p>Словарь — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии -(он похож и на tuple и на структуру одновременно). Словари от тензоров отличаются тем, что являются только одномерными массивами, -но каждый элемент может содержать произвольное количество элементов любого типа, в том числе и другие словари.</p> -<p>Доступ к элементам словарей происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. -Индекс также начинается с 0 и как у тензоров, тоже может быть отрицательным.</p> -<p>Литерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, -т.е. (,) - пустой словарь, (1, 2= «2», name=3,).</p> -<h3 id="перечисление">Перечисление<a class="td-heading-self-link" href="#%d0%bf%d0%b5%d1%80%d0%b5%d1%87%d0%b8%d1%81%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> -<p>Перечисление - это не отдельный тип данных, а обычный словарь, у которого все элементы имеют уникальные имена и целочисленные значение, -которое явно указывается при определении или вычисляется автоматически (на единицу больше предыдущего элемента). -У перечислений тип значения указывается сразу после закрывающей скобки через двоеточие (ONE=1, TWO=, THREE=): Int.</p> -<h4 id="классы">Классы<a class="td-heading-self-link" href="#%d0%ba%d0%bb%d0%b0%d1%81%d1%81%d1%8b" aria-label="Heading self-link"></a></h4> -<p>Класс (реализовано частично) - тип данных, с помощью которого реализуется один из принципов ООП - наследование. -При создании экземпляра класса создается новая переменная, у которой сохраняется информацию о своем родителе -и которая наследует от него свойства и методы. Тип данных «класс» аналогичен словарю, -но все свойства обязаны иметь имена (хотя доступ к свойствам класса по индексу так же возможен). -Литерал с типом «Класс» в тексте программы записывается в круглых скобках без завершающей запятой, т. е. () - пустой класс, (1, 2= «2», name=3).</p> -<p>Пока остальные детали классов до конца не реализованы, поэтому описывать их не буду, т. к. в итоговом варианте синтаксис классов и определения их методов могут поменяться.</p> -<h3 id="функции">Функции<a class="td-heading-self-link" href="#%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h3> -<p>Синтаксис NewLang поддерживать несколько типов функций (а в будущем и методов классов): обычные функции, чистые функции и простые чистые функции.</p> -<p>Для всех типов функций поддерживаются аргументы по умолчанию. При создании функции, её аргументы указываются как в Питоне, -т.е. вначале идут обязательные аргументы, потом аргументы со значениями по умолчанию, -где имя аргумента отделяется от его значения по умолчанию знаком равно «=». -Если функция допускает обработку произвольного количества аргументов, то последним в списке параметров указывается многоточие.</p> -<h4 id="обычная-функция">Обычная функция<a class="td-heading-self-link" href="#%d0%be%d0%b1%d1%8b%d1%87%d0%bd%d0%b0%d1%8f-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8f" aria-label="Heading self-link"></a></h4> -<p>Обычная функция — такие функции являются именно обычными функциями в понимании С/С++. -Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д.</p> -<p>Внутри обычной функции можно обращаться к локальным и глобальным объектам, и они могут содержаться вставки на языке реализации, например, для вызова функций из внешних библиотек.</p> -<p>Вставки на языке реализации оформляются в виде <strong>%{</strong> <strong>%}</strong> и могут содержать любой текст на С/С++, -а прямо из него можно обращаться к локальным и глобальным объектам NewLang так же, как и в обычном синтаксисе, -указывая первым символом имени соответствующий модификатор (<strong>$</strong> для локальных объектов и <strong>@</strong> для глобальных).</p> -<p>Технически, такая программная вставка просто переносится трансплайтером непосредственно в исходный текст генерируемого файла, -а все идентификаторы NewLang специальным образом декорируются (добавляются специальные маркеры для их идентификации), -после этого исходный текст подается на вход обычному компилятору С++. -Для локальных объектов трансплайтер может генерировать код для прямого доступа к объекту на этапе компиляции, -а для работы с глобальными объектами вынужден использовать runtime вызовы функции поиска в таблице символов.</p> -<p>Например:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#000">print</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">str</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">printf</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;%s&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">static_cast</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#204a87;font-weight:bold">const</span> <span style="color:#204a87;font-weight:bold">char</span> <span style="color:#ce5c00;font-weight:bold">*&gt;</span><span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">$</span><span style="color:#000">str</span><span style="color:#000;font-weight:bold">));</span> <span style="color:#8f5902;font-style:italic">/* Прямой вызов С функции */</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">};</span> -</span></span></code></pre></div><h4 id="чистые-функции">Чистые функции<a class="td-heading-self-link" href="#%d1%87%d0%b8%d1%81%d1%82%d1%8b%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h4> -<p>Чистая функция - это тоже обычная функция, только в том смысле, какой в него вкладывает функциональное программирование. -Создания чистой функции происходит с помощью оператора «:-». У чистой функции отсутствует доступ к контексту и глобальным объектам, -поэтому она может обрабатывать только те данные, которые были ей переданы в качестве аргументов.</p> -<p>Программные вставки на языке реализации внутри чистых функций не запрещены и могут использоваться, например, для отладки. -Но делается это на страх и риск разработчика. Именно он отвечает за их «чистоту», например при вызове функций из внешних библиотек.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> Sum<span style="color:#ce5c00;font-weight:bold">(</span>arg1, arg2<span style="color:#ce5c00;font-weight:bold">)</span> :- <span style="color:#ce5c00;font-weight:bold">{</span><span style="color:#000">$arg1</span>+<span style="color:#000">$arg2</span><span style="color:#000;font-weight:bold">;</span><span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Вернуть сумму аргументов</span> -</span></span></code></pre></div><p>Так как в языке отсутствует оператор возврата данных из текущего блока выполнения (аналог оператора return &lt;данные&gt;), -то возвращаемым значением функции / блока кода всегда является результат выполнения последней операции.</p> -<h4 id="простые-чистые-функции">Простые чистые функции<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%be%d1%81%d1%82%d1%8b%d0%b5-%d1%87%d0%b8%d1%81%d1%82%d1%8b%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h4> -<p>Простые чистые функции — отдельный класс чистых функций, которые предназначены только для вычисления логического результата -(т.е. они являются предикатами) и их отличает упрощенная формой записи. -Тело простой чистой функции состоит из последовательности операторов, которые разделяются запятыми и заканчиваются, -как и любое выражение, точкой с запятой. Все операторы простой чистой функции всегда приводятся к булевому значению, -а итоговый результат функции вычисляется по одной из возможных логических операций: <em>И</em>, <em>ИЛИ</em> и <em>исключающее ИЛИ</em>.</p> -<p>Например:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> func_and<span style="color:#ce5c00;font-weight:bold">(</span>arg1, arg2<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;=</span> <span style="color:#000">arg1</span><span style="color:#ce5c00;font-weight:bold">==</span>3, arg2 &gt; 0<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Простая чистая функция Логическое И</span> -</span></span><span style="display:flex;"><span> func_or<span style="color:#ce5c00;font-weight:bold">(</span>arg1, arg2<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">||=</span> <span style="color:#000">arg1</span><span style="color:#ce5c00;font-weight:bold">==</span>3, arg2 &gt; 0<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Простая чистая функция Логическое ИЛИ</span> -</span></span><span style="display:flex;"><span> func_xor<span style="color:#ce5c00;font-weight:bold">(</span>arg1, arg2<span style="color:#ce5c00;font-weight:bold">)</span> ^^<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">arg1</span><span style="color:#ce5c00;font-weight:bold">==</span>3, arg2 &gt; 0<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Простая чистая функция Исключающее ИЛИ</span> -</span></span></code></pre></div><h3 id="специальные-типы-данных">Специальные типы данных:<a class="td-heading-self-link" href="#%d1%81%d0%bf%d0%b5%d1%86%d0%b8%d0%b0%d0%bb%d1%8c%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85" aria-label="Heading self-link"></a></h3> -<h4 id="none">None<a class="td-heading-self-link" href="#none" aria-label="Heading self-link"></a></h4> -<p>None (пустой тип) — не содержит значения (точнее имеет одно значение None) и совместим с любым другим типом данных. -Указывается в тексте программы как один подчерк «_». Значение None имеют не инициализированные переменные -и при попытке чтения из такой переменной возникает ошибка.</p> -<p>Тип переменной может быть явно указан или выведен автоматически из присваиваемого значения. -Присвоить новое значение уже инициализированной переменной можно только для совместимого типа, так как неявное преобразование типов не допускаются.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#000">$var</span> :<span style="color:#ce5c00;font-weight:bold">=</span> _<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Создать переменную со значением None</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$var2</span> :<span style="color:#ce5c00;font-weight:bold">=</span> var<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Ошибка!!! Нельзя прочитать неинициализированную переменную var</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$var</span> <span style="color:#ce5c00;font-weight:bold">=</span> 1000<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># У переменной будет тип Short (минимальный размер для хранения значения)</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$var</span> <span style="color:#ce5c00;font-weight:bold">=</span> 0,5<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Ошибка!!! Short ← Float не совместимы</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$var</span> <span style="color:#ce5c00;font-weight:bold">=</span> _<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Очистить значение переменной</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$var</span> <span style="color:#ce5c00;font-weight:bold">=</span> 0,5<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Теперь можно, т. к. None совместим с любым типом</span> -</span></span></code></pre></div><h4 id="диапазон-range">Диапазон (Range)<a class="td-heading-self-link" href="#%d0%b4%d0%b8%d0%b0%d0%bf%d0%b0%d0%b7%d0%be%d0%bd-range" aria-label="Heading self-link"></a></h4> -<p>Диапазон (реализовано частично) — специальный тип данных, являющейся приблизительным аналогом типа «генератор» в Python. -К диапазону можно обращаться как к итератору и он будет поочередно выдавать элементы в указанном интервале с заданным шагом. -Диапазон в тексте программы указывается как два или три элемента через две точки, например 1..5 — диапазон от единицы до пяти с шагом по умолчанию 1. -В качестве параметров диапазона можно указывать не только литералы, но и имена переменных. -Например, 0,1..<em>$stop</em>..0,1 — диапазон от значения 0,1 до значения, указанного в переменной <em>$stop</em> с шагом 0,1.</p> -<p>Диапазон для целых чисел можно использовать в качестве индекса у тензоров (точнее, у любых объектов, которые допускают доступ к своим элементам по индексу, -т.е. тензоры, словари и текстовые строки). Фактический, это поведение аналогично slice в языке Python и array[1:5] -в Python означает тоже самое, что и array[1..5] в NewLang.</p> -<p>В качестве индекса у тензоров еще можно указать произвольное количество измерений с помощью многоточия, т.е.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#000">$tensor</span><span style="color:#ce5c00;font-weight:bold">[</span>…, 0<span style="color:#ce5c00;font-weight:bold">]</span> <span style="color:#ce5c00;font-weight:bold">=</span> 0<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Обнулить все первые элементы в каждом измерении.</span> -</span></span></code></pre></div><h4 id="итераторы">Итераторы<a class="td-heading-self-link" href="#%d0%b8%d1%82%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b" aria-label="Heading self-link"></a></h4> -<p>Итераторы (в разработке) - самый сложный и неоднозначный тип данных для работы с элементами коллекций.<br> -Для работы с итераторами зарезервированы символы &ldquo;!&rdquo; и &ldquo;?&rdquo;, но сами итераторы пока не реализованы.</p> -<h3 id="преобразование-типов">Преобразование типов<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b5%d0%be%d0%b1%d1%80%d0%b0%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d1%82%d0%b8%d0%bf%d0%be%d0%b2" aria-label="Heading self-link"></a></h3> -<h4 id="явное-приведение-типов">Явное приведение типов<a class="td-heading-self-link" href="#%d1%8f%d0%b2%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%b8%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5-%d1%82%d0%b8%d0%bf%d0%be%d0%b2" aria-label="Heading self-link"></a></h4> -<p>Несмотря на динамическую типизацию языка, если тип переменной указан явно, то автоматическое приведение типов не выполняется, -и чтобы присвоить переменой значение не совместимого типа, требуется явное преобразование.</p> -<p>Так как символьные названия типов относятся к деталям реализации, то явное преобразование в конкретный тип данных производится с помощью вызова функции с системным именем, -т. е. Bool(), StrWide(), Long и т. д. Причем у тензоров при таком преобразовании изменяется только тип данных, но размерность тензора не меняется.</p> -<p>Для преобразования любого типа данных в строку ещё можно использовать оператор конкатенации строк, которой преобразует любой тип данных в строковое представление. -Но так как строковых типов два (байтовые и широкие строки), то тип строки определяется первым аргументом в операторе конкатенации, т. е.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#4e9a06">&#34;&#34;</span> ++ <span style="color:#0000cf;font-weight:bold">123</span> <span style="color:#8f5902;font-style:italic"># &#34;123&#34; - Строка широких символов</span> -</span></span><span style="display:flex;"><span> <span style="color:#4e9a06">&#39;&#39;</span> ++ <span style="color:#0000cf;font-weight:bold">123</span> <span style="color:#8f5902;font-style:italic"># &#39;123&#39; - Байтовая строка</span> -</span></span></code></pre></div><pre><code>Или преобразовать любое значение в строковое с помощью строки-шаблона: -</code></pre> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> val :<span style="color:#ce5c00;font-weight:bold">=</span> 12345<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#4e9a06">&#34;</span><span style="color:#000">$1</span><span style="color:#4e9a06">&#34;</span><span style="color:#ce5c00;font-weight:bold">(</span>val<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#8f5902;font-style:italic"># Будет строка &#34;12345&#34;</span> -</span></span></code></pre></div><h4 id="tensor-comprehensions">Tensor comprehensions<a class="td-heading-self-link" href="#tensor-comprehensions" aria-label="Heading self-link"></a></h4> -<p>В эпоху машинного обучения тензоры являются основным элементом вычислений, поэтому для конвертирования <em>данных</em> в тензоры используется отдельная синтаксическая конструкция, -состоящая из двойных квадратных скобок <strong>[[</strong> <em>данные</em> <strong>]]</strong>. Фактически это оператор и функция времени выполнения в зависимости от указанных между двойные квадратными скобками выражения.</p> -<p>Чтобы преобразовать любую переменную в тензор (с учетом допустимости такого преобразования), её достаточно указать между двойными квадратными скобками. -Выражение <strong>[[</strong> <em>varibale</em> <strong>]]</strong> - преобразует переменную <em>varibale</em> в одномерный тензор с автоматическим выводом типа данных. -Для преобразования в одномерный тензор конкретного типа используется выражение <strong>[[</strong> <em>varibale</em> <strong>]]</strong>:<em>Type</em>, где _Type- - любой из арифметических типов.</p> -<p>Если требуется преобразовать переменную не в одномерный тензор, а в тензор конкретного типа и заданной размерности, -то это делается выражением [[ varibale ]]:Type[2,2], которая вернет тензор с размерностью 2х2 и типом Type у элементов.</p> -<p>Внутри двойных квадратных скобок может быть не только любое выражение, но и литерал или диапазон. -В этом случае, они также раскрываются в тензор по таким же правилам.<br> -В будущем планирую добавить возможность указания сразу нескольких значений через запятую для их объединения в один тензор.</p> -<p>Примеры:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#000;font-weight:bold">[[(</span><span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">,</span><span style="color:#0000cf;font-weight:bold">2</span><span style="color:#000;font-weight:bold">,</span><span style="color:#0000cf;font-weight:bold">3</span><span style="color:#000;font-weight:bold">)]]</span> <span style="color:#8f5902;font-style:italic"># Тензор из словаря</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">2</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">3</span><span style="color:#000;font-weight:bold">,]:</span><span style="color:#000">Char</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#000;font-weight:bold">[[</span><span style="color:#4e9a06">&#39;first second&#39;</span><span style="color:#000;font-weight:bold">]]</span> <span style="color:#8f5902;font-style:italic"># Байтовая строка в тензор</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">102</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">105</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">114</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">115</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">116</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">32</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">115</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">101</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">99</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">111</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">110</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">100</span><span style="color:#000;font-weight:bold">,]:</span><span style="color:#000">Char</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000;font-weight:bold">[[(</span><span style="color:#000">first</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#4e9a06">&#39;first&#39;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">space</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#0000cf;font-weight:bold">32</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">second</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#4e9a06">&#39;second&#39;</span><span style="color:#000;font-weight:bold">)]]</span> <span style="color:#8f5902;font-style:italic"># Получаем тензор из словаря с такими же данными</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">102</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">105</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">114</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">115</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">116</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">32</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">115</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">101</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">99</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">111</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">110</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">100</span><span style="color:#000;font-weight:bold">,]:</span><span style="color:#000">Char</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#000;font-weight:bold">[[</span> <span style="color:#0000cf;font-weight:bold">0</span> <span style="color:#ce5c00;font-weight:bold">...</span> <span style="color:#000;font-weight:bold">]]:</span><span style="color:#000">Double</span><span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">10</span><span style="color:#000;font-weight:bold">,</span><span style="color:#0000cf;font-weight:bold">2</span><span style="color:#000;font-weight:bold">]</span> <span style="color:#8f5902;font-style:italic"># Тензор заданного формата с нулями</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">[</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,],</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">]:</span><span style="color:#000">Double</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#000;font-weight:bold">[[</span> <span style="color:#000">rand</span><span style="color:#000;font-weight:bold">()</span> <span style="color:#ce5c00;font-weight:bold">...</span> <span style="color:#000;font-weight:bold">]]:</span> <span style="color:#000">Int</span><span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">3</span><span style="color:#000;font-weight:bold">,</span><span style="color:#0000cf;font-weight:bold">2</span><span style="color:#000;font-weight:bold">]</span> <span style="color:#8f5902;font-style:italic"># Тензор со случайными данными</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">[</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">1804289383</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">846930886</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">1681692777</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">1714636915</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">1957747793</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">424238335</span><span style="color:#000;font-weight:bold">,],</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">]:</span><span style="color:#000">Int</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#000;font-weight:bold">[[</span> <span style="color:#0000cf;font-weight:bold">0..10</span> <span style="color:#000;font-weight:bold">]]:</span> <span style="color:#000">Int</span><span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">5</span><span style="color:#000;font-weight:bold">,</span><span style="color:#0000cf;font-weight:bold">2</span><span style="color:#000;font-weight:bold">]</span> <span style="color:#8f5902;font-style:italic"># Тензор из диапзона</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">[</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">2</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">3</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">4</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">5</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">6</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">7</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">8</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">9</span><span style="color:#000;font-weight:bold">,],</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">]:</span><span style="color:#000">Int</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#000;font-weight:bold">[[</span> <span style="color:#0000cf;font-weight:bold">0..0.99</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#0000cf;font-weight:bold">.0.1</span> <span style="color:#000;font-weight:bold">]]</span> <span style="color:#8f5902;font-style:italic"># Или даже так</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0.1</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0.2</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0.3</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0.4</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0.5</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0.6</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0.7</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0.8</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0.9</span><span style="color:#000;font-weight:bold">,]:</span><span style="color:#000">Double</span><span style="color:#ce5c00;font-weight:bold">&lt;/</span><span style="color:#000">source</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> -</span></span></code></pre></div><h2 id="операторы-и-управляющие-конструкции">Операторы и управляющие конструкции<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d0%b8-%d1%83%d0%bf%d1%80%d0%b0%d0%b2%d0%bb%d1%8f%d1%8e%d1%89%d0%b8%d0%b5-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h2> -<h4 id="операторы">Операторы:<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b" aria-label="Heading self-link"></a></h4> -<p>Все операторы имеют парный оператор с присвоением значения.</p> -<ul> -<li><strong>+</strong> и += сложение арифметических типов данных</li> -<li> -<ul> -<li>и -= вычитание арифметических типов данных</li> -</ul> -</li> -<li>/ и /= деление (результат число с плавающей точкой)</li> -<li>// и //= целочисленное деление с округлением к меньшему числу (как в Python)</li> -<li> -<ul> -<li>и *= умножение</li> -</ul> -</li> -<li>** и **= возведение в степень (он же используется и для повторения текстовых строк)</li> -<li>++ и ++= конкатенация строк с автоматическим приведением аргументов к стоковому типу (символ инкремента специально используется вместо одиночного плюса для того, чтобы в явном виде разделить конкатенацию строк и операторы арифметического сложения)</li> -</ul> -<h4 id="операторы-сравнения">Операторы сравнения:<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d1%81%d1%80%d0%b0%d0%b2%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h4> -<ul> -<li>&lt;, &gt;, &lt;=, &gt;= классические для сравнения скаляров</li> -<li>==, != операторы сравнения с автоматическим приведением совместимых типов для любых объектов</li> -<li>===, !== оператор точного сравнения для любых объектов (автоматического приведения типов не выполняется)s</li> -</ul> -<h3 id="проверки-типов--в-разработке">Проверки типов (в разработке):<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b8-%d1%82%d0%b8%d0%bf%d0%be%d0%b2--%d0%b2-%d1%80%d0%b0%d0%b7%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b5" aria-label="Heading self-link"></a></h3> -<p>Проверка имени класса «~» - немного похож на оператор instanceof в Java. -Левым оператором должен быть проверяемый объект, а правым оператором - название типа, строка литерал или объект строкового типа с именем класса. -Результатом операции будет истина, если правый операнд содержит название класса проверяемого объекта или он присутствует в иерархии наследования у проверяемого класса.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> name :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#4e9a06">&#34;class&#34;</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Строка с именем класса</span> -</span></span><span style="display:flex;"><span> var ~ :class<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> var ~ <span style="color:#4e9a06">&#34;class&#34;</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> var ~ name<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">field1</span><span style="color:#ce5c00;font-weight:bold">=</span>«value», <span style="color:#000">field2</span><span style="color:#ce5c00;font-weight:bold">=</span>2, <span style="color:#000">field3</span><span style="color:#ce5c00;font-weight:bold">=</span>«33»,<span style="color:#ce5c00;font-weight:bold">)</span> ~~ <span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Истина (т. е. левый операнд словарь)</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">field1</span><span style="color:#ce5c00;font-weight:bold">=</span>«value», <span style="color:#000">field2</span><span style="color:#ce5c00;font-weight:bold">=</span>2, <span style="color:#000">field3</span><span style="color:#ce5c00;font-weight:bold">=</span>«33»,<span style="color:#ce5c00;font-weight:bold">)</span> ~~ <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">field1</span><span style="color:#ce5c00;font-weight:bold">=</span>_<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Тоже истина (т. к. поле field1 присутствует у левого операнда)</span> -</span></span></code></pre></div><p>Утиная типизация «~~» - приблизительный аналог функции isinstance() в Python, который для простых типов сравнивает совместимость типа левого операнда по отношению к правому, а для словарей и классов в левом операнде проверяется наличие всех имен полей, присутствующих у правого операнда. т. е.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">field1</span><span style="color:#ce5c00;font-weight:bold">=</span>«value», <span style="color:#000">field2</span><span style="color:#ce5c00;font-weight:bold">=</span>2, <span style="color:#000">field3</span><span style="color:#ce5c00;font-weight:bold">=</span>«33»,<span style="color:#ce5c00;font-weight:bold">)</span> ~~ <span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Истина (т. е. левый операнд словарь)</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">field1</span><span style="color:#ce5c00;font-weight:bold">=</span>«value», <span style="color:#000">field2</span><span style="color:#ce5c00;font-weight:bold">=</span>2, <span style="color:#000">field3</span><span style="color:#ce5c00;font-weight:bold">=</span>«33»,<span style="color:#ce5c00;font-weight:bold">)</span> ~~ <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">field1</span><span style="color:#ce5c00;font-weight:bold">=</span>_<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Тоже истина (т. к. поле field1 присутствует у левого операнда)</span> -</span></span></code></pre></div><p>Строгая утиная типизация «~~~» - для простых типов сравнивается идентичности типов без учета совместимости, -а для составных типов происходит строгое сравнение всех свойств. Для данной операции, пустой тип совместим только с другим пустим типом!</p> -<h2 id="управляющие-конструкции-в-разработке">Управляющие конструкции (в разработке)<a class="td-heading-self-link" href="#%d1%83%d0%bf%d1%80%d0%b0%d0%b2%d0%bb%d1%8f%d1%8e%d1%89%d0%b8%d0%b5-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%86%d0%b8%d0%b8-%d0%b2-%d1%80%d0%b0%d0%b7%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b5" aria-label="Heading self-link"></a></h2> -<h3 id="условный-оператор">Условный оператор<a class="td-heading-self-link" href="#%d1%83%d1%81%d0%bb%d0%be%d0%b2%d0%bd%d1%8b%d0%b9-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80" aria-label="Heading self-link"></a></h3> -<p>В качестве оператора проверки условия используется синтаксическая конструкция, соответствующая по смыслу термину «следует», -т.е. тире и угловая скобка «-&gt;». Такая запись условного оператора очень похожа на математическую и легко объединяется в последовательности для проверки множественных условий вида «else if».</p> -<p>В общем случае условный оператор имеет вид:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> условие -&gt; действие<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> или -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span>условие<span style="color:#ce5c00;font-weight:bold">)</span> -&gt; <span style="color:#ce5c00;font-weight:bold">{</span>действие<span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> или -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span>условие1 <span style="color:#ce5c00;font-weight:bold">||</span> условие2<span style="color:#ce5c00;font-weight:bold">)</span> -&gt; <span style="color:#ce5c00;font-weight:bold">{</span>действие<span style="color:#ce5c00;font-weight:bold">}</span> -&gt; <span style="color:#ce5c00;font-weight:bold">{</span>действие иначе<span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>Или расширенный вариант «else if», для наглядности записанный с отступами:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span>условие1<span style="color:#ce5c00;font-weight:bold">)</span> -&gt; <span style="color:#ce5c00;font-weight:bold">{</span>действие1<span style="color:#ce5c00;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span>условие2<span style="color:#ce5c00;font-weight:bold">)</span> -&gt; <span style="color:#ce5c00;font-weight:bold">{</span>действие2<span style="color:#ce5c00;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span>условие3<span style="color:#ce5c00;font-weight:bold">)</span> -&gt; <span style="color:#ce5c00;font-weight:bold">{</span>действие3<span style="color:#ce5c00;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> -&gt; <span style="color:#ce5c00;font-weight:bold">{</span>действие_иначе<span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><h3 id="операторы-циклов-в-планах">Операторы циклов (в планах)<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d1%86%d0%b8%d0%ba%d0%bb%d0%be%d0%b2-%d0%b2-%d0%bf%d0%bb%d0%b0%d0%bd%d0%b0%d1%85" aria-label="Heading self-link"></a></h3> -<p><em>Операторы циклов пока в разработке , т. к. плотно связаны с итераторами.</em></p> -<p>Пока планирую для циклов использовать конструкции: (условие) <strong>&lt;&ndash;&gt;</strong> {тело цикла};</p> -<p>Или так: (условие) <strong>-&raquo;</strong> {тело цикла};</p> -<p>И хотя синтаксис мне не очень нравится, но я решил пока не ломать над этим голову и планирую попробовать несколько вариантов оформления циклов.</p> -<h4 id="операторы-прерывания-потока-выполнения-команд-реализовано-частично">Операторы прерывания потока выполнения команд (реализовано частично)<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d0%bf%d1%80%d0%b5%d1%80%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%bf%d0%be%d1%82%d0%be%d0%ba%d0%b0-%d0%b2%d1%8b%d0%bf%d0%be%d0%bb%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%ba%d0%be%d0%bc%d0%b0%d0%bd%d0%b4-%d1%80%d0%b5%d0%b0%d0%bb%d0%b8%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%be-%d1%87%d0%b0%d1%81%d1%82%d0%b8%d1%87%d0%bd%d0%be" aria-label="Heading self-link"></a></h4> -<p>Оператором прерывания потока выполнения команд и возврата из текущей функции, т.е. самым близким аналогом оператора return<br> -является оператор два символа минус «&ndash;». Но в отличие от классического return, оператор возврата не возвращает значения, -т.к. значение из любой функции или блока кода возвращается всегда и им является результат выполнения самой последней операции -(или None, если такая операция отсутствует).</p> -<p>Пока не придумал, как оформлять оператор прерывания потока выполнения в случае ошибки (при его выполнении будет происходить генерация исключения), -поэтому, если будут предложения, пишите в комментариях к статье (и про оформление циклов тоже).</p> -<h3 id="обработка-ошибок-в-планах">Обработка ошибок (в планах)<a class="td-heading-self-link" href="#%d0%be%d0%b1%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b0-%d0%be%d1%88%d0%b8%d0%b1%d0%be%d0%ba-%d0%b2-%d0%bf%d0%bb%d0%b0%d0%bd%d0%b0%d1%85" aria-label="Heading self-link"></a></h3> -<p>В самом начале работ я ориентировался на классический вариант обработки исключений, -который в обычных языках программирования обычно оформляется ключевыми словами <em>try</em> .. <em>catch</em> .. <em>finally</em> с различными вариациями. -Но в условиях жестких ограничений на синтаксис языка, и невозможности использовать ключевые слова, -комбинировать символы для указания разных типов блоков при обработке исключений, было бы крайне сомнительной затеей. -Ведь основная цель разработки NewLang — простота и понятность кода, а тут с самого начала могут появиться комбинации скобочек, стрелочек, -палочек и других подобных символов.</p> -<p>И тут в голову пришла очень простая мысль. А ненужно повторять логику обработки ошибок из классических языков программирования! -Ведь основная цель подобных синтаксических конструкций - выделить участок кода где возможно возникновение ошибки, -перехватить и обработать правильный тип исключения. -Ведь классические языки программирования изначально были жестко привязаны к машинному представлению данных в оперативной памяти компьютера -и тип данных для них играл принципиально важное значение. -Но это не является ограничением для языков с динамической типизацией!</p> -<p>Поэтому, подход к обработке исключений планируется следующий: Программный код, который может привести к ошибке, заключается в двойные фигурные скобки -<strong>{{</strong> <i>любой код или вызов одиночной функции</i> <strong>}}</strong>, -а результат выполнения такого блока кода присваивается переменной. После этого анализируется возвращенное значение и тип исключения может обрабатываться обычным условным оператором.</p> -<p>Наверно, это проще показать на примере:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#000">$error</span> :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">{{</span> <span style="color:#8f5902;font-style:italic"># начало блока try</span> -</span></span><span style="display:flex;"><span> call_or_exception1<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> call_or_exception2<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}}</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># конец блока try</span> -</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Обычные условные операторы вместо типизированных блоков catch</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">$error</span> ~ :type1<span style="color:#ce5c00;font-weight:bold">)</span>-&gt;<span style="color:#ce5c00;font-weight:bold">{</span> код обработки ошибки 1<span style="color:#ce5c00;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">$error</span> ~ :type2<span style="color:#ce5c00;font-weight:bold">)</span>-&gt;<span style="color:#ce5c00;font-weight:bold">{</span> код обработки ошибки 2<span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>Самое удивительное, что при таком подходе значительно упрощается и семантика блоков <em>try</em> <strong>…</strong> <em>finally</em>, которые вообще становятся не нужны.</p> -<p>Исходный код на Java:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">try</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">{</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">try</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">{</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">throw</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">new</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">Exception</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;a&#34;</span><span style="color:#000;font-weight:bold">);</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">}</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">finally</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">{</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">throw</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">new</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">IOException</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;b&#34;</span><span style="color:#000;font-weight:bold">);</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">}</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">}</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">catch</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">IOException</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">ex</span><span style="color:#000;font-weight:bold">)</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">{</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">System</span><span style="color:#000;font-weight:bold">.</span><span style="color:#c4a000">err</span><span style="color:#000;font-weight:bold">.</span><span style="color:#c4a000">println</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">ex</span><span style="color:#000;font-weight:bold">.</span><span style="color:#c4a000">getMessage</span><span style="color:#000;font-weight:bold">());</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">}</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">catch</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">Exception</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">ex</span><span style="color:#000;font-weight:bold">)</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">{</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">System</span><span style="color:#000;font-weight:bold">.</span><span style="color:#c4a000">err</span><span style="color:#000;font-weight:bold">.</span><span style="color:#c4a000">println</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">ex</span><span style="color:#000;font-weight:bold">.</span><span style="color:#c4a000">getMessage</span><span style="color:#000;font-weight:bold">());</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">}</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span></code></pre></div><p>Эквивалентный ему на NewLang:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#000">$catch</span> :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">{{</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$finally</span> :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">{{</span> -</span></span><span style="display:flex;"><span> Error1<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;1&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}}</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Error2<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;2&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Строка выполнится даже при возникновении исключении Error1</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$finally</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Error1 вернется, если не будет Error2</span> -</span></span><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">}}</span> -</span></span><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">$catch</span> ~ :Error1<span style="color:#ce5c00;font-weight:bold">)</span> -&gt; printf<span style="color:#ce5c00;font-weight:bold">(</span>«%s», <span style="color:#000">$catch</span><span style="color:#ce5c00;font-weight:bold">)</span> -</span></span><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">$catch</span> ~ :Error2<span style="color:#ce5c00;font-weight:bold">)</span> -&gt; printf<span style="color:#ce5c00;font-weight:bold">(</span>«%s», <span style="color:#000">$catch</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><h2 id="как-все-это-попробовать">Как все это попробовать?<a class="td-heading-self-link" href="#%d0%ba%d0%b0%d0%ba-%d0%b2%d1%81%d0%b5-%d1%8d%d1%82%d0%be-%d0%bf%d0%be%d0%bf%d1%80%d0%be%d0%b1%d0%be%d0%b2%d0%b0%d1%82%d1%8c" aria-label="Heading self-link"></a></h2> -<p>Сейчас сборка проекта реализована только под Linux и если кроме текстового описания захочется в живую поэкспериментировать на своей машине, то придется собрать интерпретатор из исходников самостоятельно.</p> -<p>Так как текущий вариант предназначен первую очередь для отработки концепции, то часть из описанных возможностей пока не реализована (алгоритмические конструкции, наследование классов, итераторы, некоторые операции и т. д).</p> -<p>Но можно поиграться с созданием переменных, вызовом функций и выполнением арифметических операций над данными, чтобы оценить синтаксис, основанный на правилах, и может быть, предложить свои собственные мысли и доработки для его улучшения.</p> -<h3 id="сборка-repl-из-исходников-пока-только-под-linux">Сборка REPL из исходников (пока только под Linux)<a class="td-heading-self-link" href="#%d1%81%d0%b1%d0%be%d1%80%d0%ba%d0%b0-repl-%d0%b8%d0%b7-%d0%b8%d1%81%d1%85%d0%be%d0%b4%d0%bd%d0%b8%d0%ba%d0%be%d0%b2-%d0%bf%d0%be%d0%ba%d0%b0-%d1%82%d0%be%d0%bb%d1%8c%d0%ba%d0%be-%d0%bf%d0%be%d0%b4-linux" aria-label="Heading self-link"></a></h3> -<h4 id="подготовка-репозитория">Подготовка репозитория<a class="td-heading-self-link" href="#%d0%bf%d0%be%d0%b4%d0%b3%d0%be%d1%82%d0%be%d0%b2%d0%ba%d0%b0-%d1%80%d0%b5%d0%bf%d0%be%d0%b7%d0%b8%d1%82%d0%be%d1%80%d0%b8%d1%8f" aria-label="Heading self-link"></a></h4> -<ul> -<li>Скачать <a href="https://github.com/rsashka/newlang">исходники</a></li> -<li>Скачать и развернуть архив libtorch в каталоге contrib (PyTorch Build: Stable (1.10.*) -&gt; Your OS: Linux -&gt; Package: LibTorch -&gt; Language: C++ / Java -&gt; Compute Platform: CPU -&gt; Download here (cxx11 ABI): libtorch-cxx11-abi-shared-with-deps-1.10.2+cpu.zip)</li> -<li>Активировать и скачать исходники субмодулей (git submodule init &amp;&amp; git submodule update)</li> -<li>В каталоге <em>contrib</em> запустить файл <em>build.sh</em> для сборки библиотеки libffi</li> -<li>В каталоге <em>core</em> запустить файл <em>compile_syntax.sh</em> для генерации файлов парсера и лексического анализатора. Может потребоваться установка утилит flex и bison. Если что, у меня установлены flex 2.6.4 и bison (GNU Bison) 3.7.4</li> -</ul> -<h4 id="собрать">Собрать<a class="td-heading-self-link" href="#%d1%81%d0%be%d0%b1%d1%80%d0%b0%d1%82%d1%8c" aria-label="Heading self-link"></a></h4> -<ul> -<li>Юнит-тесты (newlang_test): в каталоге core выполнить команду <em>make CONF=UnitTest</em></li> -<li>Интерпретатор (nlc): в каталоге core выполнить команду <em>make CONF=Debug</em></li> -</ul> -<h2 id="утилита-nlc-newlangcompiler">Утилита nlc (NewLangCompiler)<a class="td-heading-self-link" href="#%d1%83%d1%82%d0%b8%d0%bb%d0%b8%d1%82%d0%b0-nlc-newlangcompiler" aria-label="Heading self-link"></a></h2> -<p>В текущее время nlc поддерживать работу только в режиме интерпретатора (несмотря на название). -Для тестирования и простой проверки компилятор не нужен, хотя на первых порах я делал именно его. -Но трудоемкость работ по постоянной переделке под новый синтаксис оказалась очень высокой, поэтому на время первичной отладки языковых конструкций было принято волевое решение ограничиться интерпретатором, -как более простым и быстрым способом проверки различных гипотез, а разработку настоящего компилятора (в виде трансплайтера на язык С++), -отложить до окончательной проработки синтаксиса.</p> -<h2 id="планы-на-будущее">Планы на будущее<a class="td-heading-self-link" href="#%d0%bf%d0%bb%d0%b0%d0%bd%d1%8b-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5" aria-label="Heading self-link"></a></h2> -<p>Естественное, одна статья и несколько маленьких примеров не дают исчерпывающей информации о возможностях языка. -Да и сами возможности пока не раскрыты в полной мере. -Ведь текущая версия, это скорее тестовая платформа для проверки декларируемых концепций и основного синтаксиса.</p> -<p>Пока остаются не реализованными некоторые из заявленных возможностей и очень важных хотелок. -Но протестировать основной подход можно уже сейчас, и я буду благодарен за любую обратную связь и предложения.</p> -<p>Если говорить о планах (естественно, в будущих версиях что-то может добавиться или измениться порядок их реализации), но в настоящий момент роадмап развития NewLang мне видится следующим образом:</p> -<ul> -<li>Доделать стандартные управляющие конструкции, обработку ошибок и итераторы.</li> -<li>Доработать систему типов с учетом множественного наследования классов.</li> -<li>Реализовать длинную арифметику и дроби.</li> -<li>Сделать какую нибудь логическую игру (крестики нолики, судоку или что-то похожее) с алгоритмическим выбором следующего хода и его вычислением с помощью машинного обучения.</li> -<li>Написать много разных примеров для оценки синтаксиса.</li> -<li>Доработать синтаксис с учетом полученного опыта и обратной связи.</li> -<li>Восстановить работоспособность компилятора для генерации исполняемых файлов.</li> -<li>Сделать очередную большую чистку кода.</li> -<li>Переработать и задокументировать получившуюся семантику языка с учетом всех возможностей и выпустить первую полнофункциональную версию NewLang.</li> -</ul> -<p><a href="https://habr.com/companies/timeweb/articles/651999/">Ссылка на первую публикаци</a></p> - - - - - - Blog: Можно ли использовать декларативный и императивный стили написания программ одновременно? - http://localhost:1313/blog/prog-styles-same-time/ - Mon, 26 Jul 2021 00:00:00 +0000 - - http://localhost:1313/blog/prog-styles-same-time/ - - - - <p><img alt="КДПВ" src="http://localhost:1313/blog/matrix.jpeg"></p> - - -<div class="pageinfo pageinfo-primary"> -<p>Внимание!!!</p> -<p>Данная статья содержит описание синтаксиса NewLnag предыдущей версии.</p> -<p>Актуальную версию синтаксиса языка можно посмотреть <a href="http://localhost:1313/docs/">тут</a>.</p> - -</div> - -<p>При разработке своего собственного языка программирования автор должен определиться, какими свойствами его язык должен обладать, -ведь в конечном итоге именно это и будет определять назначение языка и особенности его использования. -Причем некоторые свойства настолько сильно влияют на итоговую концепцию языка и его синтаксис, -что впоследствии их изменение невозможно в принципе, либо новый синтаксис получается очень запутанным и непонятным. -Наверно из-за этого многие свойства языков программирования рассматриваются и изучаются как взаимоисключающие.</p> -<p>До недавнего времени я считал, что императивная и декларативная парадигмы написания программ являются антагонистами и взаимоисключающими понятиями. -Ведь выбор стиля написания кода, изначально определяется автором языка еще на стадии его проектирования и оказывает влияние на все последующие аспекты.</p> -<p>Но сейчас я думаю, что это не верно. Императивный и декларативный стили программирования не являются взаимоисключающими, -а писать программы только в одной из указанных парадигм подталкивают правила синтаксиса, реализованные в языке!</p> -<p>Другими словами, использовать только императивную или только декларативную парадигмы разработчик вынужден не потому, что он не умеет или не хочет писать код по другому, а из-за того, -что все более-менее мейнстримные языки программирования ориентированы на использование только одной парадигмы. -И выбор только одной парадигмы написания кода, это ограничение, которое навязано программистам создателями языка. -Ведь если они изначально ориентировались только на одну концепцию разработки кода, то и разрабатывали синтаксис языка в соответствии с этой парадигмой.</p> -<p>Данная статья — размышление о совместимости декларативной и императивной парадигм программирования и возможности их одновременного использования в рамках одного языка программирования одновременно.</p> -<h2 id="что-такое-декларативное-программирование">Что такое &ldquo;Декларативное программирование&rdquo;?<a class="td-heading-self-link" href="#%d1%87%d1%82%d0%be-%d1%82%d0%b0%d0%ba%d0%be%d0%b5-%d0%b4%d0%b5%d0%ba%d0%bb%d0%b0%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h2> -<p>Вначале мне захотелось разобраться, а существуют ли чисто декларативные языки программирования? -Такие, которые могут полностью обходятся без императивных конструкций?</p> -<p>Но чуть не споткнулся уже в самом начале, т.к. даже само определение «декларативное программировании», в вики описывается <a href="https://ru.wikipedia.org/wiki/%D0%94%D0%B5%D0%BA%D0%BB%D0%B0%D1%80%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5">следующим образом</a>:</p> -<blockquote> -<p>Декларати́вное программи́рование — парадигма программирования, в которой задаётся спецификация решения задачи, то есть описывается, что представляет собой проблема и ожидаемый результат. Противоположностью декларативного является императивное программирование, описывающее на том или ином уровне детализации, как решить задачу и представить результат.</p> -</blockquote> -<p>Уже в изначальном определении закладывается противопоставление парадигм, а дальше идут рассуждения о «направлении» программирования. -И хоть вики сама и не является авторитетным источником информации, но даже такая заготовка статьи смогла показать направление поиска ответов на первый поставленный вопрос.</p> -<p>И заставил задуматься один абзац в конце статьи следующего содержания:</p> -<blockquote> -<p>«Чисто декларативные» компьютерные языки зачастую неполны по Тьюрингу — так как теоретически не всегда возможно порождение исполняемого кода по декларативному описанию. -Это иногда приводит к спорам о корректности термина «декларативное программирование» (менее спорным является «декларативное описание решения» или, что то же самое, «декларативное описание задачи»).</p> -</blockquote> -<p>Судя по наличию такой оговорки, ставится под сомнение наличие «чисто декларативных» языков. -И как только пришлось задуматься над это мыслью, то сразу стало очевидным, что какой бы декларативный язык программирования не существовал, -то в нем должна быть как минимум одна императивная конструкция, которая будет запускать поиск решения! -Ведь любой синоним слова «выполнить» или «запустить» по определению будет императивом!</p> -<p>Например в языке Prolog, который обычно и приводят в качестве примера декларативного языка программирования, &ldquo;замаскированным&rdquo; императивным оператором является знак вопроса. -Он кажется естественным и логичным, как же без него? Но по своей сути, это императивная конструкция!</p> -<p>Тоже самое касается и языка SQL. Он тоже как бы декларативный, но неожиданно все его команды являются императивными по сути. <em>SELECT</em>, <em>CREATE</em>, <em>ALTER</em>, <em>DROP</em>, <em>INSERT</em>, <em>UPDATE</em>, <em>DELETE</em> и т. д., а декларативными являются только описания условий их выполнения!</p> -<p>В результате, у меня так и не получилось найти чисто-декларативный язык программирования без императивных операторов (может быть, Вики права и такого языка программирования и вовсе не существует?).</p> -<h2 id="а-что-отличает-декларативные-языки-программирования-от-императивных">А что отличает декларативные языки программирования от императивных?<a class="td-heading-self-link" href="#%d0%b0-%d1%87%d1%82%d0%be-%d0%be%d1%82%d0%bb%d0%b8%d1%87%d0%b0%d0%b5%d1%82-%d0%b4%d0%b5%d0%ba%d0%bb%d0%b0%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b5-%d1%8f%d0%b7%d1%8b%d0%ba%d0%b8-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%be%d1%82-%d0%b8%d0%bc%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d1%85" aria-label="Heading self-link"></a></h2> -<p>Согласно определению, декларативными языками программирования их называют из-за возможности записать некие условия в декларативном стиле. -Но кроме этого, в декларативных языках как правило присутствует и некий внутренний механизм поиска решений. -Подобный &ldquo;вычислитель&rdquo; есть и в SQL и Prolog и во многих других декларативных языках.</p> -<p>Интересно, а является ли внутренняя система поиска решений обязательным признаком декларативного стиля программирования или это только особенность конкретного языка программирования, которая не зависит от декларативного стиля написания кода?</p> -<p>Чтобы проверить данные предположения, можно было попробовать написать классическую декларативную программу на императивном языке, у которого отсутствует внутренний механизм поиска решений.</p> -<p>А заодно, таким образом можно будет и изучить вопрос, получится ли написать программу в декларативном стиле используя обычный императивный язык программирования?</p> -<p>Для примера, решил попробовать повторить уже классическую программу в декларативном стиле на Прологе.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span> <span style="color:#000">parent</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Tom&#34;</span><span style="color:#000;font-weight:bold">,</span><span style="color:#4e9a06">&#34;Jake&#34;</span><span style="color:#000;font-weight:bold">).</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">parent</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Janna&#34;</span><span style="color:#000;font-weight:bold">,</span><span style="color:#4e9a06">&#34;Jake&#34;</span><span style="color:#000;font-weight:bold">).</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">parent</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Tom&#34;</span><span style="color:#000;font-weight:bold">,</span><span style="color:#4e9a06">&#34;Tim&#34;</span><span style="color:#000;font-weight:bold">).</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">male</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Tom&#34;</span><span style="color:#000;font-weight:bold">).</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">male</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Tim&#34;</span><span style="color:#000;font-weight:bold">).</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">male</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Jake&#34;</span><span style="color:#000;font-weight:bold">).</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">female</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Janna&#34;</span><span style="color:#000;font-weight:bold">).</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#000">brother</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">X</span><span style="color:#000;font-weight:bold">,</span><span style="color:#000">Y</span><span style="color:#000;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">:-</span><span style="color:#000">parent</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">Z</span><span style="color:#000;font-weight:bold">,</span><span style="color:#000">X</span><span style="color:#000;font-weight:bold">),</span><span style="color:#000">parent</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">Z</span><span style="color:#000;font-weight:bold">,</span><span style="color:#000">Y</span><span style="color:#000;font-weight:bold">),</span><span style="color:#000">male</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">X</span><span style="color:#000;font-weight:bold">),</span><span style="color:#000">male</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">Y</span><span style="color:#000;font-weight:bold">),</span><span style="color:#000">X</span><span style="color:#a40000">\</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#000">Y</span><span style="color:#000;font-weight:bold">.</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">?</span> <span style="color:#000">brother</span> -</span></span></code></pre></div><p>Получилась вот такая функционально - эквивалентная программа на С++, которая максимально приближена по стилю к декларативному прототипу:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">enum</span> <span style="color:#000">sex_</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">male</span><span style="color:#000;font-weight:bold">,</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">female</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">struct</span> <span style="color:#000">human</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">typedef</span> <span style="color:#000">std</span><span style="color:#ce5c00;font-weight:bold">::</span><span style="color:#000">vector</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">human</span> <span style="color:#ce5c00;font-weight:bold">*&gt;</span> <span style="color:#000">parent_</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">struct</span> <span style="color:#000">human</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">const</span> <span style="color:#204a87;font-weight:bold">char</span> <span style="color:#ce5c00;font-weight:bold">*</span><span style="color:#000">name</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">sex_</span> <span style="color:#000">sex</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">parent_</span> <span style="color:#000">parent</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#000">human</span> <span style="color:#000">Tom</span><span style="color:#000;font-weight:bold">{</span><span style="color:#4e9a06">&#34;Tom&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">male</span><span style="color:#000;font-weight:bold">,{}};</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">human</span> <span style="color:#000">Janna</span><span style="color:#000;font-weight:bold">{</span><span style="color:#4e9a06">&#34;Janna&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">female</span><span style="color:#000;font-weight:bold">,{}};</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">human</span> <span style="color:#000">Jake</span><span style="color:#000;font-weight:bold">{</span><span style="color:#4e9a06">&#34;Jake&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">male</span><span style="color:#000;font-weight:bold">,{</span><span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">Tom</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">Janna</span><span style="color:#000;font-weight:bold">}};</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">human</span> <span style="color:#000">Tim</span><span style="color:#000;font-weight:bold">{</span><span style="color:#4e9a06">&#34;Tim&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">male</span><span style="color:#000;font-weight:bold">,{</span><span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">Tom</span><span style="color:#000;font-weight:bold">}};</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#000">std</span><span style="color:#ce5c00;font-weight:bold">::</span><span style="color:#000">vector</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">human</span> <span style="color:#ce5c00;font-weight:bold">*&gt;</span> <span style="color:#000">humans</span><span style="color:#000;font-weight:bold">{</span><span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">Tom</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">Janna</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">Jake</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">Tim</span><span style="color:#000;font-weight:bold">};</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">auto</span> <span style="color:#000">brothers</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000;font-weight:bold">[](</span><span style="color:#000">human</span> <span style="color:#ce5c00;font-weight:bold">*</span> <span style="color:#000">a</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">human</span> <span style="color:#ce5c00;font-weight:bold">*</span> <span style="color:#000">b</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">auto</span> <span style="color:#000">intersec</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000;font-weight:bold">[](</span><span style="color:#000">parent_</span> <span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">a</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">parent_</span> <span style="color:#ce5c00;font-weight:bold">&amp;</span> <span style="color:#000">b</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">for</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">auto</span> <span style="color:#f57900">elem_a</span> <span style="color:#000;font-weight:bold">:</span> <span style="color:#000">a</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">for</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">auto</span> <span style="color:#f57900">elem_b</span> <span style="color:#000;font-weight:bold">:</span> <span style="color:#000">b</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">if</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">elem_a</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#000">elem_b</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#000">elem_a</span> <span style="color:#ce5c00;font-weight:bold">==</span> <span style="color:#000">elem_b</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#204a87">true</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#204a87">false</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">a</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#000">b</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#000">a</span> <span style="color:#ce5c00;font-weight:bold">!=</span> <span style="color:#000">b</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#000">a</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">sex</span> <span style="color:#ce5c00;font-weight:bold">==</span> <span style="color:#000">male</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#000">b</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">sex</span> <span style="color:#ce5c00;font-weight:bold">==</span> <span style="color:#000">male</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#000">intersec</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">a</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">parent</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">b</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">parent</span><span style="color:#000;font-weight:bold">));</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">for</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">auto</span> <span style="color:#f57900">a</span> <span style="color:#000;font-weight:bold">:</span> <span style="color:#000">humans</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">for</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">auto</span> <span style="color:#f57900">b</span> <span style="color:#000;font-weight:bold">:</span> <span style="color:#000">humans</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">if</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">brothers</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">a</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">b</span><span style="color:#000;font-weight:bold">))</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">std</span><span style="color:#ce5c00;font-weight:bold">::</span><span style="color:#000">cout</span> <span style="color:#ce5c00;font-weight:bold">&lt;&lt;</span> <span style="color:#000">a</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">name</span> <span style="color:#ce5c00;font-weight:bold">&lt;&lt;</span> <span style="color:#4e9a06">&#34; and &#34;</span> <span style="color:#ce5c00;font-weight:bold">&lt;&lt;</span> <span style="color:#000">b</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">name</span> <span style="color:#ce5c00;font-weight:bold">&lt;&lt;</span> <span style="color:#4e9a06">&#34;</span><span style="color:#4e9a06">\n</span><span style="color:#4e9a06">&#34;</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> -</span></span></code></pre></div><p>Конечно, текст на С++ получается значительно многословней, чем вариант на Прологе, но по сути, это почти дословное повторение декларативного стиля написания кода. -Тем более, не стоит забывать про рассуждения в начале статьи об изначальном выборе концепции при создании языка -и &ldquo;принуждении&rdquo; программистов пользоваться только одной, изначально выбранной парадигмой разработки.</p> -<p><strong>Таким образом, можно с высокой долей уверенности утверждать, что теоретически можно писать код одновременно в разных стилях.</strong></p> -<p>Но что тогда мешает в рамках одного языка программирования писать с использованием императивного и декларативного стиля? -Неужели только убежденность создателей языков в том, что императивный и декларативный стили программирования являются взаимоисключающими? -И только из-за этого получаются языки программирования, синтаксис которых подходит для использования одной единственной парадигмы?</p> -<p><em>Но если это так, то что мешает попробовать разработать синтаксис языка программирования, в котором можно было бы использовать сразу императивный и декларативный стили программирования одновременно?</em></p> -<h2 id="что-мешает-совместить-императивный-и-декларативный-стили-написания-в-рамках-одной-программы">Что мешает совместить императивный и декларативный стили написания в рамках одной программы?<a class="td-heading-self-link" href="#%d1%87%d1%82%d0%be-%d0%bc%d0%b5%d1%88%d0%b0%d0%b5%d1%82-%d1%81%d0%be%d0%b2%d0%bc%d0%b5%d1%81%d1%82%d0%b8%d1%82%d1%8c-%d0%b8%d0%bc%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b9-%d0%b8-%d0%b4%d0%b5%d0%ba%d0%bb%d0%b0%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b9-%d1%81%d1%82%d0%b8%d0%bb%d0%b8-%d0%bd%d0%b0%d0%bf%d0%b8%d1%81%d0%b0%d0%bd%d0%b8%d1%8f-%d0%b2-%d1%80%d0%b0%d0%bc%d0%ba%d0%b0%d1%85-%d0%be%d0%b4%d0%bd%d0%be%d0%b9-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d1%8b" aria-label="Heading self-link"></a></h2> -<p>В любой компьютерной программе всегда существует разделение кода на описание данных и на языковые конструкции для их обработки, т.е. фактически это разделение <strong>на данные</strong> и <strong>на функции</strong>. -Мне кажется, что основная сложность, которая не дает использовать разные стили программирования в рамках одного языка, это необходимость разделять описываемые сущности на «данные» и «управляющие конструкции». -Ведь это свойство (необходимость разделения сущностей на &ldquo;данные&rdquo; и &ldquo;функции&rdquo;), является неотъемлемой частью любого языка программирования.</p> -<p>Это не удивительно, ведь на заре становления ИТ индустрии, создатели первых языков программирования ориентировались исключительно на императивный стиль, потому что назначением любого компилятора было - преобразовать исходный текст программы в машинные инструкции. И на примерах модульного, структурного и объекто-ориентированного подходах показана и доказана необходимость оформления исполняемого кода в выделенные процедуры с последующей их группировкой в модули и классы.</p> -<p>А декларативный стиль написания программ стал появляться только после создания высокоуровневых языков программирования. -И основная цель создания данных языков сместилась на поиск решения конечного пользователя, а не на упрощение генерации бинарных файлов с машинными инструкциями. -Если внимательно посмотреть на приведенные выше примеры кода, то можно заметить, что в них определения данных и операторы для их обработки идут вперемешку, (для примера на С++ это определение лямбд функции), что кардинально отличается от императивного подхода.</p> -<p>Так может быть, основная особенность декларативного стиля как раз и заключается в том, что в нем не разделяются «данные» и «действия над данными»? -Или как вариант, можно не указывать выполняемые действия над данными вовсе (как в некоторых SQL конструкциях)?</p> -<p>Может быть как раз именно эта особенность (возможность последовательной записи программного кода в соответствии с собственными логическими рассуждениями, -в которых могут перемежаться «данные» и «функции», как это происходит при человеческом мыслительном процессе), -не дает в полной мере реализовать возможность совмещения императивных и декларативных стилей программирования?</p> -<p><em>И если это так, тогда можно попробовать разработать такой синтаксис, который будет поддерживать определение как данных, так и декларацию функций в рамках единого потока языковых конструкций!</em></p> -<h2 id="проверка-гипотезы-в-новом-языке-программирования">Проверка гипотезы в новом языке программирования<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b0-%d0%b3%d0%b8%d0%bf%d0%be%d1%82%d0%b5%d0%b7%d1%8b-%d0%b2-%d0%bd%d0%be%d0%b2%d0%be%d0%bc-%d1%8f%d0%b7%d1%8b%d0%ba%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h2> -<p>Для поверки данного предположения, я решил добавить в свой <a href="http://localhost:1313/blog/2021/05/24/%D0%BD%D0%B5%D0%BE%D0%B1%D1%8B%D1%87%D0%BD%D0%B0%D1%8F-%D0%BA%D0%BE%D0%BD%D1%86%D0%B5%D0%BF%D1%86%D0%B8%D1%8F-%D1%81%D0%B8%D0%BD%D1%82%D0%B0%D0%BA%D1%81%D0%B8%D1%81%D0%B0-%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0-%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F/">новый язык программирования</a> -(синтаксис которого допускает определение функций в одном потоке с описанием обрабатываемых данных), недостающие алгоритмические конструкции, которые позволяли бы реализовать императивный стиль программирования, -несмотря на изначальную ориентацию только на декларативную парадигму.</p> -<p>Правда с учетом изначальных ограничений синтаксиса нового языка (запрет на применение операторов в виде зарезервированных ключевых слов), -в качестве оператора проверки условия была выбрана синтаксическая конструкция, соответствующая по смыслу термину «следует», -т.е. тире и угловая скобка «<strong>-&gt;</strong>».</p> -<p>В результате, условный оператор получился практически математический, который легко объединяется в последовательности для реализации проверки множественных условий вида «else if». -А для объединения сразу нескольких логического операторов между собой и для отделения их от последующего действия, операторы проверки условия можно заключать в круглые скобки.</p> -<p>В общем случае условный оператор в новом языке программирования имеет вид:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span> <span style="color:#a40000">условие</span> <span style="color:#ce5c00;font-weight:bold">-&gt;</span> <span style="color:#a40000">действие</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#a40000">или</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">условие</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">-&gt;</span> <span style="color:#000;font-weight:bold">{</span><span style="color:#a40000">действие</span><span style="color:#000;font-weight:bold">};</span> -</span></span><span style="display:flex;"><span> <span style="color:#a40000">или</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">условие</span><span style="color:#0000cf;font-weight:bold">1</span> <span style="color:#ce5c00;font-weight:bold">||</span> <span style="color:#a40000">условие</span><span style="color:#0000cf;font-weight:bold">2</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">-&gt;</span> <span style="color:#000;font-weight:bold">{</span><span style="color:#a40000">действие</span><span style="color:#000;font-weight:bold">}</span> <span style="color:#ce5c00;font-weight:bold">-&gt;</span> <span style="color:#000;font-weight:bold">{</span><span style="color:#a40000">действие</span> <span style="color:#a40000">иначе</span><span style="color:#000;font-weight:bold">};</span> -</span></span></code></pre></div><p>Или расширенный вариант, для наглядности записанный с отступами:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">условие</span><span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">-&gt;</span> <span style="color:#000;font-weight:bold">{</span><span style="color:#a40000">действие</span><span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">условие</span><span style="color:#0000cf;font-weight:bold">2</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">-&gt;</span> <span style="color:#000;font-weight:bold">{</span><span style="color:#a40000">действие</span><span style="color:#0000cf;font-weight:bold">2</span><span style="color:#000;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">условие</span><span style="color:#0000cf;font-weight:bold">3</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">-&gt;</span> <span style="color:#000;font-weight:bold">{</span><span style="color:#a40000">действие</span><span style="color:#0000cf;font-weight:bold">3</span><span style="color:#000;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">-&gt;</span> <span style="color:#000;font-weight:bold">{</span><span style="color:#a40000">действие</span><span style="color:#000">_иначе</span><span style="color:#000;font-weight:bold">};</span> -</span></span></code></pre></div><p>Тогда и операторы циклов можно будет записать практически аналогично, только выбрав в качестве оператора, не оператор следования, -а следование с возвратом (раз уж нужно указывать циклическое действие).</p> -<p>Цикл пока:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">условие</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">&lt;-&gt;</span> <span style="color:#000;font-weight:bold">{</span><span style="color:#a40000">тело</span> <span style="color:#a40000">цикла</span><span style="color:#000;font-weight:bold">};</span> -</span></span></code></pre></div><p>счетный цикл для работы с итератором:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">счетчик</span><span style="color:#000">_или_данные</span><span style="color:#ce5c00;font-weight:bold">!</span><span style="color:#000;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">?</span> <span style="color:#ce5c00;font-weight:bold">&lt;-&gt;</span> <span style="color:#000;font-weight:bold">{</span><span style="color:#a40000">тело</span> <span style="color:#a40000">цикла</span><span style="color:#000;font-weight:bold">};</span> -</span></span></code></pre></div><p>В этом случае, решение тестового примера декларативной программы на Прологе можно будет легко оформить, как в императивном, так и в декларативном стилях одновременно!</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> м :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#4e9a06">&#34;муж.&#34;</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> ж :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#4e9a06">&#34;жен.&#34;</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> human @<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">пол</span><span style="color:#ce5c00;font-weight:bold">=</span>, <span style="color:#000">parent</span><span style="color:#ce5c00;font-weight:bold">=[</span>,<span style="color:#ce5c00;font-weight:bold">])</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Tom @<span style="color:#ce5c00;font-weight:bold">=</span> human<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">пол</span><span style="color:#ce5c00;font-weight:bold">=</span>м<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Janna @<span style="color:#ce5c00;font-weight:bold">=</span> human<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">пол</span><span style="color:#ce5c00;font-weight:bold">=</span>ж<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Jake @<span style="color:#ce5c00;font-weight:bold">=</span> human<span style="color:#ce5c00;font-weight:bold">(</span>м, <span style="color:#ce5c00;font-weight:bold">[</span><span style="color:#000;font-weight:bold">&amp;</span>Tom, <span style="color:#000;font-weight:bold">&amp;</span>Janna,<span style="color:#ce5c00;font-weight:bold">])</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Tim @<span style="color:#ce5c00;font-weight:bold">=</span> human<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">пол</span><span style="color:#ce5c00;font-weight:bold">=</span>м, <span style="color:#000">parent</span><span style="color:#ce5c00;font-weight:bold">=[</span><span style="color:#000;font-weight:bold">&amp;</span>Tom,<span style="color:#ce5c00;font-weight:bold">])</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> brother<span style="color:#ce5c00;font-weight:bold">(</span>h1, h2<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;=</span> <span style="color:#000">$h1</span>!<span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#000">$h2</span>, <span style="color:#000">$h1</span>.пол<span style="color:#ce5c00;font-weight:bold">==</span>м, <span style="color:#000">$h2</span>.пол<span style="color:#ce5c00;font-weight:bold">==</span>м, <span style="color:#000">$h1</span>.parent <span style="color:#000;font-weight:bold">&amp;</span> <span style="color:#000">$h2</span>.parent<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> // Оператор «<span style="color:#000;font-weight:bold">&amp;</span>» побитовое «И» для чисел или операция пересечения для множеств -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> // Запись алгоритма поиска решения в императивном стиле -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">h1</span><span style="color:#ce5c00;font-weight:bold">=</span>human!, <span style="color:#000">h2</span><span style="color:#ce5c00;font-weight:bold">=</span>human!<span style="color:#ce5c00;font-weight:bold">)</span>? &lt;-&gt; <span style="color:#ce5c00;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span>brother<span style="color:#ce5c00;font-weight:bold">(</span>h1, h2<span style="color:#ce5c00;font-weight:bold">))</span> -&gt; <span style="color:#ce5c00;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> @print<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">$h1</span>, <span style="color:#000">$h2</span>, «<span style="color:#4e9a06">\n</span>»<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> // Краткая запись алгоритма поиска решения в императивном стиле -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">h1</span><span style="color:#ce5c00;font-weight:bold">=</span>human!, <span style="color:#000">h2</span><span style="color:#ce5c00;font-weight:bold">=</span>human!<span style="color:#ce5c00;font-weight:bold">)</span>? &lt;-&gt; -</span></span><span style="display:flex;"><span> brother<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">$h1</span>, <span style="color:#000">$h2</span><span style="color:#ce5c00;font-weight:bold">)</span> -&gt; @print<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">$h1</span>, <span style="color:#000">$h2</span>, «<span style="color:#4e9a06">\n</span>»<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> // Запись поиска решения в декларативном стиле -</span></span><span style="display:flex;"><span> brother<span style="color:#ce5c00;font-weight:bold">(</span>human!, human!<span style="color:#ce5c00;font-weight:bold">)</span>?<span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>Примерно это и требовалось показать!</p> -<h3 id="зы">З.Ы.<a class="td-heading-self-link" href="#%d0%b7%d1%8b" aria-label="Heading self-link"></a></h3> -<p>Я почти закончил эксперименты с синтаксисом языка. -И теперь, после добавления в него недостающих алгоритмический конструкций (ветвления и циклов), планирую, -что следующая статья о новом языке программирования будет посвящена описанию его полного синтаксиса и публикации исходников прототипа компилятора для возможности поиграться на реальных примерах.</p> -<h3 id="ззы">З.З.Ы<a class="td-heading-self-link" href="#%d0%b7%d0%b7%d1%8b" aria-label="Heading self-link"></a></h3> -<p>В <a href="https://habr.com/company/timeweb/blog/569422/comments/#comment_23301086">комментариях @gbg</a> привел очень простой ответ на один из поднятых вопросов. -Причем в более элегантном виде и без написания кода!</p> -<blockquote> -<p>Ну и пять копеечек про ООП. Как ни странно:</p> -<ol> -<li>В нем таки есть декларативная часть, все эти pubic, private, virtual, etc</li> -<li>Эта декларативная часть, внезапно, элегантно позволяет реализовывать декомпозицию и управление сложностью.</li> -<li>При наличии перегрузок, можно поиграть в алгебраическое мышление, рассматривая взаимодействие двух объектов как бинарную операцию.</li> -</ol> -<p>Ух ты, ООП - это обкатанная практикой технология, которая совмещает декларатив с императивом и вроде позволяет освоившим ее вкусно кушать и мягко спать!</p> -</blockquote> -<p><a href="https://habr.com/companies/timeweb/articles/569422/">Ссылка на первую публикаци</a></p> - - - - - - Blog: Необычная концепция синтаксиса языка программирования - http://localhost:1313/blog/unusual-prog/ - Mon, 24 May 2021 00:00:00 +0000 - - http://localhost:1313/blog/unusual-prog/ - - - - <p><img alt="КДПВ" src="http://localhost:1313/blog/langs.jpeg"></p> - - -<div class="pageinfo pageinfo-primary"> -<p>Внимание!!!</p> -<p>Данная статья содержит описание синтаксиса NewLnag предыдущей версии.</p> -<p>Актуальную версию синтаксиса языка можно посмотреть <a href="http://localhost:1313/docs/">тут</a>.</p> - -</div> - -<p>Хочу представить на обсуждение читателей немного необычный концепт языка программирования, в котором отсутствует проблема, -присущая практически всем промышленным языкам - постоянное увеличение сложности синтаксиса языка из-за его естественного развития по мере выхода новых версий и добавления новых фич. -Эта проблема описана в статье <a href="http://localhost:1313/blog/complex-prog/">&ldquo;Простое сложное программирование&rdquo;</a> и <a href="http://localhost:1313/blog/lang-final/">Какая &ldquo;идеальная&rdquo; цель развития у языков программирования?</a></p> -<p>После нескольких экспериментов с синтаксисом, хочется проверить выработанную идею на широкой аудитории <a href="https://habr.com/companies/timeweb/articles/558738/">Хабра</a>, которая как нельзя лучше подходит для этих целей.</p> -<p>Особенности языка:</p> -<ul> -<li>Низкий порог входа и естественное ограничение уровня сложности в течение длительного времени даже при условии постоянного развития самого языка.</li> -<li>Возможность писать код программы как в декларативной, так и в императивной парадигме с использованием процедурного, модульного и объектно-ориентированного подхода.</li> -</ul> -<p>Ну и в соответствии с собственным наблюдением <a href="https://habr.com/post/539674/">Хабр — ума палата</a>, буду рад любым комментариям и предложениям, которые помогут протестировать или улучшить предлагаемое решение.</p> -<h2 id="введение">Введение<a class="td-heading-self-link" href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h2> -<p>Первой необычной особенностью языка является полное отсутствие зарезервированных ключевых слов. -Точнее, планируется использовать только одно единственное ключевое слово (название языка), которое может быть как главной точкой входа в приложение, -так и способом доступа к настройкам языка под конкретную предметную область, например при необходимости реализации <a href="https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%B4%D0%BC%D0%B5%D1%82%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D1%8F%D0%B7%D1%8B%D0%BA">DSL парадигмы</a>.</p> -<p>В настоящий момент название языка не выбрано, поэтому для примеров используется просто слово <em>lang</em>, которое в будущем будет изменено.</p> -<p>Данная особенность (отсутствие зарезервированных ключевых слов) реализуется за счет того, грамматика языка основана на использовании общеупотребительных символов и классических знаков препинания, -а все остальные букво-символьные последовательности при парсинге программы рассматриваются как &ldquo;токены&rdquo;.</p> -<p>Компилятор языка реализуется как <a href="https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B0%D0%BD%D1%81%D0%BF%D0%B0%D0%B9%D0%BB%D0%B5%D1%80">transpiler</a> - преобразование исходного кода программы, -написанной на одном языке программирования, в эквивалентный исходный код на другом языке. -Первые эксперименты с синтаксисом я начинал на Python, но после осознания необходимости разработки не только интерпретатора, -но и компилятора непосредственно в исполняемый код, решил остановиться на C++. Хотя в принципе, язык реализации может быть любым.</p> -<p>Использование <a href="https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B0%D0%BD%D1%81%D0%BF%D0%B0%D0%B9%D0%BB%D0%B5%D1%80">транспиляции</a> при реализации компилятора решает сразу множество очевидных и не очень задач. -Сразу отпадает необходимость разрабатывать низкоуровневый компилятор в исполняемый процессорный код, -а в моем случае основным бонусом такого подхода становится возможность использования императивной парадигмы программирования за счет вставок кода непосредственно в исходный код приложения на языке реализации.</p> -<p>И именно этот момент позволяет естественно разделить декларативный и императивный способ написания программы. -В этом случае в декларативной парадигме реализуется только одна из трех базовых управляющих конструкций, -необходимых и достаточных при реализации <a href="https://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5">любого алгоритма</a> — <em>следование</em>.</p> -<p>Другими словами, в декларативном стиле описывается только <em>последовательность</em> операций, которые следуют одна за другой, -но отсутствует возможность запрограммировать циклы или ветвление (переходы) по условию. -Из-за этого в декларативном стиле можно записать только следующие типы языковых конструкций:</p> -<ul> -<li>комментарий</li> -<li>определение переменной и присвоение ей значения</li> -<li>создание объекта и назначение его свойствам значений по умолчанию</li> -<li>создание функции (метода для всего класса объектов)</li> -<li>вызов функции или итератора</li> -<li>непосредственная вставка кода на языке реализации</li> -</ul> -<p>Так как цель текущей публикации - протестировать общую концепцию, то начну сразу с примеров без длинного описания подробностей, а некоторые нюансы буду комментировать по ходу дела. -Тем более, самая главная цель &ldquo;низкий порог входа&rdquo; само собой подразумевает возможность самостоятельно разобраться в синтаксисе. -Тем не менее, совсем без знаний языка реализации не обойтись и начальные знания в программировании на С/С++ все равно необходимы.</p> -<h2 id="привет-мир-в-императивной-парадигме">&ldquo;Привет, мир!&rdquo; в императивной парадигме<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b8%d0%b2%d0%b5%d1%82-%d0%bc%d0%b8%d1%80-%d0%b2-%d0%b8%d0%bc%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d0%bf%d0%b0%d1%80%d0%b0%d0%b4%d0%b8%d0%b3%d0%bc%d0%b5" aria-label="Heading self-link"></a></h2> -<p>Определение обычной функции выполняется с помощью оператора присвоения &ldquo;:=&rdquo;, а программный код на языке реализации (в данном случае на C++) -заключается в фигурные скобки. Простой пример вывода строки на экран выглядит примерно так:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span> <span style="color:#000">print</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">str</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#4e9a06">&#34;&#34;</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000;font-weight:bold">{</span> <span style="color:#000">printf</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;%s&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">static_cast</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#204a87;font-weight:bold">char</span> <span style="color:#ce5c00;font-weight:bold">*&gt;</span><span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">$</span><span style="color:#000">str</span><span style="color:#000;font-weight:bold">));</span> <span style="color:#000;font-weight:bold">}</span> -</span></span></code></pre></div><p>Функция <strong>print</strong> с аргументом по умолчанию в виде пустой строки внутри себя вызывает обычный printf из стандартной библиотеки.</p> -<p>Соответственно &ldquo;Привет, мир!&rdquo; в императивной парадигме программирования будет выглядеть тривиально:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic">#!/bin/lang -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"></span> <span style="color:#000">print</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">str</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#4e9a06">&#34;&#34;</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000;font-weight:bold">{</span> <span style="color:#000">printf</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;%s&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">static_cast</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#204a87;font-weight:bold">char</span> <span style="color:#ce5c00;font-weight:bold">*&gt;</span><span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">$</span><span style="color:#000">str</span><span style="color:#000;font-weight:bold">));</span> <span style="color:#000;font-weight:bold">};</span> -</span></span><span style="display:flex;"><span> <span style="color:#a40000">@</span><span style="color:#000">print</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Привет, мир!</span><span style="color:#4e9a06">\n</span><span style="color:#4e9a06">&#34;</span><span style="color:#000;font-weight:bold">);</span> -</span></span></code></pre></div><p>Из примера видно, что обращение к аргументам внутри С++ кода происходит с использованием символа <strong>$</strong>, который указывается вначале именованного аргумента. -Кроме этого, для доступа к аргументам функции можно обращаться по их порядковым номерам начиная с первого ($1, $2, $3 и т. д.). -Зарезервированный аргумент $0 содержит сам объект, метод которого вызывается или <em>nullptr</em>, если функция не принадлежит объекту.</p> -<p><em>Обычные</em> функции являются именно обычными функциями в понимании С/С++. -Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д. -Технически, код такой функции парсится на предмет замены использованных аргументов, -специальным образом декорируется её имя и добавляются специальные маркеры для идентификации содержимого. -После этого исходный текст готов для сборки обычным С++ компилятором для превращения в динамическую библиотеку -и после её загрузки функцию можно будет вызвать в любой момент (для вызова функции перед её именем необходимо указать символ <strong>&quot;@&quot;</strong>).</p> -<p>Непосредственное выполнение файла в режиме интерпретатора происходит в два этапа. На первом этапе из текста программы генерируется временный С++ файл с исходным кодом всех функций, этот файл компилируется gcc и собирается динамическая библиотека.</p> -<p>На втором этапе, собранная динамическая библиотека загружается средой выполнения, а исходный текст программы начинает последовательно выполнятся интерпретатором (все строки, за исключением определений функций).</p> -<p>Есть еще вариант, когда вместо интерпретации кода программы, генерируется С++ файл не только для функций, но и для основной части приложения. -Тогда на выходе компилятора будет уже обычный бинарный файл, хотя в том случае оперативно поправить текст программы уже не получится.</p> -<h2 id="логическое-программирование-в-декларативной-парадигме">Логическое программирование в декларативной парадигме<a class="td-heading-self-link" href="#%d0%bb%d0%be%d0%b3%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%b2-%d0%b4%d0%b5%d0%ba%d0%bb%d0%b0%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d0%bf%d0%b0%d1%80%d0%b0%d0%b4%d0%b8%d0%b3%d0%bc%d0%b5" aria-label="Heading self-link"></a></h2> -<p>Так как самым известным языком логического программирования в декларативном стиле считается Prolog, -поэтому приведу простой пример программы Brother (поиска братьев) на Прологе и эквивалентный ему код на новом языке.</p> -<p>Prolog:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> male<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Tom&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span>. -</span></span><span style="display:flex;"><span> male<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Tim&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span>. -</span></span><span style="display:flex;"><span> male<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Jake&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span>. -</span></span><span style="display:flex;"><span> female<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Janna&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span>. -</span></span><span style="display:flex;"><span> parent<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Tom&#34;</span>,<span style="color:#4e9a06">&#34;Jake&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span>. -</span></span><span style="display:flex;"><span> parent<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Janna&#34;</span>,<span style="color:#4e9a06">&#34;Jake&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span>. -</span></span><span style="display:flex;"><span> parent<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Tom&#34;</span>,<span style="color:#4e9a06">&#34;Tim&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span>. -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> brother<span style="color:#ce5c00;font-weight:bold">(</span>X,Y<span style="color:#ce5c00;font-weight:bold">)</span>:- parent<span style="color:#ce5c00;font-weight:bold">(</span>Z,X<span style="color:#ce5c00;font-weight:bold">)</span>,parent<span style="color:#ce5c00;font-weight:bold">(</span>Z,Y<span style="color:#ce5c00;font-weight:bold">)</span>,male<span style="color:#ce5c00;font-weight:bold">(</span>X<span style="color:#ce5c00;font-weight:bold">)</span>,male<span style="color:#ce5c00;font-weight:bold">(</span>Y<span style="color:#ce5c00;font-weight:bold">)</span>,X<span style="color:#4e9a06">\=</span>Y. -</span></span></code></pre></div><p>Вывод: <strong>(Jake, Tim) (Tim, Jake)</strong></p> -<p>Тот же самый пример:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic">#!/bin/lang</span> -</span></span><span style="display:flex;"><span> human:<span style="color:#ce5c00;font-weight:bold">=</span>@term<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">sex</span><span style="color:#ce5c00;font-weight:bold">=</span>,parent<span style="color:#ce5c00;font-weight:bold">=)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Tom:<span style="color:#ce5c00;font-weight:bold">=</span>@human<span style="color:#ce5c00;font-weight:bold">(</span>male<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Janna:<span style="color:#ce5c00;font-weight:bold">=</span>@human<span style="color:#ce5c00;font-weight:bold">(</span>female<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Jake:<span style="color:#ce5c00;font-weight:bold">=</span>@human<span style="color:#ce5c00;font-weight:bold">(</span>male, <span style="color:#ce5c00;font-weight:bold">(</span>Tom, Janna,<span style="color:#ce5c00;font-weight:bold">))</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Tim:<span style="color:#ce5c00;font-weight:bold">=</span>@human<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">sex</span><span style="color:#ce5c00;font-weight:bold">=</span>male, <span style="color:#000">parent</span><span style="color:#ce5c00;font-weight:bold">=(</span>Tom,<span style="color:#ce5c00;font-weight:bold">))</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> human::brother<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">test</span><span style="color:#ce5c00;font-weight:bold">=</span>human!<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;=</span> <span style="color:#000">$0</span>!<span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#000">$test</span>, <span style="color:#000">$0</span>.sex<span style="color:#ce5c00;font-weight:bold">==</span>male, @intersec<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">$0</span>.parent, <span style="color:#000">$test</span>.parent<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> human.brother? -</span></span></code></pre></div><p>Вывод: <strong>[Tim.brother(Jake), Jake.brother(Tim),]</strong></p> -<p>Надеюсь, что синтаксис интуитивно понятен, особенно при наличии эквивалентного кода на Прологе, но на всякий случай поясню отдельные моменты.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> human:<span style="color:#ce5c00;font-weight:bold">=</span>@term<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">sex</span><span style="color:#ce5c00;font-weight:bold">=</span>,parent<span style="color:#ce5c00;font-weight:bold">=)</span><span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>В этой строке создается объект с именем &ldquo;human&rdquo; и двумя свойствами &ldquo;sex&rdquo; и &ldquo;parent&rdquo;, -значения которых по умолчанию не определены, а родителем является системный объект &ldquo;term&rdquo;. -Использование символа <strong>&quot;@&quot;</strong> в начале термина обозначает вызов существующей функции с параметрами, указанными в скобках. -В данном случае вызывается конструктор системного объекта &ldquo;term&rdquo;, а возвращаемым результатом является новый термин &ldquo;human&rdquo;, -который можно воспринимать как один экземпляр класса, так и как имя целого класса, если он будет выступать в качестве родителя для других объектов.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> Tom:<span style="color:#ce5c00;font-weight:bold">=</span>@human<span style="color:#ce5c00;font-weight:bold">(</span>male<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Janna:<span style="color:#ce5c00;font-weight:bold">=</span>@human<span style="color:#ce5c00;font-weight:bold">(</span>female<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Jake:<span style="color:#ce5c00;font-weight:bold">=</span>@human<span style="color:#ce5c00;font-weight:bold">(</span>male, <span style="color:#ce5c00;font-weight:bold">(</span>Tom, Janna,<span style="color:#ce5c00;font-weight:bold">))</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Tim:<span style="color:#ce5c00;font-weight:bold">=</span>@human<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">parent</span><span style="color:#ce5c00;font-weight:bold">=(</span>Tom,<span style="color:#ce5c00;font-weight:bold">)</span>, <span style="color:#000">sex</span><span style="color:#ce5c00;font-weight:bold">=</span>male<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>Первые две строки создают объекты &ldquo;Tom&rdquo; и &ldquo;Janna&rdquo;, у которых свойство &ldquo;sex&rdquo; установлено в значения &ldquo;male&rdquo; и &ldquo;female&rdquo; соответственно. -А в последней строке при создании объекта Tim значения свойств задается с указанием их имени.</p> -<p>Конструкции <em>(Tom, Janna,)</em> и <em>(Tom,)</em>, это определение константного литерала с типом словарь, которые присваиваются указанным свойствам.</p> -<p>Чтобы определение словаря не путать с указанием аргументов при вызове функции, в нем содержится обязательная финальная запятая перед закрывающей скобкой. -Это правило (финальная запятая перед закрывающей скобкой) действует и при определении литерала массива, только для записи которого используются скобки не круглые, а квадратные (например <strong>[,]</strong> - пустой массив). -Основным отличием словаря от массива, заключаются в способах доступа к их элементам. -Для доступа к элементу массива используется целочисленный индекс, а в словаре может быть использован как индекс, так и имя элемента при его наличии. -Между словарем и массивом есть еще отличия, но сейчас они не принципиальны.</p> -<p>И предпоследняя строка в примере:</p> -<p>human::brother(test=human <em>!</em>) <strong>&amp;&amp;=</strong> <em>$0</em> != <em>$test</em>, <em>$0</em>.sex==male, @intersec(<em>$0</em>.parent, <em>$test</em>.parent);</p> -<p>это определение <i>простой чистой</i> функции &ldquo;brother&rdquo; для всех объектов, производных от &ldquo;human&rdquo;. -Данная функция принимает один именованный аргумент &ldquo;test&rdquo;, значением по умолчанию которого является <em>итератор</em> объектов класса &ldquo;human&rdquo;.</p> -<p>Оператор <strong>&amp;&amp;=</strong> означает определение <em>простой чистой</em> функции, т. е. функции без внешних зависимостей, -которая не имеет доступа к глобальному контексту, а результат выполнения которой является логическое значение, -которое вычисляется по схеме <a href="https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BD%D1%8A%D1%8E%D0%BD%D0%BA%D1%86%D0%B8%D1%8F">логическое И</a> для всех условий, указанных в теле функции через запятую.</p> -<p>Выполнение и вывод результата выполнения программы происходит в строке -<code>human.brother?</code></p> -<p>Восклицательный и вопросительный знаки обозначают <a href="https://ru.wikipedia.org/wiki/%D0%98%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80">итератор</a>. Итератор &ldquo;<strong>!</strong>&rdquo; возвращает один текущий элемент из коллекции и передвигает указатель на следующий, -а итератор &ldquo;<strong>?</strong>&rdquo; возвращает сразу всю коллекцию объектов целиком.</p> -<p>Другими словами при выполнении строки программы <em>human.brother <strong>?</strong></em> происходит последовательный перебор всей коллекции объектов типа &ldquo;human&rdquo;, -где у каждого объекта выполняется функция &ldquo;brother&rdquo; с аргументами по умолчанию. -А так как в качестве аргумента по умолчанию указан итератор <em>human <strong>!</strong></em>, то в качестве аргумента последовательно предается каждый из элементов указанного класса. -По сути, при выполнении этой строки происходит полный перебор всех возможных комбинаций объектов класса &ldquo;human&rdquo; каждый с каждым.</p> -<blockquote> -<p>Более подробное описание работы итератора и причина выбора такого синтаксиса опубликовано в отдельной статье <a href="https://habr.com/company/timeweb/blog/559916/">Лаконичный итератор для декларативного синтаксиса</a></p> -</blockquote> -<p>Результат выполнения будет состоять из тех пар объектов, для которых функция &ldquo;brother&rdquo; вернет истину, т.е. результат выполнения будет массив из двух пар объектов <strong>[Tim.brother(Jake), Jake.brother(Tim),]</strong>.</p> -<h2 id="формулировка-проверяемой-концепции">Формулировка проверяемой концепции<a class="td-heading-self-link" href="#%d1%84%d0%be%d1%80%d0%bc%d1%83%d0%bb%d0%b8%d1%80%d0%be%d0%b2%d0%ba%d0%b0-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d1%8f%d0%b5%d0%bc%d0%be%d0%b9-%d0%ba%d0%be%d0%bd%d1%86%d0%b5%d0%bf%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h2> -<p>Тестируемая концепция заключается в следующем. Синтаксис языка программирования состоит как бы из двух частей, -каждая из которых является относительно независимой и в тоже время они связаны между собой.</p> -<p>Первая часть сложная — предназначена для описания алгоритмов в <em>императивном стиле</em> на обычном языке программирования, -поэтому внутри функций разработчику доступны все возможности языка реализации.</p> -<p>Вторая часть простая (по сравнению с первой) — предназначена только для логического описания задачи в <em>декларативном стиле</em>. -Именно эта часть используется для начального уровня использования, а естественное ограничение только на последовательное выполнение операторов -(т.е. отсутствие циклов и ветвлений) не доставляет чрезмерных сложностей в понимании исходного текста программы даже в будущем по мере развития языка.</p> -<p>Связь между двумя вариантами синтаксиса прозрачна и реализуется за счет совместного использования переменных и функций, -декларация и обращение к которым происходит в едином стиле в обоих случаях за счет унификации синтаксиса на уровне использования знаков препинания.</p> -<p>Сейчас я специально не привожу полного синтаксиса и подробного описания остальных возможностей языка, т.к. компилятор пока не готов для публичной презентации. -Но буду крайне благодарен за любой отклик или дельные предложения в отношении предложенной концепции.</p> -<p>Особенно это касается возможных конфликтов по синтаксису в представленных примерах.</p> - - - - - - Blog: Простое сложное программирование - http://localhost:1313/blog/complex-prog/ - Thu, 15 Apr 2021 00:00:00 +0000 - - http://localhost:1313/blog/complex-prog/ - - - - <p><img alt="КДПВ" src="http://localhost:1313/blog/complex-prog/complex-prog.jpeg"></p> -<p>В очередной раз увидел на Хабре статью про сложное дело под названием «программирование». -И то, что программирование действительно является делом не простым воспринимается как факт и обычно не требует какого либо подтверждения.</p> -<p>Но понятие «сложность» сродни термину «куча». -Для кого-то и пять кокосов это не куча, а кого-то съел один и «больше не хочется» - значит для него и единственного кокоса будет много.</p> -<p>Так и со сложностью ПО. Вроде бы увеличение сложности является для всех очевидным и наблюдается во всех сферах применения IT технологий, -да и сами языки программирования по мере своего развития становятся все сложнее, -а вот оценивать «сложность» с помощью численных метрик — дело заведомо неблагодарное, но и «нельзя управлять тем, что невозможно измерить &hellip;».</p> -<p>Обычно разговоры о «сложности» включают в себя только оценочные суждения без какой либо численной оценки. -А так как лично меня интересует вопрос сложности языков программирования, -то я решил посчитать сложность реализации компилятора gcc в каких нибудь условных попугаях. -Вдруг можно будет увидеть какие нибудь закономерности?</p> -<h2 id="выбор-попугаев-для-измерения">Выбор «попугаев» для измерения<a class="td-heading-self-link" href="#%d0%b2%d1%8b%d0%b1%d0%be%d1%80-%d0%bf%d0%be%d0%bf%d1%83%d0%b3%d0%b0%d0%b5%d0%b2-%d0%b4%d0%bb%d1%8f-%d0%b8%d0%b7%d0%bc%d0%b5%d1%80%d0%b5%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h2> -<p>Я не стал придумывать свои или вычислять эмпирические метрики <a href="https://habr.com/company/intel/blog/106082/">программного кода</a>, -и в качестве «попугая» решил взять самую простую метрику SLOC (англ. Source Lines of Code) — количество строк исходного текста компилятора, -которая очень легко вычисляется.</p> -<p>Правда, с её помощью можно будет оценивать сложность языка только при следующем допущении — сложность языка должна находиться в прямой зависимости от сложности его реализации, -если для простых синтаксических конструкций будет требовать меньше кода, чем для более сложных.</p> -<p>Конечно, использование метрики «количество строк исходного кода» имеет и свои недостатки, -т.к. она сильно зависит от используемого языка программирования, стиля оформления исходного кода и в общем случае не позволяет сравнивать несколько разных проектов между собой.</p> -<p>Но для численной оценки сложности кода в рамках <strong>одного проекта</strong>, метрика SLOC подходит хорошо.</p> -<h2 id="методика-подсчета-sloc">Методика подсчета SLOC<a class="td-heading-self-link" href="#%d0%bc%d0%b5%d1%82%d0%be%d0%b4%d0%b8%d0%ba%d0%b0-%d0%bf%d0%be%d0%b4%d1%81%d1%87%d0%b5%d1%82%d0%b0-sloc" aria-label="Heading self-link"></a></h2> -<p>Изначально попробовал использовать простой bash скрипт с поиском по маске и подсчетом числа строк в файлах исходника через <code>wc -l</code>. -Но через некоторое время стало понятно, что приходится изобретать очередной велосипед.</p> -<p><img alt="Ну вы поняли" src="http://localhost:1313/blog/complex-prog/bag.jpeg"></p> -<p>Поэтому решил взять уже готовый. После быстрого поиска остановился на утилите <a href="https://dwheeler.com/sloccount/">SLOCCount</a>, -которая умеет анализировать почти три десятка типов исходников.</p> -<h3 id="список-типов-файлов-для-автоматического-анализа">Список типов файлов для автоматического анализа<a class="td-heading-self-link" href="#%d1%81%d0%bf%d0%b8%d1%81%d0%be%d0%ba-%d1%82%d0%b8%d0%bf%d0%be%d0%b2-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2-%d0%b4%d0%bb%d1%8f-%d0%b0%d0%b2%d1%82%d0%be%d0%bc%d0%b0%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%be%d0%b3%d0%be-%d0%b0%d0%bd%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0" aria-label="Heading self-link"></a></h3> -<pre tabindex="0"><code> 1. Ada (.ada, .ads, .adb) - 2. Assembly (.s, .S, .asm) - 3. awk (.awk) - 4. Bourne shell and variants (.sh) - 5. C (.c) - 6. C++ (.C, .cpp, .cxx, .cc) - 7. C shell (.csh) - 8. COBOL (.cob, .cbl) as of version 2.10 - 9. C# (.cs) as of version 2.11 - 10. Expect (.exp) - 11. Fortran (.f) - 12. Haskell (.hs) as of version 2.11 - 13. Java (.java) - 14. lex/flex (.l) - 15. LISP/Scheme (.el, .scm, .lsp, .jl) - 16. Makefile (makefile) — not normally shown. - 17. Modula-3 (.m3, .i3) as of version 2.07 - 18. Objective-C (.m) - 19. Pascal (.p, .pas) - 20. Perl (.pl, .pm, .perl) - 21. PHP (.php, .php[3456], .inc) as of version 2.05 - 22. Python (.py) - 23. Ruby (.rb) as of version 2.09 - 24. sed (.sed) - 25. SQL (.sql) — not normally shown. - 26. TCL (.tcl, .tk, .itk) - 27. Yacc/Bison (.y) &lt;/code&gt; -</code></pre><p>Причем, считает не просто количество строк исходного текста, но и умеет игнорировать комментарии, -исключает из подсчета дубли файлов (сравнивает их хеш суммы), а также выводит расчетную трудоемкость, -примерную оценку стоимости разработки анализируемого проекта и другие характеристики.</p> -<p>Меня изначально интересовал объем исходников на С/С++ и может быть еще на Ассемблере, если таких файлов окажется достаточно много. -Но после начала работы очень обрадовался, что не стал изобретать велосипед, а взял готовую тулзу, -т.к. она отдельно считала статистику исходных файлов синтаксического анализатора Yacc/Bison (.y), -который и определяет фактическую сложность парсера (читай сложность синтаксиса языка программирования).</p> -<p>Старые исходники gcc брал с <a href="https://gcc.gnu.org/mirrors.html">https://gcc.gnu.org/mirrors.html</a>, но перед запуском анализатора удалил каталоги других компиляторов (ada, fortran, java и т.д.), -чтобы они не попадали в итоговую статистику.</p> -<h2 id="результаты-в-попугаях">Результаты в попугаях<a class="td-heading-self-link" href="#%d1%80%d0%b5%d0%b7%d1%83%d0%bb%d1%8c%d1%82%d0%b0%d1%82%d1%8b-%d0%b2-%d0%bf%d0%be%d0%bf%d1%83%d0%b3%d0%b0%d1%8f%d1%85" aria-label="Heading self-link"></a></h2> -<p><img src="http://localhost:1313/blog/complex-prog/graph1.jpeg"></p> -<p><strong>Итоговая статистика</strong></p> -<p><img src="http://localhost:1313/blog/complex-prog/graph2.png"></p> -<p><strong>Объем кода синтаксического анализатора Yacc/Bison</strong></p> -<p><img src="http://localhost:1313/blog/complex-prog/graph3.jpeg"></p> -<p><strong>Объем общей которой базы GCC (только для языков C и C++)</strong></p> -<h2 id="выводы">Выводы<a class="td-heading-self-link" href="#%d0%b2%d1%8b%d0%b2%d0%be%d0%b4%d1%8b" aria-label="Heading self-link"></a></h2> -<p>К сожалению, синтаксический анализатор Yacc/Bison использовался только до 3 версии, а после его использование свелось на нет. -Поэтому оценить сложность синтаксиса С/С++ с помощью объема кода парсера можно лишь примерно до 1996-98 года, -после чего его стали постепенно выпиливать, т.е. чуть менее, чем за десять лет. -Но даже за этот период объем кодовой базы синтаксического анализатора вырос двукратно, что примерно соответствует по времени реализации стандарта C99.</p> -<p>Но даже если не учитывать код синтаксического анализатора, то объем общей кодовой базы так же коррелирует с внедрением новых стандартов C++: C99, С11 и C14.</p> -<p>На графике не видно выраженного пика для С+17 и следующих версий, но предполагаю, -что при текущем объеме кодой базы (более 4 миллионов строк только С и С++ кода), несколько тысяч строк, -необходимых для поддержки синтаксических конструкций новых стандартов просто незаметно.</p> -<h3 id="вывод-первый---очевидный-рост-сложности-инструментов-разработки">Вывод первый - очевидный. Рост сложности инструментов разработки<a class="td-heading-self-link" href="#%d0%b2%d1%8b%d0%b2%d0%be%d0%b4-%d0%bf%d0%b5%d1%80%d0%b2%d1%8b%d0%b9---%d0%be%d1%87%d0%b5%d0%b2%d0%b8%d0%b4%d0%bd%d1%8b%d0%b9-%d1%80%d0%be%d1%81%d1%82-%d1%81%d0%bb%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b8%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d1%80%d0%b0%d0%b7%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b8" aria-label="Heading self-link"></a></h3> -<p>Фактически на примере проекта GCC можно видеть постоянный и неотвратимый рост сложности рабочих инструментов программистов.</p> -<p>И как бы не говорили о деградации разработки в статье <a href="https://habr.com/company/itelma/blog/550620/">&ldquo;Хорошие времена рождают слабаков&rdquo;</a>, -о системном кризисе программного обеспечения, который носит поколенческом характер, но мне кажется тут дело немного в другом.</p> -<p>Обновление персонала и как следствие — необходимость обучения новых сотрудников старым наработкам, -тут дело не сколько в передаче знаний, сколько в возможности эти знания усваивать.</p> -<p>Причем возможность усвоения знаний для разных поколений будет разная, но не из-за того, что предыдущее поколение было умнее, а у нового поколения не хватает толку в этом разобрать. -Просто изменяется окружение и усложняются рабочие инструменты, по сравнению с теми, которые были в ходу у предыдущего поколения.</p> -<h3 id="вывод-второй--порог--входа">Вывод второй — порог входа<a class="td-heading-self-link" href="#%d0%b2%d1%8b%d0%b2%d0%be%d0%b4-%d0%b2%d1%82%d0%be%d1%80%d0%be%d0%b9--%d0%bf%d0%be%d1%80%d0%be%d0%b3--%d0%b2%d1%85%d0%be%d0%b4%d0%b0" aria-label="Heading self-link"></a></h3> -<p>Представьте, что нужно «сделать свой сайт». Естественно нужно определить, какую CMS для него использовать и какой брать хостинг. -И если с хостингом вопрос решается очень просто, конечно же в TimeWeb, да еще и <a href="https://timeweb.com/services/hosting?utm_source=rsashka&utm_medium=timeweb&utm_campaign=timeweb-bring-a-friend">с бонусом по ссылке</a>, то при выборе CMS приходится подумать.</p> -<p>И если для простых сайтов существуют и простые решения, то для тех, кто не ищет легких путей существует CMS Drupal, -который примечателен тем, что имеет фантастически высокий порог входа для начала использования.</p> -<p><img alt="Сложность внедрения Drupal" src="http://localhost:1313/blog/complex-prog/drupal.jpeg"></p> -<p>Это я к чему? При использовании любого инструмента, как и языка программирования, существует некий минимальный уровень комфортного использования. -Причем этот уровень прямо пропорционально связан с размером той целевой аудитории, для которой он предназначен. -Точнее, размер возможной аудитории определяется в том числе и требованиями к уровню начальных знаний и квалификации потенциального пользователя.</p> -<h3 id="итоговый-вывод--не-утешительный">Итоговый вывод — не утешительный<a class="td-heading-self-link" href="#%d0%b8%d1%82%d0%be%d0%b3%d0%be%d0%b2%d1%8b%d0%b9-%d0%b2%d1%8b%d0%b2%d0%be%d0%b4--%d0%bd%d0%b5-%d1%83%d1%82%d0%b5%d1%88%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d1%8b%d0%b9" aria-label="Heading self-link"></a></h3> -<p>Если рассматривать увеличение сложности только самого ПО, то это одно дело. Вот к примеру:</p> -<p><strong>Статистика ядра Linux с вики</strong></p> -<pre tabindex="0"><code>17 сентября 1991: Linux версии 0.01 (10 239 строк кода). -14 марта 1994: Linux версии 1.0.0 (176 250 строк кода). -Март 1995: Linux версии 1.2.0 (310 950 строк кода). -9 июня 1996: Linux версии 2.0.0 (777 956 строк кода). -25 января 1999: Linux версии 2.2.0, изначально довольно недоработанный (1 800 847 строк кода). -4 января 2001: Linux версии 2.4.0 (3 377 902 строки кода). -18 декабря 2003: Linux версии 2.6.0 (5 929 913 строк кода). -23 марта 2009: Linux версии 2.6.29, временный символ Linux — тасманский дьявол Tuz (11 010 647 строк кода). -22 июля 2011: релиз Linux 3.0 (14,6 млн строк кода). -24 октября 2011: релиз Linux 3.1. -15 января 2012: релиз Linux 3.3 преодолел отметку в 15 млн строк кода. -23 февраля 2015: первый релиз-кандидат Linux 4.0 (более 19 млн строк кода). -7 января 2019: первый релиз-кандидат Linux 5.0 (более 26 млн строк кода). -</code></pre><p>А что делать, если сложность программного обеспечения накладывается на тенденцию постоянного усложнения самих рабочих инструментов? -Ведь постоянное развитие языков программирования неизбежно повышает порог входа для всех начинающих и только усугубляет проблему сложности разработки ПО.</p> -<p>Другими словами, не зависимо от того, как хорошо документирован код и как полно он покрыт тестами, -через некоторое время устаревают используемые инструменты, завершаются жизненные циклы внешних зависимостей, -и самое главное, приходят новые люди взамен тех, кто разработал или сумел разобраться в системе.</p> -<p>И у новых людей возникает необходимость разбираться в системе с самого начала, но в других начальных условиях. -И из-за этого, сложность изучения системы для всех новых людей будет выше просто по факту того, -что изменились внешние условия и усложнились рабочие инструменты, которыми приходится использовать новым сотрудникам.</p> -<p>Понятно, что чем дальше, тем проще уже не будет. Ведь область IT , это среда с самой высокой конкуренцией. -И как уж тут не вспомнить Льюиса Кэррола, что его крылатое выражение</p> -<blockquote> -<p>Нужно бежать со всех ног, чтобы только оставаться на месте, а чтобы куда-то попасть, надо бежать как минимум вдвое быстрее!</p> -</blockquote> -<p>Ведь это относится не только к Алисе в стране чудес, но и ко всем информационным технологиям в целом!</p> -<p><a href="https://habr.com/companies/timeweb/articles/551754/">Первоначальная публикация</a></p> - - - - - - Blog: Какая «идеальная» цель развития у языков программирования? - http://localhost:1313/blog/lang-final/ - Wed, 07 Apr 2021 00:00:00 +0000 - - http://localhost:1313/blog/lang-final/ - - - - <p><img alt="КДПВ" src="http://localhost:1313/blog/lang-final/lang-final.jpeg"></p> -<p>С постоянной периодичностью появляется информация о выходе новой версии того или иного языка программирования. -И с каждой новой версией расширяются его возможности, добавляются новые синтаксические конструкции или иные улучшения.</p> -<p>И это очень сильно напоминает развитие технологий, как и в любой другой области техники. -Когда с очередным этапом совершенствуются создаваемые творения. -Быстрее, выше, сильнее … и одновременно значительно сложнее.</p> -<p>Об этой проблеме меня заставила задуматься первоапрельская статья <a href="https://habr.com/post/550270/">«Доказательное программирование»</a>.</p> -<p>Понятно, что дата публикации статьи говорит сама за себя. -Тем не менее, новые стандарты С++, постоянно выходящие спецификации Java или новый синтаксис у PHP 8, -невольно заставляют задуматься, а в нужную ли сторону идет развитие языков программирования? -Ведь большинство нововведений добавляют сложность в основной рабочий инструмент и решая одни проблемы, неявно добавляя множество других.</p> -<p>А что должно быть в конце прогресса у развития такой дисциплины как программирование? -Или хотя бы у одного конкретного языка? Ради достижения какой конечной «идеальной» цели разрабатываются новые стандарты языков программирования?</p> -<p>Если фантазировать об идеальной конечной цели развития, например транспорта, -то это будет мгновенное перемещение на любое расстояние с произвольной полезной нагрузкой и нулевым потреблением энергии.</p> -<p>Или, например, какая может быть идеальная цель у медицины? <del>Бедные не болели, а богатые не выздоравливали,</del> вероятно, лечение любых болезней и биологическое бессмертие.</p> -<p>Конечно, «идеальная» цель это очень упрощенное понятие. Фактически, «идеальная» это синоним «недостижимая», -т.к. она всегда будет упираться необходимость соблюдать компромисс между различными взаимно-исключающими граничными условиями.</p> -<p>Но сравнивать разработку средств программирования с процессом развития в других технических дисциплинах напрямую нельзя. -Ведь при создание конечного продукта в любой технической области, все сложные производственные операции, -которые требуют непосредственного участия человека, практически всегда можно разделить на отдельные, более простые части или этапы.</p> -<p>Это делается, в том числе и для того, чтобы сложность одной выполняемой операции не была запредельной для исполнителя. -Но как это можно сделать при разработке программного обеспечения?</p> -<p>В данном случае, я имею ввиду конечную ограниченность возможностей одного конкретного человека в противовес возможностям разделения технологических процессов на отдельные этапы, -каждый из которых может выполняться совершенно разными людьми (как пример, это обычный конвеер с его разделением труда на элементарные операции -или узкая специализация врачей-специалистов в одной конкретной области).</p> -<p>Ведь даже сложно себе представить фантастическую организацию труда программистов в виде конвеера:</p> -<ul> -<li>Первый разработчик пишет только интерфейсы функций и их вызовы, после чего передает код второму сотруднику.</li> -<li>Второй пишет в тексте программы только условия проверки и безусловные переходы и передает текст третьему.</li> -<li>Третий отвечает за написание циклов и общее форматирование кода и т.д. -и результате ожидаемо получится полный бред.</li> -</ul> -<p>Из-за этого индустрия разработки ПО вынуждена идти по экстенсивному пути развития (т.е. за счет увеличения используемых в производстве ресурсов). -Современные промышленные языки программирования имеют очень богатые возможности по разделению кода приложения на отдельные функции/модули/компоненты, -что позволяет вести разработку сложного программного продукта сразу множеству сотрудников одновременно.</p> -<p>Но и такое развитие имеет естественное ограничение. И этим ограничением является сам человек, -так как каждый разработчик должен знать и уметь пользоваться своим рабочим инструментом, т.е. языком программирования.</p> -<p>Если взять приведенную выше аналогию с конвеером, то в ней каждый рабочий должен был бы досконально знать б<strong>о</strong>льшую часть используемых станков -и инструментов на всем заводе, независимо от того, какую <strong>одну</strong> конкретную операцию он выполняет на своем рабочем месте.</p> -<p>Ведь парадокс развития языков программирования заключается в том, что добавляя новые возможности и синтаксические конструкции, -мы усложняем рабочий инструмент, предназначенный как для совместного, так и для индивидуального использования!</p> -<p>И получается, что одновременно с процессом постоянного наращивания возможностей средств разработки идет -и обратный процесс — увеличение сложности разработки кода отдельно взятым разработчиком. -Фактически, это и есть то самое взаимоисключающее непреодолимое противоречие.</p> -<p>Может быть именно поэтому невозможно найти «серебряную пулю», которая бы повышала производительность труда одного программиста? -Ведь внимание и возможности человека не безграничны. -И любые новшества и улучшения рабочего инструмента программиста вынужденно толкают всю IT индустрию на экстенсивный путь развития.</p> -<p>Возможно следует разрабатывать принципиально новые подходы, а не гнаться за синтаксическим сахаром в языках программирования из прошлого века? -Или и вовсе не париться, продолжать пользоваться тем, что есть, а теория дедушки Дарвина все сама расставит по своим местам?</p> -<p><a href="https://habr.com/companies/timeweb/articles/551224/">Первоначальная публикация</a></p> - - - - - - Blog: Проблема логических языков программирования - http://localhost:1313/blog/logic-prog/ - Sat, 09 Jan 2021 00:00:00 +0000 - - http://localhost:1313/blog/logic-prog/ - - - - <p><img alt="КДПВ" src="http://localhost:1313/blog/langs.jpeg"></p> -<p>Некоторое время назад я писал про <a href="http://localhost:1313/blog/inter-prog/">«Интернациональное программирование на естественных языках»</a>, -в которой попытался представить достойную цель для абстрактного языка программирования, -попробовав примерить на него роль связующего звена между миром программистов с компьютерами и не программистов.</p> -<p>Но в результате оказалось, что это не нужно в принципе, т.к. «не программистам» просто не требуется учиться писать программы. -А если иногда такое желание и возникает, то вполне хватает обычных формализованных языков программирования, -которых уже сейчас насчитывается наверно более десяти тысяч.</p> -<p>А пользователи, как программисты, так и не программисты, просто хотят решать возникающие перед ними задачи. -И хотя задачи бывают совершенно разные, но если способ (алгоритм) её решения известен, то выбрать язык для её решения не составит никакого труда.</p> -<p>За исключением одного класса задач. Задач, решение которых нельзя описать в виде алгоритма. -Но можно указать некие критерии, которым должно удовлетворять искомое решение.<br> -Я имею ввиду логические языки программирования и <a href="https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%BE%D0%BB%D0%BE%D0%B3_%28%D1%8F%D0%B7%D1%8B%D0%BA_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29">Пролог</a>, как самый яркий представитель этого класса.</p> -<p>Еще помню воспоминание из юности, когда удалось достать дискету с этим языком. -Ух, с каким задором горели мои глаза, когда мне казалось, ну вот, еще чуть-чуть и будет создана система с базой знаний, -у которой и можно будет получить заветный ответ 42 на любой вопрос.</p> -<p>Так почему этого так и не случилось? В чем проблема Пролога, да и любой системы / языка программирования, -назначение которых анализировать факты и искать ответы на вопросы?</p> -<p>Эта проблема называется <a href="https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BC%D0%B1%D0%B8%D0%BD%D0%B0%D1%82%D0%BE%D1%80%D0%BD%D1%8B%D0%B9_%D0%B2%D0%B7%D1%80%D1%8B%D0%B2">«Комбинаторный взрыв»</a> - экспоненциальная (или более) зависимость времени работы алгоритма от количества входных данных. -И есть как минимум два решения этой проблемы.</p> -<h2 id="подходы-к-написанию-программ">Подходы к написанию программ<a class="td-heading-self-link" href="#%d0%bf%d0%be%d0%b4%d1%85%d0%be%d0%b4%d1%8b-%d0%ba-%d0%bd%d0%b0%d0%bf%d0%b8%d1%81%d0%b0%d0%bd%d0%b8%d1%8e-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc" aria-label="Heading self-link"></a></h2> -<p>Прежде чем переходить к частностям, следует сказать пару слов про парадигмы программирования. -Обычно противопоставляют между собой два разных стиля в написании программ: <a href="https://ru.wikipedia.org/wiki/%D0%98%D0%BC%D0%BF%D0%B5%D1%80%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5">императивный</a> и <a href="https://ru.wikipedia.org/wiki/%D0%94%D0%B5%D0%BA%D0%BB%D0%B0%D1%80%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5">декларативный</a>.</p> -<p>Императивный — это классический вариант написания программы, при котором программист сам задает шаги алгоритма для получения конечного результата. -А сам текст программы состоит из последовательности команд, которые читают, сохраняют и обрабатывают данные или вызывают другие команды.</p> -<p>Декларативный — в этом стиле программист описывает условия задачи и правила для получения требуемого результата, -но не требуется детально описывать все шаги работы алгоритма, оставляя их на усмотрения компьютера.</p> -<p>Именно к декларативному стилю относится язык Пролог, да и все остальные логические языки программирования. -К декларативному стилю написания программ следует относить и язык структурированных запросов (SQL).</p> -<p>И проблема под называнием <a href="https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BC%D0%B1%D0%B8%D0%BD%D0%B0%D1%82%D0%BE%D1%80%D0%BD%D1%8B%D0%B9_%D0%B2%D0%B7%D1%80%D1%8B%D0%B2">«комбинаторный взрыв»</a> сильнее всего оказывает негативное влияние как раз на подобные языки. -Ведь в императивном подходе программист сам отвечает за последовательность выполняемых команд, и если он запрограммировал алгоритм полного перебора всех возможных вариантов решений, то он сам себе злобный Буратино.</p> -<p>Другое дело, программирование в декларативном стиле. Разработчик хоть и может указать ограничения, которые следует применять при поиске решения, -но это возможно только в том случае, когда известен алгоритм решения задачи. -Но если алгоритм решения известен, то проще использовать императивный стиль, как раз и реализуя этот алгоритм!</p> -<p>Поэтому основное применения языков программирования в декларативном стиле — отказаться от необходимости описания четкого алгоритма поиска решения, -отдав это компьютеру на откуп. Для которого самое простое решение «в лоб» - полный перебор возможных вариантов.</p> -<p>Именно в этом случае и начинается экспоненциальный рост времени выполнения алгоритма. -И начиная с определенного порога, время ожидания ответа становится неприемлемым для реального использования. -Это и означает «Комбинаторный взрыв», резкий («взрывной») рост времени выполнения алгоритма при увеличении размера входных данных.</p> -<h2 id="проблема-поиска-решений">Проблема поиска решений<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%be%d0%b1%d0%bb%d0%b5%d0%bc%d0%b0-%d0%bf%d0%be%d0%b8%d1%81%d0%ba%d0%b0-%d1%80%d0%b5%d1%88%d0%b5%d0%bd%d0%b8%d0%b9" aria-label="Heading self-link"></a></h2> -<p>В языке Пролог эта проблема решалась за счет использования механизма отката и отсечений. -Иногда еще уточняли про «красное» и «зеленое» отсечение решений. -Но в любом случае, это были <strong>алгоритмические</strong> механизмы для ограничения количества размера дерева возможных решений, -а необходимость их применения все равно остается на программисте.</p> -<p>Но чтобы их правильно реализовывать, нужно знать алгоритм решения, что опять возвращает нас к утверждению о том, -что если известен алгоритм, то и программировать его удобнее в императивном стиле.</p> -<p>А если полный алгоритм решения задачи не известен (или не подходит, например из-за большого времени для его работы), -то в результате остается либо увеличивать производительность системы, чтобы сократить время выполнения алгоритма, -либо искать другое решение, в том числе, сокращая вычислительную сложность поиска решений, например, исключая заведомо не подходящие данные, -чтобы уменьшить возможные комбинации их перебора.</p> -<h3 id="масштабирование-производительности">Масштабирование производительности<a class="td-heading-self-link" href="#%d0%bc%d0%b0%d1%81%d1%88%d1%82%d0%b0%d0%b1%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%bf%d1%80%d0%be%d0%b8%d0%b7%d0%b2%d0%be%d0%b4%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d0%be%d1%81%d1%82%d0%b8" aria-label="Heading self-link"></a></h3> -<p>Увеличение производительности тоже бывает разным и работает не во всех случаях. -Вертикальное масштабирование производительности одного узла вычислительной среды имеет свой естественный предел. -И даже многократное увеличение скорости работы компьютера может лишь отдалить порог терпения пользователя при ожидании получения результата, -но не в состоянии принципиально решить саму проблему.</p> -<p>Другое дело горизонтальное масштабирование, при котором выполнение алгоритма запускается на отдельных узлах, которые параллельно решают одну и ту же задачу. -Такой способ масштабирования позволяет уже значительно сократить время получения итогового результата для сложных вычислительных задач. -И хотя это способ является решением «в лоб», но успехи в области data science доказывают успешность такого подхода.</p> -<p>Конечно, у горизонтального масштабирования тоже есть подводные камни. -В первую очередь, сам алгоритм должен допускать возможность параллельного выполнения независимо от других узлов. -Также требуется автоматизация управления заданиями, самими вычислительными узлами, да и всей системой в целом.</p> -<p>Тут частично может помочь парадигма функционального программирования, которая ограничивает результат вычисления функций только входными параметрами -и результатом выполнения других функций, но сам результат не зависит от состояния системы или иных внешних данных.</p> -<h3 id="поиск-обобщенного-решения">Поиск обобщенного решения<a class="td-heading-self-link" href="#%d0%bf%d0%be%d0%b8%d1%81%d0%ba-%d0%be%d0%b1%d0%be%d0%b1%d1%89%d0%b5%d0%bd%d0%bd%d0%be%d0%b3%d0%be-%d1%80%d0%b5%d1%88%d0%b5%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h3> -<p>Вторым способом решения решения проблемы комбинаторного взрыва является уменьшение вычислительной сложности решения. -Тут имеется ввиду не выбор другого алгоритма или решение задачи в символьном виде. -Если такое возможно, то все опять сразу сведется к императивному стилю программированию.</p> -<p>Я имею ввиду возможность поиска самого алгоритма решения. -Точнее не совсем алгоритма, а возможность применения к входным данным различные методы отбора, чтобы исключить необходимость их полного перебора. -По сути, это сводится к применению различных методов и механизмов обработки входных данных с учетом различных закономерностей.</p> -<p>Это возможно как алгоритмическими методами (откат и отсечение в Прологе), так и с применением машинного обучения, -которое очень хорошо справляется с поиском различных закономерностей.</p> -<p>Естественно, такой способ подходит не для всех классов задач. Он не подходит для выявления <strong>ВСЕХ возможных решений</strong>. -Но там где это не требуется, подобные способы уменьшения вычислительной сложности имеют право на существование.</p> -<p>Например, не требуется искать все возможные лекарства от конкретной болезни, достаточно <strong>одного</strong>, с учетом определенных ограничений, которое гарантированно подействует.</p> -<p>К тому же, даже при нахождении частных решений, всегда существует шанс, что с их помощью получится увидеть не очевидные на первый взгляд закономерности, -которые помогут показать новые пути алгоритмического уменьшения вычислительной сложности основной задачи.</p> -<h2 id="область-не-решаемых-задач">Область не решаемых задач<a class="td-heading-self-link" href="#%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bd%d0%b5-%d1%80%d0%b5%d1%88%d0%b0%d0%b5%d0%bc%d1%8b%d1%85-%d0%b7%d0%b0%d0%b4%d0%b0%d1%87" aria-label="Heading self-link"></a></h2> -<blockquote> -<p>Как вы считает, а реально ли создать язык логического программирования, который бы сам умел автоматизировать поиск решений для задач подобных классов? Или хотя бы имел в своем арсенале встроенные механизмы для автоматизации подобной деятельности?</p> -</blockquote> -<h3 id="результаты-опроса-из-оригинальной-публикацииhttpshabrcomarticles536268">Результаты опроса из <a href="https://habr.com/articles/536268/">оригинальной публикации</a><a class="td-heading-self-link" href="#%d1%80%d0%b5%d0%b7%d1%83%d0%bb%d1%8c%d1%82%d0%b0%d1%82%d1%8b-%d0%be%d0%bf%d1%80%d0%be%d1%81%d0%b0-%d0%b8%d0%b7-%d0%be%d1%80%d0%b8%d0%b3%d0%b8%d0%bd%d0%b0%d0%bb%d1%8c%d0%bd%d0%be%d0%b9-%d0%bf%d1%83%d0%b1%d0%bb%d0%b8%d0%ba%d0%b0%d1%86%d0%b8%d0%b8httpshabrcomarticles536268" aria-label="Heading self-link"></a></h3> -<pre tabindex="0"><code>- 57.47% Ха-ха! То, что хочет автор и называется искусственным интеллектом (50 голосов) -- 27.59% Поиск решений нельзя автоматизировать (24 голоса) -- 19.54% Это уже есть и все давно придумано (17 голосов) -- 9.2% Такой язык не нужен, т.к. нейросети могут всё (8 голосов) -- 3.45% Свой вариант написал в комменатрии (3 голоса) -</code></pre><p>Проголосовали 87 пользователей. Воздержались 62 пользователя.</p> - - - - - - Blog: Интернациональное программирование на естественных языках - http://localhost:1313/blog/inter-prog/ - Sat, 05 Dec 2020 00:00:00 +0000 - - http://localhost:1313/blog/inter-prog/ - - - - <p><img alt="КДПВ" src="http://localhost:1313/blog/langs.jpeg"></p> - - -<div class="pageinfo pageinfo-primary"> -<p>Внимание!!!</p> -<p>Данная статья содержит описание синтаксиса NewLnag предыдущей версии.</p> -<p>Актуальную версию синтаксиса языка можно посмотреть <a href="http://localhost:1313/docs/">тут</a>.</p> - -</div> - -<p>В последнее время часто попадаются на глаза статьи о новых языках программирования, -а так же различные рейтинги и прогнозы, связанные с популярностью компьютерных языков.</p> -<p>Заявляют о себе и новые <a href="https://habr.com/company/testo_lang/blog/521682/">инструментальные средства</a>, -которые в своей работе используют собственные форматы описания конфигурационных файлов или последовательности выполняемых команд, -которые так же очень сильно приближает их к понятию «язык программирования».</p> -<p>Цель написания данной статьи — формулировка ожиданий и возможной реализации абстрактного языка программирования, -который может стать универсальным инструментом для общения между компьютером и человеком.</p> -<h2 id="о-программистах">О программистах<a class="td-heading-self-link" href="#%d0%be-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%81%d1%82%d0%b0%d1%85" aria-label="Heading self-link"></a></h2> -<p>Если начинать с самого начала, то когда-то давно я слышал перефразированное высказывание, -«каждый программист должен написать свою базу данных, текстовый редактор и язык программирования». -И если первые две вещи я уже давным давно написал, то с языком программирования пока не сложилось.</p> -<p>Ведь как обычно создаются языки программирования?</p> -<p>У каждого программиста всегда есть какой-то своей предыдущий опыт:</p> -<ul> -<li>знания одного или нескольких языков программирования (как же без этого)</li> -<li>негативный опыт от их использования (в противном случае, если все устраивает, то зачем придумывать что-то новое?)</li> -<li>желания получить новые возможности (когда в существующих языках чего-то не хватает)</li> -</ul> -<p>А перед тем, как описывать синтаксис, выбирать ключевые слова и начинать основную работу: -лексер, парсер, базовые библиотеки, нужно дать ответ на основные вопросы:</p> -<ul> -<li>Компилятор/интерпретатор/транспилятор(transpiler)?</li> -<li>Статическая или динамическая типизация?</li> -<li>Ручное управление памятью или автоматическое со сборщиком мусора?</li> -<li>Модель программирования: ООП, функциональное, структурное или что-то новое?</li> -<li>Разрешены ли вставки из других языков программирования и т. д.?</li> -</ul> -<p>У меня, наверно, как и у большинства читателей, присутствует опыт использования нескольких языков программирования. -Поэтому давно сложилось практика, что для решения задачи лучше взять известный язык или даже выучить новый, вместо того, -чтобы начинать писать собственный.</p> -<p>Тем более, что не хочется придумывать еще один язык просто ради галочки или ради самого языка. -Я считаю, что цель его создания должна быть за пределами потребностей самого разработчика.</p> -<p>И мне кажется, что удалось определить область, для которой разработка языка программирования может быть востребованной, -а потраченные на него усилия могут принести реальную пользу.</p> -<h2 id="о-не-программистах">О не программистах<a class="td-heading-self-link" href="#%d0%be-%d0%bd%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%81%d1%82%d0%b0%d1%85" aria-label="Heading self-link"></a></h2> -<p>Эта область — программирование для «не программистов» на «естественном» языке. -Я специально взял слова «не программистов» и «естественном» в кавычки, т.к. эти термины являются очень условными.</p> -<p>Ведь если не программист начинает программировать, то сам того не осознавая, он автоматически становится программистом ;-). -А «естественным» язык программирования быть не может по определению. -Точнее для компьютеров скорее всего «естественным» будет язык Assembler или набор машинных команд.</p> -<blockquote> -<p>Поэтому, цель максимум — приблизить язык программирования к естественному человеческому языку.</p> -</blockquote> -<p>Это не только сделает чтение текста программы более понятным для не профессионалов, -но и позволит начинать составлять программы просто освоив письменную речь, используя самый минимум основных правил.</p> -<p>Но в подобной формулировке кроется очень большая проблема!</p> -<blockquote> -<p>Любой язык программирования является интернациональным, т.к. его синтаксис не зависит от естественного языка, на котором общается программист.</p> -</blockquote> -<p>А если текст программы будет на &ldquo;естественном&rdquo; языке, то она станет понятной только для знающих этот язык, -одновременно становясь непонятной для всех остальных.</p> -<p>В качестве иллюстрации: <a href="http://espressocode.top/natural-language-programming/">раз</a> или <a href="https://habr.com/post/268401/">два</a>. -Если пофантазировать насчет хотелок к такому языку, то видятся следующие требования и ограничения:</p> -<ul> -<li>Так как каждый пользователь является носителем своего родного естественного языка (или даже нескольких), то жестко задавать ключевые слова невозможно, из чего следует, что основой такого языка должны стать только правила пунктуации, но никак не лексика или грамматика.</li> -<li>Компилятор/транслятор должен уметь преобразовывать исходный текст программы не только в машинный код для компьютера, но в другой вариант &ldquo;естественного&rdquo; языка, чтобы пользователь мог работать с исходным текстом на известном ему &ldquo;естественном&rdquo; языке.</li> -<li>Очень хочется видеть в новом языке <del>толерантность</del> терпимость к очепяткам. Подобная «фича» присутствует в письме на естественном языке, и несмотря на наличие опечаток, практически всегда сохраняется смысл. Естественно, в данном случае не стоит доходить до фанатизма. Компилятор не читает мысли и не может в действительности «понять», что имел ввиду пользователь, и все же довольно часто можно игнорировать опечатки в тексте программы исходя из контекста (пусть и с выводом предупреждающих сообщений).</li> -</ul> -<p>Тем не менее, такой язык должен оставаться именно языком программирования со всеми возможностями создания программ любого уровня сложности, -включая функциональное и объектно-ориентированное программирование и однозначное понимание написанного.</p> -<h2 id="о-гипотетическом-языке">О гипотетическом языке<a class="td-heading-self-link" href="#%d0%be-%d0%b3%d0%b8%d0%bf%d0%be%d1%82%d0%b5%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%be%d0%bc-%d1%8f%d0%b7%d1%8b%d0%ba%d0%b5" aria-label="Heading self-link"></a></h2> -<p>Если взять за основу правила письменной речи, то основные соглашения и пунктуация для нового языка могут выглядеть примерно так:</p> -<ul> -<li>Любой текст состоит из предложений и комментариев. Предложения обрабатываются, а комментарии игнорируются.</li> -<li>Предложение состоит из последовательности терминов, литералов и символов, разделенных пробелами и знаками препинания и завершается символом конца предложения.</li> -<li>Термин — слитно написанная последовательность букв, цифр и символов &ldquo;:&rdquo; и &ldquo;_&rdquo;.</li> -<li>Литерал — константы, включаемые непосредственно в текст программы, тип которой определяется однозначно. Это символьные строки в кавычках, целые и вещественные числа, и некоторые специальные форматы (время, дата).</li> -<li>Символы — все остальное символы, которые не относятся к знакам препинания, пробельным символам, цифрам и буквам.</li> -<li>Знаки препинания — символы пунктуации, имеющие специальное значение при разборе текста программы: -<ul> -<li>«.»,«;»,«!»,«?»,«…» — конец предложения.</li> -<li>«=» — присвоение значения.</li> -<li>&quot;&quot; (кавычки) — определение символьной строки.</li> -<li>«()» - передача параметров/аргументов или группировка операторов для определения приоритета выполнения операций.</li> -<li>«[]» - массив или обращение к элементу массива.</li> -<li>«{}» - включение в текст исходного кода программы на обычном языке программирования.</li> -<li>«$» — системная переменная.</li> -<li>«@» — системная функция.</li> -<li>«,» (запятая) — перечисление.</li> -<li>«:» (двоеточие) — список или логическая связь.</li> -</ul> -</li> -</ul> -<p>Если с символом присвоения, кавычками, круглыми и квадратными скобками все должно быть более-менее понятно, -т.к. их назначение соответствует аналогичному в подавляющем большинстве языков программирования, -то про назначение остальных символов (фигурных скобок, двоеточия, запятой и системных функций/переменной), следует немного пояснить.</p> -<p>Раз цель гипотетического языка программирования все же написание программ, -то необходимо предусмотреть возможность делать вставки обычного программного кода без учета всех возможностей и неоднозначностей, -которые присущи любому естественному языку.</p> -<p>Так же эта возможность требуется для реализации низкоуровневых функций и для взаимодействия с внешними библиотеками.</p> -<p>При создании подобных вставок и могут использоваться фигурные скобки, весь текст между которыми будет вставляться в итоговый файл практически без обработки.</p> -<p>Для похожих целей служат и символы «$» — системная переменная и «@» — системная функция. Если такой символ поставить в начале слова, -тогда он станет обозначать объект с соответствующим назначением. Например «@exit» — будет означать функцию, -а «$var» — переменную с соответствующими именами, а сами объекты станут доступны как в обычном коде, -так и в программных вставках внутри фигурных скобок.</p> -<p>Аналогичным образом организуется и доступ к отдельным полям/методам объектов: -«объект@метод» или «объект$поле».</p> -<p>Символ запятая «,» применяется для указание последовательности равноправных логических блоков в одном предложении или для создания списков.</p> -<p>Символ двоеточия «:» используется для создания списков и для обозначения логической связи между двумя частями слова/текста, в том числе для указания полного пути модуля.</p> -<p>Например, создание списка:</p> -<p><code>В_строку: элемент 1, элемент 2, последний элемент.</code></p> -<pre tabindex="0"><code>Форматированный_список: -- элемент 1; -- элемент 2; -- последний элемент. -</code></pre><p>Логическое следствие/указание связи:</p> -<pre tabindex="0"><code>module:calc //термин «calc», который находится в модуле «module» -super:module:example$var //переменная «$var» которая находится в указанной иерархии. -</code></pre><p>Как можно заметить, использование знаков препинания взято из их прямого назначения, принятого в письменной речи, -что должно обеспечить определенный компромисс между синтаксисом в стандартных языках программирования и письмом на естественном языке.</p> -<h2 id="о-компьютерах">О компьютерах<a class="td-heading-self-link" href="#%d0%be-%d0%ba%d0%be%d0%bc%d0%bf%d1%8c%d1%8e%d1%82%d0%b5%d1%80%d0%b0%d1%85" aria-label="Heading self-link"></a></h2> -<p>Так как речь идет все же о языке программирования, то не обойтись без стандартных алгоритмических конструкций: следования, ветвления и циклов.</p> -<p>Следование легко описывается обычными правилам письма на естественном языке. -В случае последовательного выполнения в одном предложении, операции и вызовы функций записываются последовательно через запятую. -Если они располагаются в разных предложениях, то они записываются так же друг за другом. -Причем форматирование по абзацам служит только для лучшего восприятия текста и логического разделения отдельных фрагментов.</p> -<p>При создании условных и циклических управляющих конструкций уже потребуются ключевые слова. -Но так как согласно исходным пожеланиям к языку, резервировать обычные термины для записи алгоритмических конструкций нельзя, -то перед ключевыми словами достаточно указывать символ системной функции, что позволит отличить обычный термин от ключевого (управляющего) слова.</p> -<p>Естественно, при программировании, данными терминами хоть и можно будет пользоваться, но делать это совсем не обязательно. -Так как при настройке под конкретный естественный язык, системным функциям и ключевым словам нужно обязательно присвоить конкретные термины и пользоваться уже ими, например:</p> -<pre tabindex="0"><code>перейти = @goto, -метка = @label, -продолжить = @continue, -прервать=@break и т.д. -</code></pre><p>И последняя по очереди, но наверно самая важная по сути конструкция: передача параметров при вызовах функций. -Если стремиться к полностью естественному синтаксису, тогда мы получим тот самый естественный язык, который очень сложно анализировать.</p> -<p>Тем не менее, мне кажется, что можно скомбинировать оба два подхода, если отказаться от обязательного использования круглых скобок, -там, где это допустимо по синтаксису.</p> -<pre tabindex="0"><code>Компьютерный: функция(параметр1, функция2(), параметр3=значение). -Естественный: функция параметр1 функция2 параметр3=значение. -</code></pre><p>Но:</p> -<pre tabindex="0"><code>Компьютерный: функция( функция2(параметр) ). -Естественный: функция функция2(параметр). -Или так: функция (функция2 параметр). -</code></pre><p>Другими словами, для естественного порядка указания аргументов, скобки для функций и запятые между параметрами могут быть опущены. -Хотя их использование должно определяться в первую очередь целевым естественным языком, а не синтаксисом.</p> -<h2 id="о-возражениях">О возражениях<a class="td-heading-self-link" href="#%d0%be-%d0%b2%d0%be%d0%b7%d1%80%d0%b0%d0%b6%d0%b5%d0%bd%d0%b8%d1%8f%d1%85" aria-label="Heading self-link"></a></h2> -<p>Предвижу обоснованные возражения против использования подобного языка со стороны программистов. -Программа на нем по любому получится значительно многословнее, чем с использованием строгого формального синтаксиса обычных компьютерных языков.</p> -<p>Поэтому напомню про его обязательное свойство - умение преобразовывать текст программы с одного языка на другой. -Это позволяет писать программы как с использованием строго формального синтаксиса без использования переопеределенных терминов на естественном языке, -так и преобразовывать исходный текст в &ldquo;естественный&rdquo; язык для &ldquo;не программиста&rdquo;.</p> -<p><a href="https://habr.com/articles/531400/">Ссылка на первую публикаци</a></p> - - - - diff --git a/docs/blog/inter-prog/index.html b/docs/blog/inter-prog/index.html deleted file mode 100644 index 24a71e9b..00000000 --- a/docs/blog/inter-prog/index.html +++ /dev/null @@ -1,462 +0,0 @@ - - - - - - - - - - - - - - - - - - - -Интернациональное программирование на естественных языках | NewLang - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    -
    -
    -
    - - -
    - - - - -
    -

    Интернациональное программирование на естественных языках

    - - - -

    КДПВ

    - - -
    -

    Внимание!!!

    -

    Данная статья содержит описание синтаксиса NewLnag предыдущей версии.

    -

    Актуальную версию синтаксиса языка можно посмотреть тут.

    - -
    - -

    В последнее время часто попадаются на глаза статьи о новых языках программирования, -а так же различные рейтинги и прогнозы, связанные с популярностью компьютерных языков.

    -

    Заявляют о себе и новые инструментальные средства, -которые в своей работе используют собственные форматы описания конфигурационных файлов или последовательности выполняемых команд, -которые так же очень сильно приближает их к понятию «язык программирования».

    -

    Цель написания данной статьи — формулировка ожиданий и возможной реализации абстрактного языка программирования, -который может стать универсальным инструментом для общения между компьютером и человеком.

    -

    О программистах

    -

    Если начинать с самого начала, то когда-то давно я слышал перефразированное высказывание, -«каждый программист должен написать свою базу данных, текстовый редактор и язык программирования». -И если первые две вещи я уже давным давно написал, то с языком программирования пока не сложилось.

    -

    Ведь как обычно создаются языки программирования?

    -

    У каждого программиста всегда есть какой-то своей предыдущий опыт:

    -
      -
    • знания одного или нескольких языков программирования (как же без этого)
    • -
    • негативный опыт от их использования (в противном случае, если все устраивает, то зачем придумывать что-то новое?)
    • -
    • желания получить новые возможности (когда в существующих языках чего-то не хватает)
    • -
    -

    А перед тем, как описывать синтаксис, выбирать ключевые слова и начинать основную работу: -лексер, парсер, базовые библиотеки, нужно дать ответ на основные вопросы:

    -
      -
    • Компилятор/интерпретатор/транспилятор(transpiler)?
    • -
    • Статическая или динамическая типизация?
    • -
    • Ручное управление памятью или автоматическое со сборщиком мусора?
    • -
    • Модель программирования: ООП, функциональное, структурное или что-то новое?
    • -
    • Разрешены ли вставки из других языков программирования и т. д.?
    • -
    -

    У меня, наверно, как и у большинства читателей, присутствует опыт использования нескольких языков программирования. -Поэтому давно сложилось практика, что для решения задачи лучше взять известный язык или даже выучить новый, вместо того, -чтобы начинать писать собственный.

    -

    Тем более, что не хочется придумывать еще один язык просто ради галочки или ради самого языка. -Я считаю, что цель его создания должна быть за пределами потребностей самого разработчика.

    -

    И мне кажется, что удалось определить область, для которой разработка языка программирования может быть востребованной, -а потраченные на него усилия могут принести реальную пользу.

    -

    О не программистах

    -

    Эта область — программирование для «не программистов» на «естественном» языке. -Я специально взял слова «не программистов» и «естественном» в кавычки, т.к. эти термины являются очень условными.

    -

    Ведь если не программист начинает программировать, то сам того не осознавая, он автоматически становится программистом ;-). -А «естественным» язык программирования быть не может по определению. -Точнее для компьютеров скорее всего «естественным» будет язык Assembler или набор машинных команд.

    -
    -

    Поэтому, цель максимум — приблизить язык программирования к естественному человеческому языку.

    -
    -

    Это не только сделает чтение текста программы более понятным для не профессионалов, -но и позволит начинать составлять программы просто освоив письменную речь, используя самый минимум основных правил.

    -

    Но в подобной формулировке кроется очень большая проблема!

    -
    -

    Любой язык программирования является интернациональным, т.к. его синтаксис не зависит от естественного языка, на котором общается программист.

    -
    -

    А если текст программы будет на “естественном” языке, то она станет понятной только для знающих этот язык, -одновременно становясь непонятной для всех остальных.

    -

    В качестве иллюстрации: раз или два. -Если пофантазировать насчет хотелок к такому языку, то видятся следующие требования и ограничения:

    -
      -
    • Так как каждый пользователь является носителем своего родного естественного языка (или даже нескольких), то жестко задавать ключевые слова невозможно, из чего следует, что основой такого языка должны стать только правила пунктуации, но никак не лексика или грамматика.
    • -
    • Компилятор/транслятор должен уметь преобразовывать исходный текст программы не только в машинный код для компьютера, но в другой вариант “естественного” языка, чтобы пользователь мог работать с исходным текстом на известном ему “естественном” языке.
    • -
    • Очень хочется видеть в новом языке толерантность терпимость к очепяткам. Подобная «фича» присутствует в письме на естественном языке, и несмотря на наличие опечаток, практически всегда сохраняется смысл. Естественно, в данном случае не стоит доходить до фанатизма. Компилятор не читает мысли и не может в действительности «понять», что имел ввиду пользователь, и все же довольно часто можно игнорировать опечатки в тексте программы исходя из контекста (пусть и с выводом предупреждающих сообщений).
    • -
    -

    Тем не менее, такой язык должен оставаться именно языком программирования со всеми возможностями создания программ любого уровня сложности, -включая функциональное и объектно-ориентированное программирование и однозначное понимание написанного.

    -

    О гипотетическом языке

    -

    Если взять за основу правила письменной речи, то основные соглашения и пунктуация для нового языка могут выглядеть примерно так:

    -
      -
    • Любой текст состоит из предложений и комментариев. Предложения обрабатываются, а комментарии игнорируются.
    • -
    • Предложение состоит из последовательности терминов, литералов и символов, разделенных пробелами и знаками препинания и завершается символом конца предложения.
    • -
    • Термин — слитно написанная последовательность букв, цифр и символов “:” и “_”.
    • -
    • Литерал — константы, включаемые непосредственно в текст программы, тип которой определяется однозначно. Это символьные строки в кавычках, целые и вещественные числа, и некоторые специальные форматы (время, дата).
    • -
    • Символы — все остальное символы, которые не относятся к знакам препинания, пробельным символам, цифрам и буквам.
    • -
    • Знаки препинания — символы пунктуации, имеющие специальное значение при разборе текста программы: -
        -
      • «.»,«;»,«!»,«?»,«…» — конец предложения.
      • -
      • «=» — присвоение значения.
      • -
      • "" (кавычки) — определение символьной строки.
      • -
      • «()» - передача параметров/аргументов или группировка операторов для определения приоритета выполнения операций.
      • -
      • «[]» - массив или обращение к элементу массива.
      • -
      • «{}» - включение в текст исходного кода программы на обычном языке программирования.
      • -
      • «$» — системная переменная.
      • -
      • «@» — системная функция.
      • -
      • «,» (запятая) — перечисление.
      • -
      • «:» (двоеточие) — список или логическая связь.
      • -
      -
    • -
    -

    Если с символом присвоения, кавычками, круглыми и квадратными скобками все должно быть более-менее понятно, -т.к. их назначение соответствует аналогичному в подавляющем большинстве языков программирования, -то про назначение остальных символов (фигурных скобок, двоеточия, запятой и системных функций/переменной), следует немного пояснить.

    -

    Раз цель гипотетического языка программирования все же написание программ, -то необходимо предусмотреть возможность делать вставки обычного программного кода без учета всех возможностей и неоднозначностей, -которые присущи любому естественному языку.

    -

    Так же эта возможность требуется для реализации низкоуровневых функций и для взаимодействия с внешними библиотеками.

    -

    При создании подобных вставок и могут использоваться фигурные скобки, весь текст между которыми будет вставляться в итоговый файл практически без обработки.

    -

    Для похожих целей служат и символы «$» — системная переменная и «@» — системная функция. Если такой символ поставить в начале слова, -тогда он станет обозначать объект с соответствующим назначением. Например «@exit» — будет означать функцию, -а «$var» — переменную с соответствующими именами, а сами объекты станут доступны как в обычном коде, -так и в программных вставках внутри фигурных скобок.

    -

    Аналогичным образом организуется и доступ к отдельным полям/методам объектов: -«объект@метод» или «объект$поле».

    -

    Символ запятая «,» применяется для указание последовательности равноправных логических блоков в одном предложении или для создания списков.

    -

    Символ двоеточия «:» используется для создания списков и для обозначения логической связи между двумя частями слова/текста, в том числе для указания полного пути модуля.

    -

    Например, создание списка:

    -

    В_строку: элемент 1, элемент 2, последний элемент.

    -
    Форматированный_список:
    -- элемент 1;
    -- элемент 2;
    -- последний элемент.
    -

    Логическое следствие/указание связи:

    -
    module:calc //термин «calc», который находится в модуле «module»
    -super:module:example$var //переменная «$var» которая находится в указанной иерархии.
    -

    Как можно заметить, использование знаков препинания взято из их прямого назначения, принятого в письменной речи, -что должно обеспечить определенный компромисс между синтаксисом в стандартных языках программирования и письмом на естественном языке.

    -

    О компьютерах

    -

    Так как речь идет все же о языке программирования, то не обойтись без стандартных алгоритмических конструкций: следования, ветвления и циклов.

    -

    Следование легко описывается обычными правилам письма на естественном языке. -В случае последовательного выполнения в одном предложении, операции и вызовы функций записываются последовательно через запятую. -Если они располагаются в разных предложениях, то они записываются так же друг за другом. -Причем форматирование по абзацам служит только для лучшего восприятия текста и логического разделения отдельных фрагментов.

    -

    При создании условных и циклических управляющих конструкций уже потребуются ключевые слова. -Но так как согласно исходным пожеланиям к языку, резервировать обычные термины для записи алгоритмических конструкций нельзя, -то перед ключевыми словами достаточно указывать символ системной функции, что позволит отличить обычный термин от ключевого (управляющего) слова.

    -

    Естественно, при программировании, данными терминами хоть и можно будет пользоваться, но делать это совсем не обязательно. -Так как при настройке под конкретный естественный язык, системным функциям и ключевым словам нужно обязательно присвоить конкретные термины и пользоваться уже ими, например:

    -
    перейти = @goto,
    -метка = @label,
    -продолжить = @continue,
    -прервать=@break и т.д.
    -

    И последняя по очереди, но наверно самая важная по сути конструкция: передача параметров при вызовах функций. -Если стремиться к полностью естественному синтаксису, тогда мы получим тот самый естественный язык, который очень сложно анализировать.

    -

    Тем не менее, мне кажется, что можно скомбинировать оба два подхода, если отказаться от обязательного использования круглых скобок, -там, где это допустимо по синтаксису.

    -
    Компьютерный: функция(параметр1, функция2(), параметр3=значение).
    -Естественный: функция параметр1 функция2 параметр3=значение.
    -

    Но:

    -
    Компьютерный: функция( функция2(параметр) ).
    -Естественный: функция функция2(параметр).
    -Или так: функция (функция2 параметр).
    -

    Другими словами, для естественного порядка указания аргументов, скобки для функций и запятые между параметрами могут быть опущены. -Хотя их использование должно определяться в первую очередь целевым естественным языком, а не синтаксисом.

    -

    О возражениях

    -

    Предвижу обоснованные возражения против использования подобного языка со стороны программистов. -Программа на нем по любому получится значительно многословнее, чем с использованием строгого формального синтаксиса обычных компьютерных языков.

    -

    Поэтому напомню про его обязательное свойство - умение преобразовывать текст программы с одного языка на другой. -Это позволяет писать программы как с использованием строго формального синтаксиса без использования переопеределенных терминов на естественном языке, -так и преобразовывать исходный текст в “естественный” язык для “не программиста”.

    -

    Ссылка на первую публикаци

    - - - -
    - - -
    -
    -
    -
    -
    -
    - -
    -
    -
    - -
    - - - - - - \ No newline at end of file diff --git a/docs/blog/lang-final/index.html b/docs/blog/lang-final/index.html deleted file mode 100644 index acb4b8ee..00000000 --- a/docs/blog/lang-final/index.html +++ /dev/null @@ -1,344 +0,0 @@ - - - - - - - - - - - - - - - - - - - -Какая «идеальная» цель развития у языков программирования? | NewLang - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    -
    -
    -
    - - -
    - - - - -
    -

    Какая «идеальная» цель развития у языков программирования?

    - - - -

    КДПВ

    -

    С постоянной периодичностью появляется информация о выходе новой версии того или иного языка программирования. -И с каждой новой версией расширяются его возможности, добавляются новые синтаксические конструкции или иные улучшения.

    -

    И это очень сильно напоминает развитие технологий, как и в любой другой области техники. -Когда с очередным этапом совершенствуются создаваемые творения. -Быстрее, выше, сильнее … и одновременно значительно сложнее.

    -

    Об этой проблеме меня заставила задуматься первоапрельская статья «Доказательное программирование».

    -

    Понятно, что дата публикации статьи говорит сама за себя. -Тем не менее, новые стандарты С++, постоянно выходящие спецификации Java или новый синтаксис у PHP 8, -невольно заставляют задуматься, а в нужную ли сторону идет развитие языков программирования? -Ведь большинство нововведений добавляют сложность в основной рабочий инструмент и решая одни проблемы, неявно добавляя множество других.

    -

    А что должно быть в конце прогресса у развития такой дисциплины как программирование? -Или хотя бы у одного конкретного языка? Ради достижения какой конечной «идеальной» цели разрабатываются новые стандарты языков программирования?

    -

    Если фантазировать об идеальной конечной цели развития, например транспорта, -то это будет мгновенное перемещение на любое расстояние с произвольной полезной нагрузкой и нулевым потреблением энергии.

    -

    Или, например, какая может быть идеальная цель у медицины? Бедные не болели, а богатые не выздоравливали, вероятно, лечение любых болезней и биологическое бессмертие.

    -

    Конечно, «идеальная» цель это очень упрощенное понятие. Фактически, «идеальная» это синоним «недостижимая», -т.к. она всегда будет упираться необходимость соблюдать компромисс между различными взаимно-исключающими граничными условиями.

    -

    Но сравнивать разработку средств программирования с процессом развития в других технических дисциплинах напрямую нельзя. -Ведь при создание конечного продукта в любой технической области, все сложные производственные операции, -которые требуют непосредственного участия человека, практически всегда можно разделить на отдельные, более простые части или этапы.

    -

    Это делается, в том числе и для того, чтобы сложность одной выполняемой операции не была запредельной для исполнителя. -Но как это можно сделать при разработке программного обеспечения?

    -

    В данном случае, я имею ввиду конечную ограниченность возможностей одного конкретного человека в противовес возможностям разделения технологических процессов на отдельные этапы, -каждый из которых может выполняться совершенно разными людьми (как пример, это обычный конвеер с его разделением труда на элементарные операции -или узкая специализация врачей-специалистов в одной конкретной области).

    -

    Ведь даже сложно себе представить фантастическую организацию труда программистов в виде конвеера:

    -
      -
    • Первый разработчик пишет только интерфейсы функций и их вызовы, после чего передает код второму сотруднику.
    • -
    • Второй пишет в тексте программы только условия проверки и безусловные переходы и передает текст третьему.
    • -
    • Третий отвечает за написание циклов и общее форматирование кода и т.д. -и результате ожидаемо получится полный бред.
    • -
    -

    Из-за этого индустрия разработки ПО вынуждена идти по экстенсивному пути развития (т.е. за счет увеличения используемых в производстве ресурсов). -Современные промышленные языки программирования имеют очень богатые возможности по разделению кода приложения на отдельные функции/модули/компоненты, -что позволяет вести разработку сложного программного продукта сразу множеству сотрудников одновременно.

    -

    Но и такое развитие имеет естественное ограничение. И этим ограничением является сам человек, -так как каждый разработчик должен знать и уметь пользоваться своим рабочим инструментом, т.е. языком программирования.

    -

    Если взять приведенную выше аналогию с конвеером, то в ней каждый рабочий должен был бы досконально знать большую часть используемых станков -и инструментов на всем заводе, независимо от того, какую одну конкретную операцию он выполняет на своем рабочем месте.

    -

    Ведь парадокс развития языков программирования заключается в том, что добавляя новые возможности и синтаксические конструкции, -мы усложняем рабочий инструмент, предназначенный как для совместного, так и для индивидуального использования!

    -

    И получается, что одновременно с процессом постоянного наращивания возможностей средств разработки идет -и обратный процесс — увеличение сложности разработки кода отдельно взятым разработчиком. -Фактически, это и есть то самое взаимоисключающее непреодолимое противоречие.

    -

    Может быть именно поэтому невозможно найти «серебряную пулю», которая бы повышала производительность труда одного программиста? -Ведь внимание и возможности человека не безграничны. -И любые новшества и улучшения рабочего инструмента программиста вынужденно толкают всю IT индустрию на экстенсивный путь развития.

    -

    Возможно следует разрабатывать принципиально новые подходы, а не гнаться за синтаксическим сахаром в языках программирования из прошлого века? -Или и вовсе не париться, продолжать пользоваться тем, что есть, а теория дедушки Дарвина все сама расставит по своим местам?

    -

    Первоначальная публикация

    - - - -
    - - -
    -
    -
    -
    -
    -
    - -
    -
    -
    - -
    - - - - - - \ No newline at end of file diff --git a/docs/blog/lang-final/lang-final.jpeg b/docs/blog/lang-final/lang-final.jpeg deleted file mode 100644 index 2c5b9f2c0b9d035e92713bfef63173f6e76d2977..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51058 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 J4UE5Y{{u*e_&@*v diff --git a/docs/blog/langs.jpeg b/docs/blog/langs.jpeg deleted file mode 100644 index ec905246947cd1769180b1c938d1f26b7d83b16a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 227272 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ŝW4G1HPlHHT}!RNRq&#xxsJ{p?oe3Y84qhFYg zLX^UQIgW zpBY{Ns&CMzcHm!q9$2I7v6|-6OoMi9ISy>L!=Sj_1uDcL11;j%ZNDRF-khI&SZDI5 z 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�kvv2*fmOX^T3^?;ON=UG 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 - - - - - - - - - - - - - - - - - - -Проблема логических языков программирования | NewLang - - - - - - - - - - - - - - - - - - - - - - - - - -

    - -
    -
    -
    -
    - - -
    - - - - -
    -

    Проблема логических языков программирования

    - - - -

    КДПВ

    -

    Некоторое время назад я писал про «Интернациональное программирование на естественных языках», -в которой попытался представить достойную цель для абстрактного языка программирования, -попробовав примерить на него роль связующего звена между миром программистов с компьютерами и не программистов.

    -

    Но в результате оказалось, что это не нужно в принципе, т.к. «не программистам» просто не требуется учиться писать программы. -А если иногда такое желание и возникает, то вполне хватает обычных формализованных языков программирования, -которых уже сейчас насчитывается наверно более десяти тысяч.

    -

    А пользователи, как программисты, так и не программисты, просто хотят решать возникающие перед ними задачи. -И хотя задачи бывают совершенно разные, но если способ (алгоритм) её решения известен, то выбрать язык для её решения не составит никакого труда.

    -

    За исключением одного класса задач. Задач, решение которых нельзя описать в виде алгоритма. -Но можно указать некие критерии, которым должно удовлетворять искомое решение.
    -Я имею ввиду логические языки программирования и Пролог, как самый яркий представитель этого класса.

    -

    Еще помню воспоминание из юности, когда удалось достать дискету с этим языком. -Ух, с каким задором горели мои глаза, когда мне казалось, ну вот, еще чуть-чуть и будет создана система с базой знаний, -у которой и можно будет получить заветный ответ 42 на любой вопрос.

    -

    Так почему этого так и не случилось? В чем проблема Пролога, да и любой системы / языка программирования, -назначение которых анализировать факты и искать ответы на вопросы?

    -

    Эта проблема называется «Комбинаторный взрыв» - экспоненциальная (или более) зависимость времени работы алгоритма от количества входных данных. -И есть как минимум два решения этой проблемы.

    -

    Подходы к написанию программ

    -

    Прежде чем переходить к частностям, следует сказать пару слов про парадигмы программирования. -Обычно противопоставляют между собой два разных стиля в написании программ: императивный и декларативный.

    -

    Императивный — это классический вариант написания программы, при котором программист сам задает шаги алгоритма для получения конечного результата. -А сам текст программы состоит из последовательности команд, которые читают, сохраняют и обрабатывают данные или вызывают другие команды.

    -

    Декларативный — в этом стиле программист описывает условия задачи и правила для получения требуемого результата, -но не требуется детально описывать все шаги работы алгоритма, оставляя их на усмотрения компьютера.

    -

    Именно к декларативному стилю относится язык Пролог, да и все остальные логические языки программирования. -К декларативному стилю написания программ следует относить и язык структурированных запросов (SQL).

    -

    И проблема под называнием «комбинаторный взрыв» сильнее всего оказывает негативное влияние как раз на подобные языки. -Ведь в императивном подходе программист сам отвечает за последовательность выполняемых команд, и если он запрограммировал алгоритм полного перебора всех возможных вариантов решений, то он сам себе злобный Буратино.

    -

    Другое дело, программирование в декларативном стиле. Разработчик хоть и может указать ограничения, которые следует применять при поиске решения, -но это возможно только в том случае, когда известен алгоритм решения задачи. -Но если алгоритм решения известен, то проще использовать императивный стиль, как раз и реализуя этот алгоритм!

    -

    Поэтому основное применения языков программирования в декларативном стиле — отказаться от необходимости описания четкого алгоритма поиска решения, -отдав это компьютеру на откуп. Для которого самое простое решение «в лоб» - полный перебор возможных вариантов.

    -

    Именно в этом случае и начинается экспоненциальный рост времени выполнения алгоритма. -И начиная с определенного порога, время ожидания ответа становится неприемлемым для реального использования. -Это и означает «Комбинаторный взрыв», резкий («взрывной») рост времени выполнения алгоритма при увеличении размера входных данных.

    -

    Проблема поиска решений

    -

    В языке Пролог эта проблема решалась за счет использования механизма отката и отсечений. -Иногда еще уточняли про «красное» и «зеленое» отсечение решений. -Но в любом случае, это были алгоритмические механизмы для ограничения количества размера дерева возможных решений, -а необходимость их применения все равно остается на программисте.

    -

    Но чтобы их правильно реализовывать, нужно знать алгоритм решения, что опять возвращает нас к утверждению о том, -что если известен алгоритм, то и программировать его удобнее в императивном стиле.

    -

    А если полный алгоритм решения задачи не известен (или не подходит, например из-за большого времени для его работы), -то в результате остается либо увеличивать производительность системы, чтобы сократить время выполнения алгоритма, -либо искать другое решение, в том числе, сокращая вычислительную сложность поиска решений, например, исключая заведомо не подходящие данные, -чтобы уменьшить возможные комбинации их перебора.

    -

    Масштабирование производительности

    -

    Увеличение производительности тоже бывает разным и работает не во всех случаях. -Вертикальное масштабирование производительности одного узла вычислительной среды имеет свой естественный предел. -И даже многократное увеличение скорости работы компьютера может лишь отдалить порог терпения пользователя при ожидании получения результата, -но не в состоянии принципиально решить саму проблему.

    -

    Другое дело горизонтальное масштабирование, при котором выполнение алгоритма запускается на отдельных узлах, которые параллельно решают одну и ту же задачу. -Такой способ масштабирования позволяет уже значительно сократить время получения итогового результата для сложных вычислительных задач. -И хотя это способ является решением «в лоб», но успехи в области data science доказывают успешность такого подхода.

    -

    Конечно, у горизонтального масштабирования тоже есть подводные камни. -В первую очередь, сам алгоритм должен допускать возможность параллельного выполнения независимо от других узлов. -Также требуется автоматизация управления заданиями, самими вычислительными узлами, да и всей системой в целом.

    -

    Тут частично может помочь парадигма функционального программирования, которая ограничивает результат вычисления функций только входными параметрами -и результатом выполнения других функций, но сам результат не зависит от состояния системы или иных внешних данных.

    -

    Поиск обобщенного решения

    -

    Вторым способом решения решения проблемы комбинаторного взрыва является уменьшение вычислительной сложности решения. -Тут имеется ввиду не выбор другого алгоритма или решение задачи в символьном виде. -Если такое возможно, то все опять сразу сведется к императивному стилю программированию.

    -

    Я имею ввиду возможность поиска самого алгоритма решения. -Точнее не совсем алгоритма, а возможность применения к входным данным различные методы отбора, чтобы исключить необходимость их полного перебора. -По сути, это сводится к применению различных методов и механизмов обработки входных данных с учетом различных закономерностей.

    -

    Это возможно как алгоритмическими методами (откат и отсечение в Прологе), так и с применением машинного обучения, -которое очень хорошо справляется с поиском различных закономерностей.

    -

    Естественно, такой способ подходит не для всех классов задач. Он не подходит для выявления ВСЕХ возможных решений. -Но там где это не требуется, подобные способы уменьшения вычислительной сложности имеют право на существование.

    -

    Например, не требуется искать все возможные лекарства от конкретной болезни, достаточно одного, с учетом определенных ограничений, которое гарантированно подействует.

    -

    К тому же, даже при нахождении частных решений, всегда существует шанс, что с их помощью получится увидеть не очевидные на первый взгляд закономерности, -которые помогут показать новые пути алгоритмического уменьшения вычислительной сложности основной задачи.

    -

    Область не решаемых задач

    -
    -

    Как вы считает, а реально ли создать язык логического программирования, который бы сам умел автоматизировать поиск решений для задач подобных классов? Или хотя бы имел в своем арсенале встроенные механизмы для автоматизации подобной деятельности?

    -
    -

    Результаты опроса из оригинальной публикации

    -
    - 57.47%    Ха-ха! То, что хочет автор и называется искусственным интеллектом (50 голосов)
    -- 27.59%    Поиск решений нельзя автоматизировать (24 голоса)
    -- 19.54%    Это уже есть и все давно придумано (17 голосов)
    -- 9.2%      Такой язык не нужен, т.к. нейросети могут всё (8 голосов)
    -- 3.45%     Свой вариант написал в комменатрии (3 голоса)
    -

    Проголосовали 87 пользователей. Воздержались 62 пользователя.

    - - - -
    - - -
    -
    -
    -
    -
    -
    - -
    -
    -
    - -
    - - - - - - \ No newline at end of file diff --git a/docs/blog/matrix.jpeg b/docs/blog/matrix.jpeg deleted file mode 100644 index 6961ac64a64bc43b5fe4e500d9745be96d1c2715..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 377403 zcmbTdWmFtb^fovI2q9Q-m*7rthXBFD5Zs3Z3GVJ81a}z-9%L8>4bGs!-DLuUySrPK z-}~Qp_niH-ySJ-O-P>K==RQ^ERMnOK_xIll;EjrcvH}1F1qJZ=`2zfV0*K3L%FAf0 zYl_iXS#a4pTUyb1@^ZhUWA$*eakQdSR#Bu=`6RDM=PB}zjg!vBgol=jQ-4d~|}h zyfQBdHNIfbyAbgOC+59kkge(<)|@zD zF|4GzrnauWp%LEH+11_C+t)uZI5{;vGmH2;H@~{JzOlKry|cS_dUk$sd3Akrd-oqM zlxLj(oBjvb{{z?aAfUWJLqkQw_zxG#3$N#jijRi=miHxrj0VOR7eacz;8#SliFs8W zm<;@yC&Xs16R$}a1y-3(|AY3wko~^{_Wl1Cvi}R%|BY)NfQ^dsJb9@20BOLj_?6zt z;VksDuS@^Cp1$LHVm)3{UYPzp%0T6qTgmUcg3#G=hVz!KYJJd$Ya1%s9##tVNU;;= z_xJ9%Qpow%kMQD^Rmc8|>RTgB+$%+@eX8I6{Y88~yhi1Hqjn3&G(_bK`^ci$6Xu92 za)L)-jziolx?0r={H^h-Cr{DD4dL7#%{MXi5zCg}0h>785M>5Q&*Ba<(M?7F_>69y zlu~wq40X?Yrn|QA;WZARPJwKu&Cz1L>DFB!3wjxH2#uHb(=RIqNzqErm;&aB<4;M+ zcAAuwVGVWXDKC1izAHF$s3dBpac~#yWP2@1+o^J>@`efit}Q-5J6-62k?$Mv5Na)F|Ss+e|&3v0*Q-qD4f6e2atTy<2!y36pS5Gbk6x$ ztf13`zlY}>U{{jEEXd$3UQm+5{@mK8=Qw-|&bI+!4JS?vACG+XqwQ3c#=ddt zY&ze2VykI@&s<#BhAnC;SpQ6Ly)i~Pi~Dg|nJ{7%)nmq1B4G3>$ziuL?@Sc(5yXP8 zrcuBltGv8ebAdRoT3=#QD(A_0<+#@NVMQJHFua}en=~ZA6Cd7{p|N=ubb?pWDGH>T zjE+7y4C<);Qr7BbGD1B)9U=kU&O@FBjxObc4$AeuR%8132C$?$%Y;Ky2y_8$N%@*Px+W zm6XrC=A;Mf1(%#wc9Cg~VA;us)i6`n6k|X@kBK3$UM3FPMXl-_%%z4}b-CQF5*L?JS{94%j4$o= zc3}4n(lYJMu1f2Xn_!9d<}9l79#sd%BURUGFZM>jd9V?Kwz{=y7i(vH+IJ-kQR0*f z>rr0;zqA8{-3p;gsV$Ab?DnMP??`TY`e0$Kbe)>2FkD|ADl19vO7Q3`yN33T!gbSA zv&Zyp%&M6st(7d-qV)by1(adU6i=P{@Nm4XCSxLf(XnUpT?&CZfM8DQ=U4>?6el7& z=F8x1?c|vHwN=V5P%0ds{fJw6cPis*sxI+}88n$tW=XDcO!XDM zFWy{`Q#!k!r{jKo|32Q%k*gQo?vRvg#6*6`ZP!G41vhgw_q#4g^7O+skCl&fqJy1f zgIfZwshx&dh9fK;1*X%x#YFCq4xQ?c%%f)4ye0rdAO(CbPL=?LU`47Hvj*n6*xq2OeENV0LzD_B2(sv+K?nK8tvq zaIg#|&~A5~BtSxo+xkp+Uh1hEl`*5Y+PIl)7IdstGVQ+KaPo7ek%Y(XN{8i`-+?O^ zI&_Nw1D*Bb&99Q+n^Q32h%2#k!+!uodN-)^15@YAp-{RQ1RT@O9QmWJZkX-c_sz}| zIVwHh>--9@-m|Di4ibAoN_#x{yn>>m2!4z|)Zw%6l6ga_nSetqF>rd=wq2?f9f3N; zQpHwdd@$>_AkX|$6#f?nRx3VqRykY|(e?APUAWsIj~Uyb@u53k1)~+K@;YroMPn(o zi!P_Zhr_K#*C^5~uQA)v0+oRR(PjgDwmCk&GdKpZllFwV_C%duQGJ1!@t>WEK|W-h z&>aF@tR%&Uu}+bQ{a#>|@hC#jFXG|v+t8N&0=4E=I~86}*VKc_7)vWQ$B|qNoAISR z>!iWcUIQ;aZfD3hmNUVg*y2^-Zji3XDVXV%3C~_%^@D8H#KvqdxJU-eI+3B_>N|#> zwhoymr_Xl1=qQHmEfvuoYg2XL-kCnztcHgb%ZNu&#%<8Y(^6t34<(D+dW;36 zFJgAuQ9ENVz*3P#tze;z@&UW)W@e2(@?C9RU47EgmMdh=3V0`qA>h8^6Q_n>KXI5F*Olz1xt}VIo#T9#)?EO zaIGGX?Yp{OYEoN=UP+Fe6uA3WqRpWK_#Q2)g9Ncu;+n==@IZa zD`DP}hZ2?4Kig>AlFmydOilrD&4=0rcvdLzAEIZ;Zx_7FWuC zWv%)Qm`_o=0dtS0lW)=?Y$Ec|K&uTOM5F+Y?wAg|rD1B#8ik9f1AwkH#v(yQV}~fv zOo0`vm`3hvlw!)rYFg&L^cQP59Zhtx`8+8({VBb|@+W%aEA#du;0(~q_cYFSZ;eHv zB>9$9k5CgV&k{sG*3}+5uUqNi2ifMy=vaLIV zAJwaq9Gzu2<0%o+3nH2p;K5(CF$6awO^pW4Q-#Uc6^#*7tED|tTXB68tNZ`8z3!&F zq%MYi6a%lbo7Dlih7+{IWYw>q-L3Mq$s}K!DjMnWx zKw^(dK{-+O!;lokq@an)h=ctsCeFzG8neF=wZ`w8gJ1k^QyIL1HnPT3J8edXdt_0y ztK2ri`L|9DFd+!}$&Qh-AxAT#Lz_D{l@qnIT~6lRkXu~R;fA?d({YZl=AqejxVxWH zWx-4cV`^2YSOuT(p}4D5qhJ_)%Yq3;VeW=GsCL1G)Gr&oe6gYiV%+BLX`}+ zU4fBL=ZeqvQR`^BZqNMfJypoIGOxrDR?j{B-CrCBEopnH;A;s~uq(ki^Ha8-m{QSl z-Ud%8YOR=%zMu8Lm~c9J8X(eGTUz%m5m+iyb8Qg5?`sx?vPWNMEGGHuoP@O_4K;YK^kL*tkJu^HiMgbS>FwCa*1jcoJ2nrwIbFkiP+n6$T$1Ay`h>?= zl9=|^zf+l<#ZwVVn_HRMp$R4TNS?mr+qoCBHCck9td6|zvGlU>e6oM*CF*o*b%0lC zd%>%HEHYhG_7A{6(Jgxxvs%FKA<0z7W_UEw)BVAM{!-(jqC^MGbg;+4pPy~|70%*5 z)Pxt#<#<#cILB|KIK+$0LfM~!tw(j?M`bbae61KRHDe)blXokMR+{k0)|@)@N{-x2 z=$;+tHu7{X#$2&jvC4%w_d;wx*>ZfSbc@t32jYQk7J8=rMPH_^M`ufoZWzxY`*pS? zVt@Jnxm($=YUAT*(m{5)4cILdh?yXf%5&vk>pcd z9PYH)^b-p#hxA&*)=96p$-dNyxUQ}w8EZwgCN=TQr>}@N*kA?-)XLd+VpRLEu>fgT zXZU+D_Tt9zdC@%^A-*&E`&Yuoj~D&gSVUZ#b$|T25@n{_&26Y+DLkBg<`!O<)9g!` z8iaM>cZ|K4+~ekSrC5_>?PNL}t7nCiKwK3P95M~=5X~oMF3QU3j5W;KZO)NjeUz1? z=rt-zG@n-3v4;c}R7t0)yMaQz#gaEw7Z-ED`c283di4jZPC0&cS;Kw4Rp?56QkO?s z8X?BTmn#L7uGwiFv{*cm{<@q;_&6NL2ABk>IY!0)tb{J%N-?b!+ zx1K7R(2$>M*);iymFMXj_lto6LILL)s~uk?>x9Lk-7+!4uYSAbYE2zGxgWprXC=jd zpGISE(9{z3iDG8x^V@jxdFS?b>nyv*jsy_RA$OOv(QG5Tyu>vpyuWSXtG!Wo9R0OB z66*ws>Bi?5W2nseU>g>JnF@A~uMj3X<1?qo3}B7BdGoXxz31ab+_03RxbGA3k>w0b z7RYN=^Suii+kN-5~(pi=8`~!emqcrb^XWEEwbLxcl2aGI?ZtRNn=a)?6%1BI@ zw-|`d6!>-*h^a^Ye09w8*jSr_2z+1i@!5#@D^1NxP=4`nU$#JSLc`wv?5y#L`T4ZP z-~6xzXIryU_8a$oM2N0NWRbRFz|y7XYL#+EUvjZ^^&bW=e5M^Ok+=yfQFRQ9&Z*f> z?c*t47(7+nPO@C+OCA-e1f`f|ZvMUaLX=tGqZH{w#5%x2Tr**7d!hIlK5=ne6Q<$D zio+ujJb-nl7y00u^+>Y36?!M3gt-wWY6X^um zA8kEh0@LPjlH|{K*?)b2L*7rbM`lS21B5bIA1YtJ z+b18zTaViADoj3}?u;$F&(t-oRgbZEDro%uyl>MGZUuj_LT{?Um2r+hjkyvf+DuwC zyiN`*Z*SHbPE`%{9T47UemZm)IVO2{KO^A;>+>reBAUWM=CCqEi#H`#DX7o3a&o^& z#lt_O? zR?T>tU5#Fsx`RWRVe5vebv*%FlAr@5O(N#%4#CZmp*EeC+=4!u-3or8RgI4Rjxs-+S7+VKpH-;wHolxdeWu%*X46zyVEGq zxdo4%7iGeg_Y@XMnKSk@#g@@R9c&TM^f7Sm?QZSCKR{mO$gGZ|a)dZF<>b}c zz<+=nJDMXCVyt3+p?FaJKL7`fpM*a6o9H&IGB0}kPNbDvsh+Rp_QZo6kwNQxAbv4!??e} z0v_isy(mij<64budQm_FV@QN}0zP3eG+Xm@>WZ?RHA`qnbsqOat9{syYDS)vNS+EZ zV0=|-JD)OXm{yMea6|3`!1a5*ovCZ{bEHByeQN&Mbgqe0DtBUvT7X;1OT6$++zIIM zN$#A;1iGl@82_%dEL*E!iIk9o-NY>|?CEKl_^|5=rw>sDvdqT_(WKI7Ua24sB!p<< zsM{@xD*vu!*8_Ra-w7U;YaB9pr^?s&CCMZW;|(o*t=Vo;8p_zE4`HSbH{4N|%U@&N zei5AdB|RU6`M|+kVX>Aj+Q``@L8a|l7_nJR1LPaJPO%b{`hd(UKy%`1ZBFtckw9=} zXeNmkP9`gC)`9QJxW^kqM@i(!=L5rAoq_JzlfDIEZiPq5i0Pd=^+*uUbPI#s%FqaK z^@5eb_XUj531FCtbXvBqUL&$bOlV61SLlxe> zXZr0!=Sg!JYQtJu^Lj+aB-^4X&tW^6qgGA8v^!#qpv7X`cR^+RuKYuIeE-z7&0L*FShlvy5GI z?U19O7jboCDRp>x&gYSdMnhSZu8qog_KR+tj?+pyU2sOW;OZ>iqFt*bX1O87)bcKC zW-v8Trtf(v7TJjhioG3A(ikTwuwfy}*{xEU7m|Oo2hDQRy-&GMW3tkxkExgeB>dgi z=Wr7;OLC|tc)0@I!D}^DP22L2dP9nD>>sBgL*CKrGAg-0(0eAb7tcf9KU;i}OW9E@ zztSqTJ*0oY?YJcLQ>8h3hNuL*ADk+>d+w(w5H^c6^H6_6Ao?6H)*SoyMfh3O%ox%XwNV$Tu}v7j((|J z5JykfDh#2SGO<41IoZv^R@uEP^>SBCFKjz^O)&~0J(uB+Wt^A@B_@-baKn15t)i z_NN#J%l6_&p;3pgS6Fr*_(u36X6Z!DfPe?({6a8m19z~fLW(hDYIyI`>GjgC3zG9R z^!q0RO9gCN42%T7H;StuHHi<*NTVDRi4W{1<&VJaRo7+xv8F%JqiiPp0n9)}S`L6` zJ^z9pI5x%Vlm;l;8AQ89OI4Aqe$!lT+(nw`oaWGZ;fe>c^QSUV!6oogRCrBw6R7O4 z=hD;=U35xZLiZu~%Y0dM&bK77I}+(^53SA;f@ZIS|7j6hYIbYqnDzQk)}KFjsK1R6 z%=(?S<>dL{cjRL0a=MWrqR=lgJK=-Ut3>RFsF&i`YqbS3u7!1vYS!bi;CBA98F+x`_LM!=4E3l=y9YBT>;Buo!5z`v&aucURdXUT0 zv**_kPj^OFXq*B+D0E%rWY>J$ zxHdCf)k~DEFikn`TC4F-TZUegAhH%UH~kwG9>m=SqyeE$E!(RunGrdt^Gz4ynucn~ zzfdMo7|>61L)}C7&@IZ6#Lf5(ls-{6fVZ?yxn~(KEvkxxlMfQ}lqJ5epqWn-jsiwG zI+cMoMrv(Vkz~DEx={_4T7>I4$-Zl2hP46ph>n%|;QV`u@sfXlAr|B84b(1+?VJa_ z(vU1sxMlV9#c$W5T*lOBlOu2W2fHstf+g_tpW&Hzc-y9GYE59D`Ki1M_vKpH=xp|D zG5Lqonqpl`rZ!zrNkD0SouDAB)zBqlh9ZA5b!lMLQ;-`YP1jh%^_h>Gp$ zH4J}EE;R7AQm2@PIDR3xeJ4AoX==?Pu^qE6IHpf5?F} zhWpo)W!R8%b0anky)T`lvzw!V<(KGomTp!`~-H!6aX^4%;$^)U|WSK3~czq%?d zv4(WV0>585BRqADzQE>-6%vL;y8-eZ;G4wthbKZA9LU=_OOmbAeXqr;dBapH2hTm*=C^ zx0vCUG1Tb41NJ9_ZkxB*Os!gw(3%=8xVTYmo z#2J}>gSi_r4|l=CE!^fB^q@@Wr}u zDZin0IgiZOxFMsyh@@&w{1K>=BN0LTA?RyRmSWt`G4n^el2n>3QpScO_sKjU7WjDK zIzCK_a%THPGh$=v!hm326%O){dH4POOYOt2@4FTVDCs_*Z|F@H)WA3OY_vVSZgVBQ z&)+wsb(7i(Dnax&*e3y=!bOvIJMTOozzpMXcxWlBmTJn@*0|HQg^_+szur*<@VI-u z)fc~8Gj?GyH+`X0E3U@(HdP?gM&N7G-7YnVn_dCU(RZ+R#vP{REBT1MH=t7|;;}G1 z&6wonSDYT6;X+5g+WrTjBajakb^p8jUE`Woj^28X?4@R5%o(pql}$Nr;nZKmM7d@! zbNf#Vp1VTn?xl7aW1X!%X-nGNydhnn(_DVd(ufP=q(C^Mqo|~v4)C2aqjerxVdUqI z_|e1|=eV}A0Q8Ryn?_03)e9Fvp-uIc$%gJyprq5m9bA+cs^DDX7~0MjDi2{5m+y$o za|wS-DP>lky4%zzCjXDLZ|WpPx*ShsP?diVF<*;kii~2QQcI4Nn_%V$k~9 zmo(A)(p_UQ-O|x3MP~4GB8j5u3J(r<6*h@m;pBj~{vU?VrQ{kzRg$ErIazuy*-LdO z!_`J5NUouztlB+mgbjHY5o?l_vgwfzNg=A)Pv{Khb-{>pj%GDU{)k!_Cz2TEnm7_;f ztSe`6EC6TcQwK=5J;3(p3iTe^wQDv!^Zt zvaeycBc@^`Ov$<0X|5SgwNf)H`0;%!d1=UUF-tWTiiW6N&+8MLA?>cckU~6WyWi8snxZ>BU{x6RQ00&} zs~KXN{2sENBRpieZ}*P7Z?#+J9fx5yrI<85)Tb>L+|p9VX~kr#a52}-xX+t<#&1@g zdG+#;LStLLlr8lUIUDu~r`Zw7yhEvrqklboIz=P#Je9F+(4-4}^Q!Y`<+J-$ zk2l=c!#Tmtp7uSC&_!Ey^-bPWhgIr^k|_W^5%9fF zc|ZcU#p`+~AD1k4%^USEpj^Q##nQ2WD8#2*r9$dKpO@%fh!&Aq^3P!hriu~%aAF}3w1f5C`~!4i z=E*}%kf0uzzG=5b)E1+~ZOUpQ7>+H{e~m^6sz4>#hj(ghrhs5icq9BXL#H{5qlEFC z`In$(@ym~^Aco|9(3(|Cx|jMl2|gz@X2s!`F8bQwjH*y&gHno@tm{#_u?;oXs1P@k z`ilRmI|WOZQMp!^mR*`=7t|(_C57A33ozC<`0IuKy6B%usW!{kg0nQ3gX%^cfx;4Z zw}otGBs5qVPWg|%^vDOw>7y2YuQh6lt!1Mr&i;EXLy~2uoY0AHpQYz}CHKrT<&f;e z`Kv5-hm|A78Y8fhQanR$0zVV$Cp)=siArXoXr7fGG;6>63+T2b;-)u_M5V&O*(qnJ z%tA#NzMI)f<+wJ}-^Z`;!lYkw``fst>guWmd7Bv&GSwHVbTLTteS7h}CmJB8H@IGd zA-^cj73jGPKWkj*nv*=J+eHS(PdSNavqS`9&fkP+J1}$^9>y*en-0ZwDtce{N7oht z_lP#mP#8r2jQHG0OqLPk&}XW)WrJe(oIjtdBpBaB7)nkaUBFi;QbT=K{{isTp|(QD zPCiZyj0uB{mS3jvO+6?k$`y0)6at1hWb0_WCCRhNo$8Oqm`3am2h6P;RdJe38e9S5 zGjjU*zmAD`Kc%7mDzSIi2_P)IpEpwI z@g0B>-`gfu!Sb$0*S%OViS1}Cu{5G@t)xj?kKWLvvj3Epa9{Us3of}?7uuHTxV=$d zr&-kt_=76Svgads@za*CKv`DPHDK;S|9`Qr&#WQ3vUaNYd(;fLP(8O=dEED|gEOQ& zLBEWw(k-6gw)VEBtDV~zY`Ab^%w^nP9=gy~vh-?clclyUOpplge=~`eya}Oz)lZj_cGZOrFoZyAdmeSM6(gP@Y{$4PxUu3L{gm&Szqcv%_a##ZQW<}&vj;t#6L zK1FFmVWPzGXxkXfEiLAb+`M`YG+((INXg0#j!bKh!{(2BC_wEHSmVT{(JSVLM)_Od z8xHKdFf{!6Ha*7T;z=+?hQJtjfW1TjB3n?SUe$fmCF6kF(MB7!Dr>UHi3l_><|`o9 z8AF)ULT8(Q*9Fuw7p4vlod>}dL(31V1er+ltM4oR0kno46H0?`PEA!YJluB8W+J)P zgryv3+20?C{R3RWRE+E4d`Ynp+Gxf>#9Gs>Bk$A}j2L2nmXzYhd;|2jKH#2N2_<;h z7ey%#kUP#ae?8288SQ-f;r+)(v%$FzDzldPQ?;`;~SbZOLK>{LwZ)rbn~Vd zf4D@lDVJv9iH>o8C5iv=o+^gUAcx|HMtH}B4Qa_WsYWx5o_E}8sXkRqC(l|@&MVfV zz`F9!)@5{W%j{295xL)ZA1N+bWn|-FyA$6-Ij+wnS$dXmPr>n>?O2PZHq2vPNy_3# zlXOx-@w4u4u2T9p{Tp09DYhCq+l-e%Md9fR<#z z;&t{woGfQ#?XO;DV4ar6Ucq@J+!8@%sro|~nIO|4+Gl&d8Skh*C*Mrte|qgSr*L)l z&fn|AP3MGj_S!JPz@GbiYx!X*=G%0j^I(9;hO?r-o+Y+#37o!8Y-hbd$F(m=Zqx${ z0{4h;BfB^}2K9)DlwL|^xNJ_VD*71}w^Y3PEJM9JIu+droQ#I==FpwKuuc5)TO!_x z$U2g8#U91y4;8L!5LHgyxj=EF^0}k`CcD%~1J@&N>7NFnqcGjJPx|a7);%(srUT=KQ-rx!tK-JvH_T7}IE36SekUuY=p}-_i}nlRjtSsJwxQ zApCNlETfS9X+(NY<3gU`^!0r0>eNfc+X8YCshJrvg={9Ps_}wXTDpGJNbfL8+E)wK zvM;@vV_zkpB=Xg}suy9!_(h!-D37++JDHB3nX8R9JTt)XCU13M23{zLAk2X;sJd@! zp#a8SGdNt*c+hR(aUr;3X1rqRSy&}EVGG9d11^ry=W_PW-MC#LV=J~UJaZcUmAag&SMIqSHRqBHy`H*WBJgmz z>9Uq=L7{~Ko&i+Ug;#we$Z{Wn%qWd5b(7~XH@V=^IkaMS`BX&NB4cn`*~R55dZ70& z@L<(1V_$_ITtF%B=mjAkoY0M0mc=6KuIj<$Vt9wW=OZm=II^?J70Z0#Xyi-Nv&QD0 z{7c63da9>bfx#$}E{3*NwP9;8NmQeOD~sx)@^yv>Q~h?RnkaB~;udSQ+;OT$I76p3 zi$EU|vt%n`-f5zugoI3?U=eU6t? zkX};Z_5Iz)ZIJ?M3$MV!kprEy9%WO>eVXOQLlS3b@v<75_;3f(w>Ut&BJwkwa$Pw&` z`G6ynn1w?#?)Xgfl)&lQWifea39{D9!r&*hnar3nX4)l~E#^qNN&m*Voo&fq5< zUMbJDz=tD}XOr)~z!b6Z=GTcUAAgo!e9V;&T{(Qy>=CSFeaUt+q~S!d-;kC#N^eR zxP)kM`fg8Hn{)d69HfR5SK8GWk2slgZ%yT^RrP)2M+U*yVHf4j7er=zJdytZx?;tX z8bG_Xr&=E4qm%fkUpWKxDYE7nOzFbC52*c;J_oibU~9tnLtMJ`^@*Lh&|Z^A!I?vre2vcJqfGu*@lrE-jxM|fDkb>ro?w|AUp$`2XKYbJbd z??_uj*9hGz`br8^${k%#Wl_Wx7wKs5MEZ+i@*43qsber=Hg=aQC)l8O&f2-o45Xzw zal0}7TA3rOhW9^fL<@JF%z!2oSHBNTb9mB0B8}SLaI)wai54lf_R&^}OlK5Dgf75O zFF4B9gSuXVQ&qG0Ir50oMBC9S-CHf=1zjA&iLL)zk+g}DE^}YjC?YE1r}Jp`NsZ`~ z4@#0Q9N9*=%e$+!Y^^($-@$#X+j*%gu_y?y(+MwSug)!GwO!a6$HBFW}Zn&okAm+Pe~)3 zDhj`L4IiMaWaU8X)dG4+q6*Zwp@>x&yY{5QvxOlI@D5pHi8Pz471>BqD`$+Owe2G# zxBAKm036w6QtM`m_zfQPk?Iny9&-Wrg3t!mc-{;_te4(SdT?w$F6gSY`mc#}ivQA7 zcl0^TIEBq;3$pdx#Q4jaQ1U(fFJ{D`JoaZ3{OD%&;Vki|>)2>dWruF30l{1*bVxoS9* zry@NmWc|kej^T9INE0SzGx*8tYwflO^Cq?IREMypqC_dD!)pbD7Whlk#IyL(tg4fy z*g8zJb@y^uwokq-p*jVn-iK8UBL5QUG2b0%L;+dDu+!`5Nylv&$da**t`~)6emyRY zCdOSab?ftPyVomNSgLkM<-tIaq{BR#wBMyWdnX*u6h)U*>!v1tXW6D>zV~i9YpF9`Ay{VhfdXZ4rl1 z!?DB*vU#iAJ^KtfVGZsw`bc$Jl&f{^YoG#MJa;VTrjl ziAz}4z(2Raqza2M+mrsAL7e1E41WzRdd~F8Cq){Jdx>ivM-4}B|QG*WPB~wt6 ze<%a;0XPeD$X;$&p-xYAE#VM{w}8SUY!4))?bR1svc0J%)Gq}OG}ZAr0>C#ptqX@@m zrpETtMgfd|+`fNzc>8eaKSrpTWupwnMsO_TLBBUs6Ny{NDB@`+fzJ*avY*^E{Z=F4+r|d7Ya!+1ai-6ZC zui2?aGT@fz^o>yB2an}df@4l@((l>o0%oCuJ(Jx-bEA*frZe#z(}g1Gzu)xVXKiF< zA*MA|<^SGAsajV2ps-)}SD{23821o_=tZuuQnSTDHL$QA`O>jHawF){osBt z?l!%${+vfU);)^9p|yuleSD0UCKkk18ojG+-rwG^G*)`iNN$E<+S{}i*AI1S`qV?F1|17mO_xowL!x%+2%@0 zA!Wg}LC~*o{y1-~X|W~s8e|ZgYWQ)s6b8r@ z`3to*O&tQG&5M@bJ7{ikpb)t(r2LhhWr*izf%O@0n6>lfNWCu5DV%CnTZFVL)JpTf z;y@E6qqcfB&9x1?4g$L#d*0CQOg|$B&%=WQrYVQH2qCv^ceVI*pKX+ynDdygZDZV7 zP!)Df%>V?b4{3Rp1!EF5xju5{5w%gJ;j`Njb+0;Rozp)Qz#~S=uSzN^Ih^{gbs56$eBttFmR3%L3RVCe1s^7RzIoY*~Cx7{x&VVTT3k4J!u zLHQe@lbL1OsKqM_AEAxlofoX++vQ{u9HE9_NK1LqmFg4KJ8uKoI+e2}-O1;FzV=+m zm$q6*5|8u`+i1LX@d%dG(5I9Vqiwcnv_j3yV{;oN{2ME=czcF$h*_Q7>&`tTKK2ny z2x$MRI7(ZZ!vAc=Kx{gAJnsG;YL{7!b>=TK)`xTu4}<+KmWhY9P**#85pQ0x2y z^pXoY{ScDE5c8;xwkyhZ0!Z16Iel~uQdc=&1+yFcsA@r$$BU8cRrd{14qqC%OWLif z82Z1t5nq#ZGR+RE^;d;Trlv!9hm%h zvL=tkwZ-fwz2zsAhLf#MJaX?Ie>FGf47@P+NP@ki+n@1QNOBhLk%V8qetO9fZ4~h{ zfowynfwYO6dNIGJ153-GTw*p8?k0H5H;1P$5NoEr)Nb9L&RBkS$oz?-cb+S(EDOQO zM|KB%2NEYY@<6}6r)#(U>WBXX%%%IsyR7%`5j;)W)_rd=G@_1L^ULbQD{kF^TYia* zM_qY>leJNbDowG`^Q7TU52~f}yG(nJJ`A%v^XLh^=$l!(aHHCakFW$qe;045w8iVJgn4N*Xw%pY1@JE;s zd{qG`dGS!`_VaYP^U!=1ss9gPr$`Y{&mh1oiW;WY{SwVtrdP4f>vIi-$dQxflv^{# zPp#f_Kk*&6tCO(Ufqi7gVM^KPfbzoB6kdv+=!omg^kzw>q+N&9+bR0G<|$^lA7f*^ zw(3S~q=9OIFxKcRbdiC+X~e*~^QDoFwwBG|rqw?Hu73qTp5b0eG&l!gWKgLtePd4B zyCjXZu5_7AV8CTnuPG*?FH4^*D%S)IM&G0&HK0X(jN|=PN25}E*IRJgI+9G$5^;gK`5U{n z%BTl^%g1!9QsWK_O6Pj66y3|$-WW?QSqi416}Ov2a~o@X50YMEto!><@^}RM*LR0V zA}c3UPhvxNsHy}$yPK?dMbDre<0Ii9QPs!z55RtE+jG8O0Zr6V%{4l5OMEyB zLv0t_lO&E;UgV(e`#~j(;49ll3r2}qIl?AaN5d6)*+TWT1y*`}Q6uru&yhTt-m~(smQSCjG{SA}IXG!(eOD-b=Esw)!h;HLen^Y!JV3 zDV7R&+W{ya3I$$r9=Ul3HHh`QZpJBHR+NhpD(d~!g$It#J4p}4C&z5Yy%bOK)05by z1St?E)h!N@I;)~-sH{>6)Ae?MOIcO;99c*4(rYWkRc60VUJgmhFz6;N$%D;Zz-EQ` zxsL2mWtGg(YpPv0EoX$*xP;I8q25*S4H$jF&|mjj_$w;`mhox?irc_`kIzW~6*0Mr zlU5j!E^Z1$2r0fC`@~YM9v(=2<5vX2QP@{qW;$F@Kf^RWC!k$J#n`hO?I_jODXP_z zc%ZTzEmae@^&coUe2koY+tJ6|)|T>^?Xz~#fqwAUr17}wTE9+;;9#?75)l!bO;&#{(glD^)H_3WD6&;vW{lV z;=vdpx+X+NWb|lwSBiA0gC%@T*5PS%K1NoZ-&zXPyNt+ke-uZMaO0>gyG4^@vd3M+ z(@$d=>Td2~ZNlU{i=X@mob9S{#xMn%jE^8AoSaE*Vaq*6hqUic_6>LTohZ6o2ztK9 zO)>X!Z=*7xv5HD09~$c$YF27xIH~XTy~NE{nc;c%BOB51uJswE{cfLH!)N@7=h%uB zAc^C5Bd|WEQrc{yp4Z7jW9wn$xo6c9XtIHb1w(M(Z@{2EbhkCQyEHdPo^vDQJ zO6D9bcM?1>#~41w9?y$pI!o`qu&3pJdLbflj|dqt6v_5{#Cv%;%VLB)sT#M=C0o|L z3Hs&jr1P^Pw@BOvjGrb10Lpe%m)C!h{J(N_4Z9eAm zq<@D?W=fdvn<^UOUpd~>%IRkO9{}G#Aiwr*_d1Ui+ois%b}S58FTPc`U_j5I9jnU1 zNw`JT`CRj`(vyPrm+~yZ;8Uti8r$oUPZJ3kw7Zd66B%)z;W;2@2P$~2Dq{VVZs0lM zy_&m&{0bitEYm^P652b1bpzYR!c|-a1$r;_s=z;OP0HHcnqZr&PnoMbvL6g9+c3D> z=1NZ6bps`d@A*>2T7KfubrvVy_f`DQO}g-W*S`-T)Kw)H5KLa?CMa_o?F%5l3*%16+(yT5u$*pcK4eKycx0nV?D#&VF|g*3?Ih6 z!PH49T>8f}l9kIkl-^RuWeLo1pO}y0e&({J8{Vw9f03Oy-t{HB2yI2&_HiK0k0OEw zbJv{qrsv3|C$Kptys-km&N)Vlc=P*X_*2eKB41Dp8`Mn>(n^oh206k*Chuc>6RXee3+Chwyt3e|qbw6;t1r!oL%uq0C5ht5@2+wnrr<>QwfRZiW8^f9WYwTlHOM5hNzY%;_4uz!Zw}0@M zKDf8Y@!MIWyDR|pbGwX;l^Exms&wU6QHn;ismi3I8y<7vA)xA?4leC=18?Rmw=!X* zRFN3lE5zKNn=G4oQ?eceCWV#E%K4j`eMGWl#_yI z(^HahO&-ngQ{#O90JHPon_W87Qn=ME9@^nVKxu>Go^6OES zDo#o0h4>5L!{Wai%i>K&@pPXK=`tp1zc^b5!XnD{^sC7tEN#ubo#oDBjaTN{005tJjGwJ^VPh&ZbvMJtRH#gM2O30j zGd!`Rts`S9SwjWmw>6y?Dzf&{=uH_)qxP+AatUDGX?e+xBse~#`U>@(MQcY^&qdEm zM{`onE1UiPTbN=Cg^e?hTz;Kvl5Q03eOb>Z7;mdOnDiY}NYSI2;kh&1p=gw&5D;}? zUTmjMwOcD$98OWGJ9I_`hluq(I`L#lvf%JtLw`E$o*InfvDGRR=Nnk{9~*e(W79N! zHaCV-J+jF%ylM(L`@DcY^6eyc&r@D4EG68h*z##%uH3cI&hRgdG{`jlUr*Jv
    rtF7D9ZObD$*~OlP{{RcFEqmbBo8Si1)*CH8<*rur58iX1l=kj_O2VZIwCZ!a zT*h>2LVU-+d?+7qpvEA#|#w$BZiIE;fo%_p5G}N5XGtWSgM}DYB<%!}eT5B5+^H4sd?_9|;++C3yQ_(0 z)nGF27*mjNdJ)G?pPhR6YVxNPlpT*&g;xZUi!6LT_Qw@LBNyLsVX7U>Z|@X~nJ*3(S2!nT+c;bw`tnE)(Ke)dgu zPc5rLoNCi;$$wwhe!bTPOtz&8ajQ>RE}H%y*1dbL75LHcV)NmKsc&-)!fO5*)K|~b zb$ec7xr^BLVVp9aL9cTGk64)U%So-#?qG4z#K)FaQ(X@=xRxmvAfdrQfKEMY*NT$8 z&sH&N_pzs_AU4o3$2H4MzGjX}Pu^&~;c4Wt)vYGCW?9lzWMn*s$i^!SQs<{A%WD|o z;~JFZ8Cupp$JRVasOnxf@fMqReJa~6o~9bj$q|$gO5C6rCpbCAN$0J8S%;#dN)t)+ z*UbE%4Tq;1P^lQk`fKOvd|j@2ZF4A3x=FyV)$sS_S3h0D=@oM(85#(~Mo1;_co?q6 zxt*EWB&6)ikxJ4X>~emBv1-~Q2Nbjk!E|zX$5EcNM@E7+O%r%_Z!c80$m7f$)M8cX zzd|uFPMp0DeAKO?@ejwTZJJhwIdAjk#&E-&@OvM6_$XAB45!*9cVqMD&)8)C(Ioxe zyB;~>y9cO$&I+Hxp%qH zX$iLCHeOpJ1079y)t|cVdDX4T?tMMsi@gh9d)f6_@4P#$#28$p>68+3TVoHJKbUkN z;=eG(LlcMPjTEXu?QQ;jAISW-8A`StMl_=ukb7&byw=b4Jg4IZp>?k7_p|D1kz9w` z+gpC+00le0iz5d;^P2j+rZJ^TDw}OH>vDKgqe?1{ss4R*JeE;v(iBt8ePZXe+4akv zE3yfZ;9<8VduFXQEzKg-hhE*8MgTe7Smu-=VL}QcZIrb+I~6StSokjTjdi1j$?oPB zSBkqj0MIxj@O^9Kv#Wa~+^o5y_%wWucBAZhr6iX$cmDtqGIh%fwa~6+k}N&P%i1Oz=*R>a+?nUTD1b@844l3mI(78P{H#F8k2PYdq$Q8j=K4Z_SpD||Q z&MB;Z+Z?W0&84F5c3R$|*53{^{SwhG5*4_T?&aP+ zt0aY0Q=FXbP)D}oUQHPDV-V$DWd=F&dV^n3wTbmg z%@VD`7j_ZtW*8?tRC2po=58+5Y=>}J52as2OI;sD{>Ziw#-9=O=+}0mqxfR(do$iS z7^Hj0xL0m_X1-fGZeGrpM%DiSFVy*b<=@%UcC%{#0D51k;mRbs)i;vGyv|SKUgK&M z?0a79DcentfBmI&DdO-C!dsIW^5yXID1TNC#E;Z|b@G`s)N9vWDvOlhVGTbuFp%@}0FTX*P?fPSM2g<}YU)5$##lo2I#>v@@+gX0Ify zde4Tw7|LvI?k1Yv8EzBJw@K~VeLfPZtpy}~P7=bL#JN{J$lVSr>J^#v+A?xg zB9CZ1f=+#NSy{I3XVu(vFtp!wb4pTC+)b$NSegk{O9VYY$31H}$}QUDMaAiJKJi%& z9ANqy>4l!hL>hY#M;LZrO3}L_+py`BEQ4s{sHGjX2qxGPP2 zNTzUBlJ=2I*R#?tbu(&0{tDCW?^_c~f;|)ghPrF;YJDCHcs!Itxo&*jy&?(oF#< z7pTGHSDQKe>DxrlI&xg;>152i!uocVZ5*n}A(@#`xI1t=S6nSttekeS)dd=rB;#vX zp8D0ru(;Y47%t(SSJRJtR&?gMxd?=#&C8+Cd_C4qfZC!BHG_mnoVMBONmjJ%#oZn=09|d;QqDR=*DqPXm>ggoKse@ zHlt+5IPMwJWax(&Ap44nb60Rm#8aBPf>vftx=i;!WlzNC$#44_fhPx_5JgZF9$>>0QndNbi0W_!wWo9rfUuE!t*P zWh=BSQJE!klb@7r;~eL$dARD$zE~b^Iz11L#!I`)Ia+H=yVCK>IKq>` z=C`F6^+`A8bkc>evTY)V#l0I#&|q(|+{+~MO~{Z8$f0>*j)Qj?$l`AL)HV&$Pi1roKnw?6KT~5WzDwB?yn6qC_`jpeK13Og2qky>J z4{TR_X~k1fUwPQ6!9hhG5x$nw!_8|PG5K!$ff0@4KCO)7+c@I5ET>xS>~QkNb$OfH z%<8@u_)AyuTg7J$qseX#_k4xgGtL;`XC1498#-~5Y5T_xHl-?ZZ8dT)h@KUD`>W^D zS~;vNV)H`1%wA^2QMrPH&pGMa6{Z5LVP!4flQh89j4Y?S^*CP-*{m{)iB8kVOpNpy zC-ARN6E`Kuk53UkWy-8xww3Mm7};FN(x`akWx*i!BDv(0skLica|tNQ4(VyR>UX~m zJVq2-Sy@@F``hfE&KVJ=3OONxCu@AeBZJe5@#9(-{pIYoJb2cnd(G*(W*5b81YRz; zrX$4B!}cf<*q#)G`G@IU7(85Q!d>ppoE|0+gtooe%GpnC9FiXI@cwebF-b$=7dBzsgO zPT9nSe9N2+?Kv3&g?g5xiihtKr=f#mrd{eW-d`Av_LU1PlYqm_i!1;j9(s^7?_GK& zWu%wlbvGEAGxJD9TwJrW;RW>{*CG!`NENAYJea9m`MS2esxi3$t-|f?l>Gdq8uW@mpU&exTGddyIzaWWo z^5;4G+fF)gD>Y6u=O61+KW7L{Uf=Ldj{xb@U+UsLIkrgIOvUn$qz(xl^}~#tjD6#i z6)Q*IJ%{3Mx1rcQpM|w8KIEz@vdb7!V{N#}Uwo76&U@FDPMueJv39ZMQKvV0v1u1{ zKLAY!f##1!nhV9hSzv~6`10M803O)qoc6GafQ}-~dk?^she?T2Xwc^Rac@A1XO7i85Je zI^^0`n;R{nIT9p|xUnE)XN=>qt#EL4SGAV?4e+paBkd)>L$}ksJE+=xB!ndK`7_-u zzzW%LjGrz?t_Sk2dX*EZ+glv9Cl^_^ioXb>m3&1s^D~PT)8>(#_~5DI>%~SXr5i2o zELSfrm9KNiyj|i+bz7%wm4p(ggQAM}@R)T@K4-gzp&Dz<&a=|)^_wXg8Mj4lp`IsT zFfstguUhJrNKuvA)%7=&;YwPq%h72|Yo-gi&@;w%+lK1R>Gb~qJ?oNHoa%B%XSs{3 z%|1x=+~mgltEOpkT#`+D8bUUS>1i0~dQP$8S**So==ue$GrRoAb%h|2E zmV9GjD(Y)J>O4qo;6E@Rx$>9p{{WsU@bgMMklb`6lzCz1bNA9Vrimy}uL|Iz{{VNf z{{R~4rj;kl(f(&l5~rtgyZBwBMLf-abX6^FopP=|SzDF}-p6UluO}Z@m8h-R=Hn_^ zsIAX<)--*7`rpM;+soX+`u!N0yvf z(p`9N_Txx|#3PMmeWqEYSp4ER%I+f|9triYKAl9T%`cac#|n{CyZ-=&F=Ftv(MvoR z_VQaaGZ?N6ibs+1=aK8|de>y}9IbM{Pd!eVR!Yt<)6C1$?@YJ$w&@$2WRPJHWt*N) zxvq)RN-k1*vw1?%a&J@GFLhV(?~ZQdyN+0_*iGalpU3<2dJK4gvm00Jtb9rt=yW*#2)zcZ$SyzKsG z3wd_e+GDp_Ai}vL?=DV1B7a|M^kD@~rMf@N?~HjT>Q>S(gl1UZB_v!NV<3Z(T2`lf zHM%sZ3)!xRZ>ZjC6KHxCmv3uvX=ggT##si{xozZb2fC;LW3eaJyyX}}o}`|q1Y-!f zPEB9(Jbjpj1QDODeQl3n9p;bmt6I~39O|A4x{3``M7<(NV!K_&(qMnq!gG~kI6aSX zUS&+WobeIFLD{a|f3NGI=Fb5M*Hz-|*W>+vT@N>wH;fX>S3NUc%4zI-38%9*pkaMx zk(L3+PHT!w+0N-4GQBz9r=g{y*v)Hk9Iq&kV{QzMgP*N)SDa@T6t8oZy+tUvrT81V zpNq9S`=*#`cL?ePUT~F*zIzj%mBC8|MiJ$7*LxgPu(avM&OUo1hP<4~EAMQ!PEW0S zu!>1p9^@lsps-uB!l!r2TL5N>Nhh$SD?j)LQ>OS$BZkgxM)fRG>~DokZ0u7cZyS`z?EFCy9JBKZkE_Z08Ejfll=Km6d>H zWj=%uLHDPI#K#dB)Q?~IX1+tiVq=JmYDe<3k>0*yjt%1S`gGojrFGxS z$oYCWNn-NqbmZDiE30eiAI@+yDRA(BKvewtw)}>l>r5clIYre)mgS+g(SIll2O zp>1ttHOK|ywN0qF01OYna%&tW5n!o%H121G!z>*>MDB7gX2Wpn?_H{B>r+HATNAl> z1bWrVT}yK6Xz7-PVstFKo2NWiHEG?Zb5)(%f1&6;4)B<~gY2`*V8Z4$bWtcS89r~B zbLb6x{xccK`Qo0B<*D=7+-D=_k2a6_bk|KCjX#KA8Ffu};pUCt*=@AtveMnf((O*Njb&z@P>2OrHD$s=|cWiX` zubrMcvZGQpX+CB5FPZam$JSJ;Q>#u~%dac4)4s>4{?Lu#FBNyI z{hf&y8ehQFfk>rms|acq!GTh=oZ;R+f(Owyn00ksxqy znFa|ca6N18WS=F^xsqxZ{Rs3d+uk$q3dYB$PAah;^eyIABi@CNS@>nG%dbH^`t{70 zmU=akh^_YpXF%X2Aoc~HlgR@<)$-Y$2+@>P6=yfA`D*_F54`zo&XS`j#)7k(-q-1? z{66!7@&2)O;!hD@>bij+X}X!EbprqrdJkdJz1$5r(WM%6_D8#cglN)@I(s7r!yY8P z@NbE1HLW&JD)P!@o+iK`GLS*R_Z8_@r5r^kPF+t%wIyDgrz5lY&GDCA`0?U_u6Ti= zTd@kk8r#MZ6;~t-XWaVrt~@pwVH2~vdz`pzKh?uZ5#~oUbK6jq;5Uoapi7o zh8zs$l9JZMsVz-?KUx0Eu$l{Tw&rF4&FG`B{A-S-A8R!!?7AG4D7w>9lhJhZI}Z}a zd#3z7&~*se*Uy$x(+uR5Yz}|VTJf;1olJFFQs|b4kA`rmjjKvs64KsB3*t>+>+J>1 z(S^AYgq4N>aySPcOnz1G;i&yxI7R8u_psD{uACzDzMe)DXA+Ee>0Qrbz3PXIw3sLV z0If@8PRQ8P%g1jkM&uAVz{u-dHEiUrjyjfdNuA%qZyM_U6Y*u0-kW_btfo{BQL(rK zz$2j^$BOZ@EIm4uTWf8P8!^Mer54)NYP3Fy{kpt;sA@hfk4Tc>C6Zf0;@TW4ozWu_ z$~Y%+Cz|mx+EJ@sRjswH_Z}`=4{KgkpG#X$BjbCr&oC#q1B&}-Xpgmqh*)6rixIm4 zNyws7<nGtV4b zl?xmK=K`{v`C{Z}De}e3^de}F+ogz*3NcA0rS8XXLMb(AUA(Cy2&|!4=avJee>$~B zE8a|{NhQpm;B~$X@%-Kfv(#aG3KQIYqGr|DePqe_)U&U05(=~Pa4`;Re}SuF1aQysSfvYGxG_mouQc~7Jq5k>Coz0e0LJZ8SYsrh1hil6O#kxV5*r(xscrD;2D9M!6tiHmJeJrFrsqoNudVn>%wy zzoF;<0JIOo?KiU#oPt04)ze+BT{b&w zHOr>nguXe|lK%Wf1D3ape7V5f$ChpeIX}{jEE-(Tb{J?hxu4{8KLw?8s@z*hq3y1a zK{DrzHg=!Ewx7a`QdYS*t*`nWw~ck{J8KOl=4qZdY;H_#ZMSiegh)!~vE&1vO5}w% zB;uB=?7{^N9dS z-TjZCqNDady`JBYP5Uq2OJc`}?xNXeXAaP|rIdvP7C9WB*0RFJSCvV9qA>B5s9eBo|~dwXqqOcd#2hvcG{Mvm}p^DCk)$wAPxp==kXY2Pu}QwRp=^9ne2H_ z#yv|@{{V!l@-0s4JDo~LS#D;Cji)LK0geC)K)~tKwRYfOr5<*@4!jgpqtDZ!-*{da zf8j*x61}ap#nsHYRgUO~P^4y7P5A!+WDUIXdkW&Lxog_z6>F?U?%svpg5DaE-%I;_ zyywxw+L)>}Gs#*7Yg%YfB+1n$FrUA`6Ko zStOM~`J9l%g3NM8dw@6<+d>g{l#Z-CV)d8gb-x8>@jbVM87vYPw>K@Zr2vI+x%J>< z9eA!RPb;f*abme$ORvcDy=vn`@ny`mcazCwBn5&^8irT(J90Bx(^YWRsTFk2s(#jj z=Zd|~6U9CnSfOjXE1$PP7*rBOFgO5mGoEYM!s31JXEkPen0os1O<3uE7|`{T3FSuwog18%KSBpJ%Z!StSCxFuY+QY;`B%?Fj`6;)ajxpK>KA8q%!~^kzyLo0 z0IyF86$tXJk3$O;2=b%SJ{4=)uZjF0eW0=5YL5=dNcrMBwyqCSGT85oiu3Wb<4&hC zJp5!8DxApft}bmf-Bfrk*5>nkG0hzJh|z%Th|It#OohsjK5X~)uRbtRyxKTp4r|nB z&pt7B)O4#$mX0{dm4*;{4)ydHCG6_TDc?ih!mdh^jrtOJSHrr|(cbdeOKF!((9UBS z+7oLM-h<``HLfbHH0<|An2NO1v)vgUFw}n6<;MuwZvfd6gZZDvw82y4yO!^BTr4?t zd$S3U-KyM0fhyoSj{gAdS9*M&armE-e>KZMM-ck~iuZfzKnqBc*wiX!}db zuf%XurR^^2ZhGIs58B&M_(5&1M`5DaN_ANAA#MKvD~;G;$^P-;vz7`?=*W0kUq*Ny zv8cYcsa)L=^UUSQ1GzQpQ-Y-h6Vaz1XB3O&8$hs*c~fQFtNXP*RegUNIsX6v_>$+s zUNF+Ni#Q{m=E~tGjyYFyGbzXfdRL){f}JLtJFCS?4K{nGz3~>~<3En!nrnM|4MzS# zlKqYnv7D$FVy+@QgBX3pZrnQZ1r7i#iq#5q}ax`mRr|pF{u04 z^=2%`-K)~WCY9OUhfOVaJm2j`&Szo^1|x9K1$&Rmy?#$cJc(Zp3kA!}5f8 z9jJ0#w~(9nZqB~u;_AxI-%o-`F0VEn!z74Q^-<~X(!7YM)sw3|BEJ*QNmP@Zv`3mG z9A$w6Y3rW2udH(HdX8O&S}tZ%M<5bEDyh90Q`n5i^4ib6i(>?2`_)+~D-~p`AInx>Jh&!WsN*7_9l zWIkwU(L#BfxAex|bJDzZj-xtiz27U-ZFjcbr;i+MIn!0rc6xd5ZvD?ax=$_NJo8^c z2X&$JFn371r%n5ygb%%(_pBs-8TG8{5mNmR zr#=cnrudh@`j3P)U2QFG^+pretf=_6x=sTY=oErf^zG?io96W@;qg(#(x-l18`D(( z02A|U-gR*JsN$(pZO469ss5#l&jRVc475#J?X|?4Se`j7U|8UBpu_bsdszlvLsHSU{Facg?o|HIjUi>sq5q!gNRmUuhe% zy!_c5S1m}k&RUUe=#3o{#5WpL@H(F`LU$l;s(nH2>spJy1PCrw9R)b2bHsM_iJ4!dtY znHBBT)JV4XEh8&huxyr4IBbqNuM-;yPOUbjWViD?Tx=yewB)4HTdwCLuiP}3%p0nJ z57!*mt%r(G(DiWfv@|mWA--lf9V@Gv+9Ru(tq_i0G&@HhPDKjM>Io;m=294T716P| zao9<2fC2LHkys^ZHe!=fY^@sNQJ-4X>}vKs-{KCQw*LSDJPjdJx>+vBJ+bC5_*cc? zq~2#+SK%9BBh3>=e5sdYkF=7Dka9U5mE>b3YfAc~%Eh*llHGZp z#(ov}YR_D2Ii}TR)1J~9*7XEvVKP9n450^qEzl8x+?x5B=50P)iMO;Ls3F&jY2VSlsQjD}XD~qO{{#jBn z8FnmG5PTuN-s?cX(+uk5-rk7+s^07 z#(UFtOF_LBhf1?SI(c^&AtK0NHj-mdynr#+{42_FlwIK+e>QoJGg`(v`tC=r#Fm<& zx3(ptk7+`BkU%-A!?!wI^WBv}xzpyF)%lclXh~4vK$MS|FK>G2p)GCD=%V$vPf{H| zKE-@Srvc`$%fB<3Hs8n2I)2AD%9Ji z*OznCJ}&su$HjNH)7!;y6v+_te$bv@oaZFS6DMf)2OMXn_3Da-0 z^SQVCHh7-T!rm#lyuV-(?Jfjt*v9WEkAJ2=8jQj&PAVj3FqEvKzZ1y(RI%N7kL?id zbeOE6TZX|Wjw{&0w;CLh>7nc4oTEpT^wV>&_S1!^E+<=`0CH$kHg&~RfZ9Fs9zZj21YoK z)%gA_kO!wV=gKnn(ra{Z$})AOWvcT$pW-IBd8&90X1g*?cP067@;P=2+~aZUoY!s% zN9#$gtao7IzOtIy-On@dvMcJ)LehD1oR2($M0|dHde^&)Z`rvmyLUajP5qmaT6Vc> z#&__|s9W2^C!H0vOB+f7{p<6W=bm`$=~>|ExWUb_tMSSn5wBAZZIR|t902-=}eq66T z_jIKSu2xNGL@G(NxpX1Zr|D6qE%<7!ik#plDfKz z^Eun-rHP5SLmZ%t#zryeU9f5C9getJ=^xDB)BI9A9i_Aj0ekDxj@^7N^F3Ir&PVokvsMu;&4<+396W*D;)43#M9OD3g4?#{;YE$K$UYdOM z2ZyOmsYU6hQ_msPZ?ugvc8X2Y$ihQ#%1MO+kQg4^5;0z*gez2B%SENTzQ?HH3bR*Q zEiHZ7&7)dtwyzsM*=`Trd|*p~{9cvlwNnoy(z^V;4)&))S4!*hD_X?*1-y>`043C? zVs_d)n%Z($nIygxYbWj6OJqA#cr`mXWQ{<+LN|pN-T>s2+|r_@N^L)cRFtX7r||ln zXT!_?0Qg3=h;^%&9&2l6!$LUov(Ude9!&VR&u#m2j>Twh%| zl6jwVvF>ZOg*8f=iaO}iRG_01)_f=M?%MOh*4l(O62)?D8tu=TryFHuI9z8NRFZkc zcvzaxou+u$iqcbQqUG+dE#HN1Vz4{y?TbS3)0k#p*C#tl?XT~2bs z{=(i}KuHh$Ox(a=Z!KChUB5pEq0TwM?_P|e{hG7WU(D^4WZ=ab6nR7yXY@-6N2Np&Rgu^%}g^fmQRrj%4! z^>BrvqRl-b+HFJ3ytS0u>>%8L!vJ?U?ho@d%UVjB_H$S4bJc1dKI7D19CL)Jt1XWr@kQ32 zwu@mMyy48arXm}^sieD3Y`AYwW;b*g+(rQ&p_}Fr>l5(!Vzh(Xt%da?b zk~`>{1TwaGL(cDN?5d*R`LsH!B;f9K7xuB~acmKgu6MF`X8!5+735Q!s_%V|I-H$H zbFlbTZ!FsWop~G(O>mb(Ej(e;6$(z`r;H9yK9$XimoK=V{2fkQOXW^C{{Vs~#yuuz zuB>1CLVaS|@)3D&eKPIy74SBN$=kH4TzgiyIV9WI(+Mj!+Ofc1#r=zFAyb>F*Diaa z`d4fpx0g5BM|5AdmHHucOAqZ7p4wL^Ht&sy;5Ib&l~t$g+L{WpLLHKOCq(74r3Jlzdn1n72?O)d7JAd1e}ckLsY8?uV!##WL_ zojuvliK``OLv~H$5_MZe)MZl@v6EpLcTGKdo`a_Dnq_-UMJ{y4wRnr%Lm`?M2ZNFG zDfJ!4<4SbgXU?9FMiPUJ`IgT{K>%GQ*hq2qsYf2DKg88b_tLl7Ux`omuH6ye_)k{1 z(EJ;Dev^5c#QUr*;_A@Gz!_xg$IFBt@3*CS^*<%j$;s@tIV3F*tg-Y(Lf^QcbOOXz{T$Dq*O7 zVl^9UU0#P7`$2p*UxObPwf_JLTV4IKJu>8^b9ZDQGUpxez#n|qyMe7NO&)2jbzgI_ z?_jFDMJvwNO|QAw^I7hh({9B;c{@j1^y3RVo{V6Vxb~BDY60ezwIwSu)s%)3qz-eM z#%q|$X-M{q-x%q){s6PPYqwt#ya}b;Cpj=gNe)lC7~}WY)$$7oRyemCe(g6U>iT@0 z-`sp+!PHpC3omAylGCf{@^^o6;<}OFBak|hMSYDe5%!d{Lv0E2l`=`)oMN2Tw;b(z zoo=6^-aVWX6-c9>A|{qaP53zDC!ToEO7bdJf|HK7TiEfcVks%O-tBK>-Mws9)NCZP zl6Yw@TMOUh-1IKo^ufrpOOGG+dQ$y ze%-6UmM*n?#o;dF6tC<5008;{1bza!JG-Vfex>$dOYWB9_u?E3bj65hjoDoDV~Z<7;`R41se+#N?M zFm5g>^n3iy+!aMCFm61lt)Bk?GX^<4oW>9q3P~h&uJ)X@x#%^`t;+ZCtH6^07k5!w zQ*AdBT5`0xN~942@=6nd&1uxq>zIkqf(=?_rkSs#-T4zC$Q+J+D~hx^lQ`=^Ni*C0 zaq%YNNo+LjS4*~@`Y4b|s9OeEF2>Lm+q3WoI2rF>6@$yvl&eykN&S~?KU9214=;rI zt5Kbz+tKvz=+83o=HK{8FRkRb7X-dUr-FFtfzur^?O#WLzp#wbvGlor@F6&>9I9!E zl7j9w^{-XccCtsV>b9(l7eYCZGcj0!+Mz~E9`&3#qU^Uah2reDBh@X85J1Ys)$_v) z6(guL=}Pix^e&Xtq|r_Tw;AhOOH+Ajde?ybeR-y7i3Z3eNb?eA72FlR_c+P?eQV@1 z489d=IbEykyXbs|VS%Sor#H{9O^;Lf+u|)pPS+xVqy{smTFIGUMl8(=vmBM`Njdkg zn#!=W>O-2^-SvN?K4&Py(WwU{mG1Vx`IP3?d^kU6tG!xZ4e9cDh4nFLF8sD1Ce6jL z7y#Vkrah~=G^>ATstTmJZGHN7{In}?L(e5WCY%jykx=M?HLNkVOFZ9n0+JM*YcJd=#=s#*sO2v z?S%2%BrZ{AiGw779vBhS8v1G#B{)V_wfY}ZhpOiY%GSR_Gf$EzL!pGe;evN#BD$(6 zO3vq1RNbA?^oQ)#`#)%Z5@c;tR@9NLE$!~^4xS&%F7T=qjL3Qe<^o9Q2VYN-%rh#q zs!D`atgn9li1|EzXF647hgMB1-@nV`N8v4d!#*eRjjn~M_(MvUNW7UKAKCG=cM&T9 z30K@nU`~E**~N0yh9eJ4+bXiU-tT|H+Z=TvTMtXydslV6{{XJXk$%uW3}N_9@oQf2 zycZ(s8ylZ4IZslg23-5$fIj)JvCHu?#8Bp*>g(=yKFcq}%MnAGTdSw?b~woAy1QU({BRz3mU)H4RD>QQoAktV^TM5?ra0KQTb$R(0bi9T^p(+;nz5qR+#6MulUf9YyAXO;+7*lkBLn ztZ}myUB_@F@JR!w*1k5aYV~I?XJ(@9uAiatwJX)FDf>G$2W@V(Un7h7k>S+v*1376 zO9G|cl%^>e8!E(i2j8uGS$%0%rl)-w?Pc}dYHFp`nZZdTF+GQ+d&wkw$s)u#YhX8H z1mu5vippORleaa@tCQsLznykN-rVbty}4pG-vTIXwmBH-S+!|4X6&Tdwc)KE(^1sm zj{5N|E!h0i$gIJ5?i3UHcdi^wY15|NIP*T=@aGmLwCU4soNoIcO8iW|_;aj$74X-G z>^xqLs%buHe>TQYvKbgR%0iMcjC1Q>AB9+|c%N#iHs1QL^FBul98Ek&wp8_d{{X|> z`9|);bg~3tg#_f9``A>nS3d3)5=!P-ZOj#VS6`btx?Pe0TY@{gt0W#A#0lY?wjEqN5@xs z{C*`#bouUD=gC`15^xJ=ZqhdA-*zj^gksUm(zWib`JQAdV&R5Ze`Kzex6r`& z$K#8ih(0ctRdq4jx~f4DZ0wCdRUcddUWQqQSXw-d-Ss>2%rtPcc{IOM&#s_o+;<+; z?ZQc;+k}%XY0xZ!Uoeq@#~^++jafBo8B~?6VIY9ZDkt}d6iQZ2grt(W)#`eL+FX&^ z+L07+fCvNcpL+4>Q;lTjJzG4QP=!?IJ2u96j@=r2Nzp=mq9EiB25I4B`2Yn$`o3ic z(UpdmyC}A_X4iu?8+&zl?mXRrnTkX}-U{OxJu#m{Tv+OIljeu~Hm4Rgo0Gh4{#u=9 zjs7Re;!y+^P)n!V!vt3BtuTTp-=k!sH0DH~UI%wV0P zIL94xUqw#tl1IN!T4i8&>M=;JV#@#+cILI(n@wER*+Hjf5Ua_0%uaU`lSG9Xz%}Qo@@mc%H4Rx~#AvqKppqHko6RH2*x4(<7(SJr6}i&1lUCf% z4Ed?rO4i>(k_l#$EHFn52>k1J%N3!saf-6B4eBggJdv2kB>MV_x^2IUa^UarTIJ0X zLz`Q?j@~VTS8$LC4gq7FFHd7xR;;M2znzThR*e|l{K#d~t|n;|Gc?gDW>y$D2L~TY zxYUeNeHluuB9_)-DqydcM*YJi9AxLNeJF3f!@BEh9ag(&ZX&a~X%NdADoDuTi6C>* zyo@~gT%eYn4=#k%T%m0q+B2>AV|LciYC4nKLp6q)t2?VG-t0+4gcJNOUn~I56#7>- zE(x_3^?%j=M=mZgZ9%nn{a@s98qAj$ULum_SQb0EB-oH5Y*h9O*b4M1@~S+k=(lH~ zO~F#-O<2{`d>60XX|`8oV{2v1aR9puWr;kHHw=@{K9$Q1Z3s!lrjBT1aM6>C+~>9X zJB=JH5=JAFa1sN^2h-_Y_<6>^yq=v7>Jx=;c{Of^ZY00dX7h@ys{a7IDgXp}@y2VX zN_5vQ-42_^oEI*~rFetI)}z3BEsea+W&0aI$sNGhgY6E)I(m_`_4KbEo*rJ^%14h* zgLT}bm)-iF!|?0Dx_62^1>usu+RGHtO%2pX=TKMY!nSsvK>8Z_`t@g89QN6x z=j&E@h;!L!(c1iQUk!LS#Y^GsBg2||Ld_JC#UPa7b}MC=IOpa)DjnlFHKImoT2hjB zvC8~I_<3V%p=cg1@aQ&Hmu)OkTRRpO?-2)23EIRB$((u&p=OeQlTnwNpB#8 z9XKSdsmA@LU0+kVzjN|H1cg*(v5)`*@fGPPDpb`q)bx2{P70oyotJ|=Jsz>AYPz6< z%hTuQl{e@>-ZjiB5n>aZC~)Q<`V1MzR_oRk8T9sWNVI% zu&52~&3yvH+m>|Q^w;m`d#Z}kbnNu~PIpYScAcY><&HeFvFtz2E7GepmDcR^DorJI z)Uvv?ck{G2F@tZMBPjWhdm6>jbmPqjujXdyI%}E_Q(62rQf)P@h@K~vKYF7ZdFOGi zNaC)hr=zpe{Ek(LO-)Zn*!TYc2l&@V*FGTIXh*|3TWK>)EgS5y80Cj~+vZ05k0U%5 z&3I0np$};%t2{?d#vJo|o_G62_#r$S@qb;?V`%=*Z6YXi7#m6{9Y2VIGw+)AaFrUR z%JpdV@Uyi(SGp&X`@~j14`YtiV~W+ST!v7BZ?o?q&-aKdNIzdn;*4Qa5qW=1;!2$H z9{2RjzlU1g#m>JCq;Vv#c*Z#+V}T(c4svnOet4&g!+W<+ZH+NhQiboa>$X1%^h*yE zTWT7O{8rZcqmUWp0Z-j3ujn}+g?T>Ss*0wMC+ig)J(@UwiXJgtM*993=My5lk%xe-J+JN@F&SVOq*eIKU42rcv{ZRi_u^3 zJ22I^r1aF|ZS@UXNs=p=uC5}UBOHJ+J90+hf$jR&sr$KmwpP^iElz&zm9;q?PI+%G z<&saDNgR?#a%ZEq|%L%cSF-=zcVB#?&_PcgFVMu%Cyuib1Jh?vuC|W z`!@K4Qo4&*y?ZStD~NZf)Naxl9ZYx)u${xxBnt9=u;Cs<%~knh$a&X_ejDok7}l(8 z^$Tsfe65RCfz{IIoDzu-t1QXw{85MbZe%4prj{z&xmvhBZBn3>4$gR^0n))W+L*2XRbv_@_lEU6i zM&=cs7-ZN;C%R=w^d9ECtW8%osYTlV0OoL3sOHr;z0O|rwawDp0$nEghq3NI3iRpw zk>u=m!qHs4k8SvW;OonO4QcwrSxowSZg(*dJonBPHh2|e%*Ij^0>O-ihkj|#lh zs!1}p#lHYOh19yehMOg&i>zkiB?Y6lk$~VfPs-g!dFnmR*jm?IvNXchO>)Ved8YV# z?NG^iIv*w+{TaBz{{Z#-S6y63BT$Rgos+G~)ML9TPpgE!-5wrHfbItv{_6WsD&1UN(Q%sO@Vj91jx~NJh+O_z5hB=tE=bD(L&y=H32%N~Nvu*ZOCod>8Q+ zkML{5FYylg(j8C4a!%ITCB4G#iU|{INpi!vUCI!2+(|tvJX)!Wuk~tsEnn&Ve^1H9 zI=Gtu09U7UmaXaX{{TPg&%?Y^;%o00>(`pTr#zQ;*OIi-%^}M>G07&rj)fS|f`oQQ z(b1%+!9qO@n~2&Xs_TPY5ozpi8DCUc8#XT;IQrIIOkM72*;{#~a4VK_NadW`JIk+z z`mTwhCZnpxnrcjA7WUT+7UE#}!z_J5;Abs>dlOzF$I`1)+0ys7yIU`x`CRb+zY4W| zoh!ZW?V`7z`CRkeK?+LBdV)d4d(_%$=g?DkS0~dWk92#NEOFHFoYYlsQ#!6zb~Yo` zu5~1|x4oU7&cY@Lpa4}eNm2DDzpZgPFr?)=Yu=Omdz^Bm8g5gjz3D&1p{we$>le2d zQYO;a!mmXD00-m+bWx)kFi=MHX(}*`6J=Orp5Qb=+soR1LU`#~$}o?;V_78~PMgD4 zvo*_Uc2P-jbn&+Ji3>XrGC%{I3i9z%f{(VU(n$fFI z8QOOaypDOUObe+Q%AHv$HEnj&UHr~W464R*rB+vJ+S=MX@8)s?dk3=F+IT*D zg)uFrT5?XrL75Dh`8I*hbBtoVJZxa^&$r=jw>(T@i`IL77V32VGXDUCk{Dqc^6CNI zOGa;toae4Lei_HLd3Z0W%1z;UeEDtq9&QogY#>6-9e;{--nWzECc;pD~KYnq|YB44=FI0P3$xG>zj< z+qomt%@gIPYu}nbna|I4_1O}M&98G z0A!j~B(zrwl1j?wtm%67#)t67PL|X}CVf`rM3O|Z6&_3(z-*7wzE-XtHSyAn_T^n| z)?JU3t3g-CN;AE=SC?6K)b(u>Q_=nvct1nLzZSIlV70WsYZn*2<(r)!_ti!Y7yBP@!32ji!w1@SwYDkg=*?4Y-;Cz9a<$dTEu|~dikYjEBy~30xzlu3irI=yb_(1} zj(o90 zsJo^l83?;aH08ddminHT@Y7he(AQAZ?xIVZt2kAyB9%)goLxX>9rl9E0plQ7&Sn&) zRmPk&P3!4n=QA30D!9^vX*a7@y{-C~{wupWh4l9_yGbnWWp;CtN#v4#rn)eYkV2myRmZK+{qSH7HseU z&0#57>R~A~^)E#XnB)+9f-4D07`YlV#wWKyj2Ol<>)yGd`DFagWZYZxGA=P800V$) zvN|1+y3|->+PwX9N>1!evc<3NW{uBg2Nj(C*J47($SK1( z88HXwWFOteGsbhpb1Y__(%$3i`rEO~_02t}E9LL{+p%xN+DMzj78}o&Rz1u}&H!Id z_2=Pha^h!gf8owNEoQM3wb|!$S}Yfh6Sn^Vm0TX1ff*mAeKcm}4rF~2oTVORah5Tg zoA8MKSixY!sKCutN68DcROQPHyRu}D?03>fA>H#4xb-Ld)th|qO%UYg1l7$5*X&ze z)P_9)9c!7tX`(sXbI}pcY3Inma!<^S=~Wr>txAmCS5Ui_NaJ-Q4l%pe9<)Iw(+DfH z^(51wjKW%9^+&Pw^`%v{D@Soul&@&sk0gMl(uJ(1}Nx zC#h!s`61I|SdaQdtC`!m8R19ellWG2>A6&Q*=_xPMpWS^QMY?7h&&HtsOugou!l@m zH?1Jp5a5qrryc8~7U2pq=h)vBDAS`Zd)V~9iZ&XKpLwRe$i<9-glZ)+bU0vHfH}zY z74x_$LTXmu?mP?>qbSPPzoEV04-VMN;Z0#?x_d}c=Gx`wLyeIIlot2HGK>y#MRVdS zN^?ru>W+LxY07HJ-&L{a+QgREe-ZxI6rX6cmg96|X8e>GQ`1 zOHXL@^`FkVfL$l|efI7#`=E;K0yTDkQZ^?f(Fg#e$^gQ7g8$ zdVU8Js;k{v>2tU5MbX)l$ja?03i3sVz-Pq0S~XU%jik4;XBU@n$c0?YMo<%;Kvn<_-1j-Hu(4{+D_(|} zSjlRyeUasfb2h7dq7kz9{0lcJ*O2)I^UI(Lf1BTChqn&OPIh! zM@_gtOblY8N)wN>ru1aVDM#7C=z4dC?|f0?U0N&WvT~wUl1WkxtF_KZ1pfdDIXE53 z#d#Qr(WMs@&mz2O(vK=^_x}Kmx_^TI0O4soTIQ*FXLER#>f#7hf{!TxXz|H^!5udGZTBPZFx4P)ft5lse%Xe;!%=o2c zXW@8a)AaXfL*Y3(>ZG@vce8A*m>TzF4-?LClL*H$~l^Y5phr_>O%8SPZq+{0u z?x)tcUEU+weU-QB&QE#P_L|%J)a2m(+??cNw|e$vsy#_vqtkRw?M#d*t(q^D0%T%AqZ6d39>lOT;*jY8t^-`gyvLnAgzIpnT; z@^PNvSEq)ZsVGO{f7Q=R4K}GLuZf(e_QcZYxA6lq&2u6aBO6%;epBDB52qf&yHz;C zaq>G96lT1QUkcw!n)aV9kqtuaz=Ud=yWLrg@Qm$P3p z7V60yS`NEz#Y$Cdsl2C=VJeeUU%$75hUV04Ip&8V&ig&)q^kFKNO82=!-r{SE<$E1XVBEVl zZ!!G7mD19u2B#0y-TRTW;?Gd{U1<-(yGgujePT5&Q6@2IcKO{J%AgZ7Iz9-jyBi>(6tId0VB!#7&46U>#cNPnR0T?~HS3O9oEpoFd zrApka=X_P;tD$)j(q+8Tp@tNJRx6STRTx~A$36c58tlVi)tjB0XHFiCmFKHCOPi;< zxiZSk?%y*ra!Kwe2^088PNcKMvc%xAGd*Qzd-8%iZ#6BpwlIv8SXaur6YbM2u<_8PcBOcY~ zFL_-YD(zhy$Hq0eli~-&O+MDue2YPEdu0%h<%UD$#!3Oum65u4QR!NymZrC{;vX4w z-G52&9)YClOBC(Bu2UPDc*Ce5F+BkoI2GN3loe*%vDJf=eY2I%57YGj0JL1No8^ur zF2%YE`U;hKWA5(Ha&zTcbsc?kCZ@+>3kn^vs~%4kG~%gmyWCKUrnTIwr7)bex$5UA zeH;G(uha6at1e%C8dO&IkE6aFwS*rDb!fF!^J0qr%&x>aMrD|Qc^MoU`Fj5J+@gH- zd%Bm2lj4hI)ODh|UDoSs%P7s>uveu~9o{dQwi>8<&l~)69sF z_ReBH=ua8^bNW{WJtb%MwfUTo(pG&=&&NLrU&DU`ydmP*{8guFR=Sjuq&hq;ne7g8 z<%hoBeF+tGF)nzyLNK#?zfCp$JEP9S*K)+z{j}9|-%jZ8utG2(k?CJe(E44_ z`^EVnC9{>ze;QDFu|sxW(=?NFwc1Qa>s<9}^5~YQHCo)dC8_Iw349}?YrZMdEG`{x z(&pwU8Y3ZI8N!p5Am^I-OwScwl_^Rp)?L5M`7F~Hh@(bRinWt})z3olUx(w+yi2WG zFNZ$cZ>P@6&i6BtVM#VAEMMJ5duF^ERb1m2?X7<(@7JN=QmEw^ziO5L0K>lTq2WF} zv9h$+H5qi&DW{oHCL2nst_eD3|!chpW^>io+Kd2F9(4-ubydr^xO^4lZkImL; zCwh&+jtD*RgI+cwlxrwAb<5M`W5vYLg>?qjk=EDKYa6~i@eCSwg=~B>vBqy;xRU1P z;a3F~0mL5!Z;kGDKn3KFSaSf}u`l3tyE%gEx(@bamMmM`qIlGl5Er}}vwZ5`B8 z#(dbpW$q1qBaEW`)_p63i}zWTc`Muzju3DZcCM%{Q?3a_l0g}^MJJpOln#fzO20D_ zzcVX76t2-)E3-wefQU)o=0m5^E6TfnOBxg!IN*>goZ zw*LUHxbiRTuNA9r`umJqnATgTDxfLcRS)PZvMs2qozQJZQl-RdlduCnt!ozAHjBE{ z>U=Mu>i3q?wX8FnayMhiE|2(Nit=$)=t4HiKg~gY?Zt_U+aii;HKqh6cfTH{dZNpOg&pd*Y_ONaHF( zoE6e{Z=$#AMS79O)P*{Fq|n5X?mo}^Em*bu0rG9qOB;jkrimh$$qC%cjBwvH%^KRSrhD2H=1CU6qYdf z0I&=W4geV*mF2?=3bSs164Li++vIt1!c(g@>Mwa|btav@O&*o;E5Z8Co$yz}UMbal zQ){YQ-@C^KmW~Y8nFO7{bk5PoY>M-6ZkN{QN|ifrucNp1-1Bf=%jxZX{^iX%Egi)^n2NNj}DNlz9?fMtjDqBYkV7 zHqp|Z(QeXZSnx>&NjpIM*%+*67TJvA+tAtY*M|nF1oAVL^4B=)Tv)76vS}r`$BD%I zCX!p7UZ>#?5r1Jow|4T4D$PSdBLxwGDbLE^#hhoU#t%yJsp9ay)yfawmiymM{f{c1 zD+}#ggIvguRsr^FLdE znJfGXi^Sd!)HVMA3F_;uL#D3#%R>o<;uQY=%#h3KLF2fho?}v-PD=2%;!Qlpr8=CL zh*|pI^hcH1>30zcf~)KwdjqFx_UBd(*FDMAgSGzvGL_w!iFg2--Vr^rta$EQ?@uGQI~cjpdZ$_ z>tkbwrqk7U0`U!aogoyIlVOgnvr$d_z=`{J0kG(cy+?&H{(rNF?+u zqwua3kHpem)}=3Zz5f8<9(u=OX{A=BCCmOV_#dg~9yIU{q2Rq<`$yIxYdh;nj50*) z$ZGd6__bLnK=&~CsMbnQUx~;qsE&Pv4a!KbQO@zYJw9v3;5lL$1o&9-r`H($TzKqFvugk=rHw zSyveZ0vPAm3i;g5q@zv3E1~n*oZ6=-MRe|WUKa2Uqc@GL^$9N)JH*vPvM?pLEZJgz zB5TC0kBX+~sJC^$$nk4qp&D+NE}Xsmhj{Nz7gI`Yri5GhvUx&9$}*Bb82TFJ!c|d| z=1k|pR8f<<{7)3u^s9(xJ{{ZUru1av^meyaH$xa-S+RN8*E$2wlP!W=TR`>P#QNirck>~T6 z2-J_5dY?)uR7yOkbf*-#SLQ(@6fxuOHwryHt5mOZRFl2`05f|`jyNNCx@J=GGDfO1 zyFHI0yy~t}c87gV3a!c73$D7E-X*wuxU8gH5gK`Fs-R<>^NzobbzxG2lwVV)4HX9@ z`uUdp6Mc80c%w_3Oa$Jw!YEbeB%E#c&T;tBiC)%}xwc50Ok-A*l=ioCweek^r4ZBL zogr&UUENv?lmjFlNhFX#&o$vtbp7eA&l-cJ?@4I=PLIK8QSKo!#4R4(k?oywZc`a5 zI5^2s&PEO~>0DK%XU*60IIA^&YioY{94xU~>HaUYx*}M#{G{6_AhdZucOVS(>w#Xg zl&WFn2>e>DI-b4U@bZecHmh@U;`FzgtWd0WQA#e~?Fl8gQ{|}n0$_d6ak%HHApLR6 zCkSgPTE-c3gf8UmZ!?e7H|aK7WF|~Zq!k&?*3Vk*rE1fuB(yuJ+N|d*Y3g(LB5TW; zpt+G{l;P50(1Hi)UW_?u#YzgxvFJyZ5mJJ(>~~Vns_CB&Vt8)mHuA~#X%V5o3NXP0 zok;JukH);Tp;r>_k1Z;7F)r)z{R>|UCe>2sI#!%-iz~$2f!d+et7L*P!9D8?f3r^W zm5i~Jf41$JK@`5HpCI60?neEf^o+SZfs_rUtzmvMa-r+uj0TC-c* z$QVK8bIWo!5_$~a3iG3WUPaX7hrJ$DxAQn{Vl?rWgY>jZh0$WSd68neW8_@1A&ZwE zb+AC>V}XOgt)TfCtQv&2{7U`_(Y1dIYPy5ZZnrn0%&ZG51`fF8vz#yslb(2`TB4nj z9a+Yul3$6={8aG#m)Eh}$pmp~2Hhn#XhzeKox{`|=O5u);j4Qm%J%MWg{#T#^zU=a z^wpnBnoUu`Ga=a$AL4KRwR<%jYNbVOyFHqYH4>z@^)fXLFHqJexYP>oSsaIX2vffq z+x7IW>UF76N}u)Wb;7MGNmCi2XgN!(+p=Pg2|T1yncXhZKs@k1TD(Rh;inC5uktRn zZJ`ZsuKf;fStq&kXC$6-PHWOiF|ri(KOZ8?gP2o`xiJ-82-$Vm z=dDxN#>=k8wxO#_XDz$SvHY$r;dKPWGsiu?mB~tsY9^!CciiQtN;6F^ySwgtSA+Zs zKC@}zOZ$%%+Q%HSOC(m|1dnV+Se=+Vxn75k)#KHv8hp`FJbJYw2PmliCoS<)O}6mA zjqiLrd2lXP5}WRmf>@|wxO$A>`VebOJvpd*SbfI$cuSMoL+-hISFv3`z&0i+W0EAc znkHpomMtokG@E|bdbWBLsoncY?#^(+jRcv-{@LsPde^1Q z)REtInl=14x5IYttK3E%inMUX#~ETe{uRlHZxba(A2XV}_VV^I`JDE*tI6Ui98TG| z9LCIYNdDl?CqXXXyq0&{Pr_ae-Ymt!tarwXS+4pN}v68)+@A zgpkK`a}kc=q=GpP!Z1_jQ-DWYSBDA;w4C1E4+}n+MF%b!|D^38&!I<0fkXs zyi%r*PBBnNt9&`R)^$$|{{Us_@~l>5%mj@f^BsZ*eWUn5QJyiH@bPfvsm}N8c=)Ks zH96(E!uaa)J7~t82mG=>y?lN5@Ay}40-KZevg@(kgM*Xyk~qjCFCf9e{#EVC*&eHQ zM|$?!rJjkUFw_LGvoMMX+vZ%Hoc>kfxl){^c%Dmir8!bWI0@Fgb)^z>zS-V9Of}0r`<1PyF zayUMOel^iTb$Oan)ab*`r!$T9Jhn|QOt_sA8<`?@=p;mYN=2dcM)E4|(w>fgg$V zoeA!|{dII{=4*TX9!T8H8y(vvRv^Z5I^f{vgIPtTp@dpW$l`uCd{ohwUy*bun!{1m zBuVutrF6KGAs7Hep*R2#Tkm9$I%2J^W#nq&r>(R;fB4n$LsRjuibS^UA+}XmZPsMN zZ2$mB?VM*G_1}l1PD#pVZXSdbTao1&rR0`zO>J&K^Fb51T<*_d`B$$-3T;kZHa$vl zQfgB97*SjpA|aD;1hTeqgN#>vqs;d^9B#_inMqZKK~upUt6A!eC8|C1!MfI?s`yRx z*mN;@X>jq)b8=nOtH!Og@Ib)~ezo$IlqpH3&zr3n)0@1Awf_JeSlH-S+Afu)!vozS zr1y;@JexrTsL8+tfuG8XG@E?#9V#ugIWx$0P)a%sVX@l1+B>FuH21laXA;FYG7<;- zBQ@DJPl&gvKHjwz>@Mpj2H7Spsh zBRv8m2^qqaV>FZNZN5Q+ zjNwW#nn~MREj~v*8-boPUW-Sh(Hx9hryokBtWvThc!$~JbC7aIO+tS4iBH~Wh>gU0 z4wYr>EFhQk6*3g8cA9;)y~lX>vP1ZIY$u{6q?rWs_k!6l`*{19>4-guTtqF*1AZBRq|wDPDra-tCpWKEJ1rL zX@!xMeF3bcO*g7DloMq7jqAy62;T0bZu#3h)^w?*ChSExB_?O0d51kKp}QRo*y%hx zw=5bsT_eChGaL{Pp|39!$hDHW<>FmE9JTo!-^8daH7B#U(=RTrqK?KG=4A z!FK-u2*3lr1$dc!rB3mjZFcQ#wLCn!a;ME2kxK2_$=c8LJk8mmjgd(iV0h_YM`b5= zeKNCmW{#Z;O}Bdzee0T}xpq0K$wzO<^@aFlq0i$eJSz?3-OD+SB-L$YM~BRG4V{2} zz)lI>oC1BT<`!XyR9+>dlKU@vUfbV)m5-MG(8MY~T6Rf&mlu0qz4!SZZ*`|FrJd3- zRxz_KROB2Upx3(^j&qCdeFSRr&M&`_%)xg&M50JheJj zC$tZS3o@18fsBA_u7v2$PE@3yq1QsC8Oh3&lk_=QEyS9LQg8vydeW0r?t0RlsoZ_7 zCl?V5$T5j-6)|=*nWY#do={andRRj**K>oFz zNi@~ABBYvX$9?eEQcDN9l6yF{3s~da){_#cCpg0uApSG3d zc3RxR(%XF4Zic(+t1F$=bXPrY%TCavT>{Tbw_SGb?i4p_;zW^WXCTD5APfz-JoV4D ze5Fa(ZlvlrlH^ft+ACYT{*kZoOX8-hABQCPYim3gejU><V)2&_u3Z=`5o{g*6yapXfEKJ>-*4FNK9}RU&FMwYQwTqojVK0ijQD9)S z(?>sNwUY$RCtz3swR+=|!LD3Oc*^hDtrnL#u@ZR7@7e6My^e3d+GU=Z;f+UKI)%Jf zGQZg&GD9Pqc}U(^C{hb;7!95?p17_|T}jTgX!5%)cUrBxoLI`UooLbJx?1$rZQt-X zkBGWeo&B8py`|l&-6JC1!3=L1a@qapQlJ1x8NupvftvPm`m>CcDaG5Pc7HA3;(Hl= zYLSwqQCU5@{IB^OWzdS|+TK=~Vj)IR@-yx|Yt@G|B_(T~yc>j^QoqRT{uz99*FF+z zSNDD&5FfSKHH)ppd(@+2Cmy*1xvJn*W$!yb^Ev9^qgi{-&t9F)Z-Cwng700E#~vlR zZ8O5!JjpEg020$k4&;I`I=f)|00}jQVOc0FEj?Q~^9s@ASXz3?`5f=ZPl|E;RQQXn z_<`;GsPAXF9Q&F~w^~ZcXeDH{E?CJdJK8qdNWmVpg+&=?%ql3mT+xI{JBM~G-7{RW zv{jMMCm86zBVO{{+S^;SdzX4;v+I*wP?tQKXB{~y$*1`l7fkaoXX*wzS8OdE5!o9@ zL|N0If>`A;kTAJWPCxx;+On%DCb>+iN=dF?$f^8Qv9Yl|>A191DyxNDk=3v;D~dGv zXLF7)QI+rb8DQc-$ACLmUrQZbEOkB{xw$Jg%!oNIc8`-I8P9IGuO}4v*P5(eQ69+qJYZEp<6=uDrIm zc#g&qJ2}F(IR60k*7KzpM(JO<(K>OAZ)E%EX6n}_eNc$y^S2_SNI!|ffKTFcT{L0K zPgQU7I%vg4o~qw2g=0SoLo~Tv3ygIMlhH`~y7^q_{`U$jSM!(0f-yX+^H5Luo~> zzK36=*vaCH*lZ(EW|5U6T=gX2SC3L(R$S+kQcDjWd;SNmSbP%jZk?zvoh;iBqFO{*U>hmSLpdVG&W_-CkTTBO>#rK8$dMQS%m z8@otAb;mgvEI_!@_!WDHnHO0CQ#|N;HE+!qxLBjP5=HW&qce{$1xKL4$?shB()Q}> zf9mHoCY^P4zn9{8?akD;mrFE`(S>1$Z{e@0j3Ws0rE}^d7{WZOUy&kwmvS}11V;E$ zPu^kgN$V7$)R%5lqu0pwMe$~vd*OSnE?YMiX3xW_sZO0` zE9>fbN|d2hNi}<&ckJPGZ6h{t|;(3{3kj1r6wsFa?S1z1YJ@x8(xpd&Eq?)@@GVF+^SA)%gDmk^_Dl0$L5)$Qb~}uceit0 z6e!*aGcjNXLzdurcdX$?Q`M6SE?U3H;b*?o z^__iMd%35&au1&)6UXv*C_6TYHh_2uEK)exn%tE7rqQjJf44*HhEO)Qq{L z-m9&O-anRYJ5;*U>=>IE(m7q11T&NXx7U&@Yy@FCaj8?{cVCIN2|{pFp6^e@;%!l; zib#_z?TjcLYucOTYE1Q{(rQfETmJy~M`BxOaBh#!B!l=*VO&n1)}K7K=yGy>Ve`vk zEpqA`+ejyX9FhczN8E1s_03)$5~n8_e7~ z4W!2=Kh_Y$3@FLxzAMSbuW0#WvfT3Vi`qU|^xs31@!j-Vhl{Reid(saj2Ov#k2Q$^ zl5j{q-1M%zG=w{zrs_>Ti07eCo_Fc!cxCJ&_Q|dg=H@T;i{00=eMf)7 zz1T~Ve6MG>`G1k_LR^yNdoqTLWV)NkuHq$3GqWCx-nXweNhY;7t3PM3YS+uETq>qk z)<2Ro^c3jRbfb5>+;pMr)!yvp^?Pw`B9u6PaTGJK9fkp|QD>M~m$eu@^FoM2GlC_p8jQ z6vL|ekHTf^;@g`MpyFVw4FS-(|b9RHjlX&1Acn;u1r-Yq++)@ zaWwQ%irm<}@x_j_;EA*riK4xd?kVDUqy5^dM#uvaQI#jp(84sOPF(#C zCfy>6caXLcA^X{g@BP*P02=9=l#*TcU#mJ~+g9(;me*8mLjC5Mo+#0H^6+-3BcRC7 z8T6sjRHCA_2TejLBeK!{C(Yseja@C~p5srwf>?sd^0Ko6V|)TYD#Ul`pIYa5YumZb z@ajolbCk95uBQ&G4Z_H?v`!oelsGs&2t8||;c4>fbUZvcPUGUgiBaveX{EHcH*IdY zXox4~8`u_J;I;tl0InQ8CsI<1dLxeyOPWq8=#Fut@RT}6hVj||0BYaft3BKaE2~?# zm{nr~9FhPz=kIjmp8Ho#``aD1tee+jmyEm>plCYoy{6mUO7YvG?0G_#Mj=?CAmb~R zQ-Re@TyYiKgsfC6R%$Y54{e~^I|uuEd0EC-5KpkLLU@_2IW;?_T1!q{Pon+{OJbTf zt!DQz#eUEeXJX8Jxm(L%&PV{{05~Ldr>~kH*)4UKN@%$wC@jT8j@N) zt@Y!|vRWf<1~taXMoAzsEHHn&kzSoD@ovqX)T<`iZ$r+nw7Zqg_#|Jdn)D%79U16C zq-m;4V$yewiuPU9YORJ!xWor z^WwE)S{4$3G8hqz_o8;N=dtRy-V4>?@K&AT8=GQudFESqS<6`A%`i z>MMKm8+*-_Ov=$BGMu3#74Pj@+g8naUG9x-BF5uVYl(_t7=U?PoGJovGJdBO$6BN* zB^&DYIV)6+B%-f(vAyEI3Eb)W4wtEwhD$55=^XGj<=nX3r#K*tgMvHP4igs&m8VMn z^lhW_>*#s-JW{Dzbe+_rZ6BXr#}F-9&&Z{KuWy|#&v%~NmE?R4xWN^ow&sZrcwfm3 zTjk*6Ju^v4H?WkI%QHMp7Et8+dR9v5>SYxq^&y2zwN#o&xoCQZhw%4Nl07yXsVyv~ zy|nY~A-R~VN{%vw^$WYU>}MmfubISSsYS`fHj}eyZEw!qZFA-^IOxU6!ZK+)Hm#+% z?A^NB=N&eYcWQ^{lVn?lfK0g~$mMSosN-t-x{4wzO z{9Sr@xI%IFUe4wwgW*ekO7?j587H)}wzraLq=^A^+Bg_E&Q2E|q*q0JT&cx6R&BJG zpY^%ZUlmfEQ>3pZ(pvujUZ)kS+uOtEBmzSo{GpQ@vCmv_n)azmQnQt=dsJmoR&(5| zqyGTMwb>im*#kNC@R>9MsGx~YxVDL%kwzMZ$-jS2|SU&uVPT;YDo5F zO~t8dXWD6hy;YR5$j5*eAbo45b+o*8Iww`y@md|#_M_pH(=2Ufn^jww)Azy^h^Bo8 zPI2|G5}iC#oTn8VJ+E`Zg)CdCDaJ9g+U=M=B%4c`(#!iUTc;|FCHqpKBc3t0uO7AC zhmBauUezxvU-dii(XAOv+bedr{1cOkDwh)Rzb6I zB>D=%RW7+&FqKQLTQY_GzJ2Vij;&o3*DMk`DXv%~NnmG1m&-0AJUIsg@u{iE?Q&`; zyIl4^gnkLV*Yz7cHrb$gZ-0l&4n%!fn~s2UUmcp_;Z823ukQM-Pms+qQKuI+pS$O6 zPf7TZ;g1yRmo}P4iQ#=!JU^wWhSf!@gEM~|&BsU=)}ba*(MGY#H_#)InN_2$EmL;6;7O`2ubet?`8cn$;DHI zr3lHrUft}!raMdXHC=MfIG}r%X$B%emVBOocQrK)#aZ0#?ZlO4ZI>m z2Z+c;LzCYu57xbm3v}&Ha@Dui#mj)$INZ=sI!IuI%*Yo_T)O%0xE~#d!yzARr%|eC`!f zo;Fi*P5vj(;bR%&Wj8DKJbEitXp72Q8^VCU{d)R|P2SNynaSSKD@kl(yk$J?ax+>f zUKce|ylzW*5cAI*RKi~A5N^fY9?>UoC1Q$jI2k0@J$bmR#KN?sm%5FZY|`3!Q1i8j z1lJ6v=M>I2DM=@(rFUTBB`m0X5`u6I*U zeMGTX*h(0v{o7!(W1iINHmz>spEiwLrpFjHx;9Dqo$i%;X+EFjM1`eWY_{R|aJV@9 zeJkf{Q>hx9(t2O@JQ}p>#(dJfu5mG-GJtvKk9zl;(DvQ!)a*PDWG?QmZJIe|lH~+Z z#TdzE+z8|FuNNIQqZutM@Az2qF|w3YWgeRT2W#Sgv}<-z+RLWt$5FLVi#DGkB(AD4 zi4jiMz#Tvh>zeZDPBi7rr1@WT?ecvOGJ{m#H#DsK?ecrC$n(h}L3I>c{Iq5OxEaNJ zX}(u09@28Wb%7gL$w$? z>~uffL6+^~Hq*L4`q;@1NaPIv06M}?nklWBgqxC0Ud-ritR>dtf;eGv>_2t_^1xS{ zI+4S+uV$}3jYAKFmvl#)0&#+PUf`d&biaMtKj2%r}&c6>v)90 zG8BB^XCoEMi*TJ680&MJ70W6uE9#H2JZ130KOElJ>oRE9^WU^;^U0;j7n3t!a=VU4 z*B^y^eLAv&agS5vDO9Nh)NiTg{{RsNt*UtHJDqb)eI{!iJj173PNbGt<0~Fm^*QHv zOxIj$S{%3D$@(3Un^gIA*4I2E#FrN{TU|>!OT!>xAU$*MUqyzDBPhl#bv}m=1sNoY z{uR3Z$?+bKefC7XnJyz9M28!}U@%Tb4{o)+b?s@+n|4-a)#B z_*T~6NJjfylOx3{%91E{U*01yW6z)u}APpGVFR`!(~yKH4T(y39;TP=?h@omVo_=S5V zte$JdazkVc5)KI9oZ#o2^IqK=cfzR8sy)gy+ruc%`k{Uz_=Pq;fC5+yucwF zS%SN$U!cK1jXVttRC2xA)6g(fIchmww!5Bp9AfxJLD(YUv}YVk zve5a8lqyFPrR>=6gZh2!`o5W{!KeuAjKr9H(xZSfHrF;XaEzTdA9-~!#z{u>++F*c z9~5-Q)04$__fx?%GwKmEF{GQFSb2c%9lDCFJk;eHao=C*1{O|k5Q=xRK76=qi@i-* zHyeWAC|_1L)~xznx<-R}PYw6FmLoqn}~KAFXN&f(rV;#?I z))0Qur@Fn=WftcfpyPsFFES*4wo#mj>lMU_B$$o~N0-nOeZ zImQdG;EifY%1S-|00RSaTu#pCEXO9jD{{uj?zbwkHuT$dnc$C;5^gf?0~>g*3bJuc z_37$y)RT?hUWawzEkN4%wkcI&Hc}&7t3Cikaj=yqg<+lv=y|Uuq?g8N_(lnJ3n03 z7)fZNmX}ox zyL4>}lpTP<&11n_zhUc4x$8#C68E3HX1>lh-q`*gtlgbl+TbN%0~O;^c{fgD|%FwDrzX&oi$DzsMPS--774i653CeNn9L(oZ)arPZi0D z+VS0gTAbDPO>R$lc$%D6@z`67R4mBBNhPs^xrsmhYKTG7ZPj;V#x9#~qqv&ZpqFsQ zmhG6J!b$$ye|z!iMG9^Wx$gG=03f9Y7TmXEw2N6aOQrW!;SArHdAS=3KAQQ*&FR{&Xdu4r@&Fyu1Jq*1b%{0+9?dpxO zHq?mmy|a(VQmr>Oslat)=k7$Qs%pnnSBiEUrftZ7y4}AFarsu1se32Q9);7V?A_zg zPXJANd)KPX#?*8+pqE5-Z-`-{Yfn>LP zyQ!DVcEoV8JLNdePoVcS-Ag`5FIU)n?LJtqpJSl-XQy~uRTq+Yvhw1 z#c)~`Q&PII$?jE6O6tWAiF&T5b>geri_mQ@nnIFWp&Mak`AQ6N^570Q#a#$R#?Mmd zLOizIh=`m_Bwr(8`$(egx)OGhlsTCYbjaGs5hViv5}rf zJuA<|(TzP$97QO>GwdIS{u9ysedA9O==zIarOOG#krW0Sgy$7=Gi_3J`E?CCe>b@?WFIQ&IuNBx>HZ_Ty&CVC%;^=$^?)orb{J%8*F{ncw& zf-_^B0WLFNJ%*)!a6#Scinns3$Do1P%$mLeXQTfYc z*FGUPE!sKp5xlz|r{gal}rbLq1@`mmhehtQZT#>`r?(6cP7zHX5T0S*PI%6xmV`UkrET54Yuw4}FX2=rP|l^7x!2q}?hHmzlQRw!W?U zpDBvLxn7kEN15Hdes9&BzPI9;wOv-~@>0zu%*{Nkah7H|KdpLHaH^d(1<_d^r3@r# zQ;Zd~Rz_mLCexjPIV7BS>s>s}O(Un8)fU4?hvi%$c*CBnyQLo8JyKV}4mY(8hq*-+KwX0m=9JR}Knm6)VazZFYZq_>sYaojhFcB->h9N&Mf$k0mf@ zz95chX4D0h$&mj40B8C;l1C#73iRWT!oHuI6NhR_7gpQtet)U;7q5qEQG$}T*Z03$ z{p6GU6!AU1r}l=IZT+ueoc*g!VLGVy+sghRRYNz!)PByT;`=pXp`2lAHwv$n_LiTS z#a!yzrJao0RM#`5qfO^Msd5v{188EsGlE8I*o`_}#p^I^DJ&mlL}}R&b~>yfNmX#wk0ZTp+J_mLb#bbw`>=S8@VLB=i*yq$wn% zM5;oPQI(FS+u?qvcV@Cjt(IAXP@dea@k(V4Cu)uY*m$qAdc1aH0GxTD7_idG}FqT_VWHneHgl8cIImVehc%0V0+wZ~S9uT8>TPCB$BUYn;q znYHl?;ufv(N5t~$+RLPxg}_kl8U$Vj1_0^6u6#ZoIA}OU+`|uth8ivrCDT43Yg!JK z{hI~*rHMPuxK%Nh#xg-1oOdQ$r^!>d$7f9>w7n@ zrry<4dYQ2xwwQCDt#wJcBdNZ1(DdII{BH3Fi#{0XUJbvR7t*x3L)##T2OKcvx}Usj z$f1N(tMjJ%{wI+`2O3qm*Pr5flE`60x;1sq;2W{^uU_2GMtb&AdNPY6-CX*!F*VV3 z2%Q>2Bc``#q}twg-PdjB{Mjx{6I4@K#AQi?bYHVky7_ur4!d3N$H-|&~N9V*m!!yt!?9&!z!6= zqz$_`CyZl?@i8?NB@sxem zndzSm9b;{H$ANeKmnen1soa6c_wvjB8LywmUeN8#ulGOH@G@S zSQ&)TuqssZobih3it8eGMX% zs3iM$=wRy?^4;o^OE}u@#IOsu2kBmg3UP%c81y^n(~K#o$DuBrZ~p)j6jf8b@=o5Q z0g?qpS$^%e(3+B7&9`e4eUr=7S_oJ=t7J%fk5gIm-k&s#`ICnPNH*NQQ}mCokZrA>#0~+J@$!fJd6-6!>cnMoDAdZTKh## zw4l2qUU<{3D64FXR+rYVs@eUnB5dv5S)*R8fb;b@sN|Gj`ChDtO{hLwU7oL|-P>PY zOL1@G$ZahoU{V>p=-NL;0aT7USBW@HMJG+&9u(;`tm!MFZ;4+K+feYemV;-g&Egx| zXQ2ep$FD{TbN5}{4~wHd9o8=5*ivC3RYG!9d)K*y{{U#Fo7nd7wy#Y$YZmms45x`K z=S#c7_p!ueiWF>>1NeVlm4#efu+vTv_it;M)Wm&WNy00Y?#@KS){7OQ5$8JrA?!V? z*t(tSJ(25PGj4BUh1HRY>?CA3Y+!-YBQ?+?%*(DD?HeB^3)0go)>}97?OGR(Q=RPGp#m9(lW0gS=x0V@W3%>&!jyjX;-D z2G#l0XJY}?`R~t4^0D>lI4H+<&o3ETgrcJxHsAH~AWsloT=-_`^=qcOwOQj3EQc%< zgPar77^rk2tHv}{ot?qaf~=!SB<${1(kvv^HLF-M4Vhq2pd>bU0|TiikH)T~lqtI} zc)F5MrrP+AOwjxrt$3qJGwRoIT4=g-&K3!-0!W8xVu++;EEgWfwR!x|r|@gs^W3S! z;In5rcc{(c&3&$J;7Fo^HHl%1C1Z^MR6*SE0Q}8eNpeHodzULyhq~6MDXr>{eR(X7 zG4o+SA9N1irFPMzp%jtbMx0?3m56P`dd%u3J4_=oIUjik^{bPW1@86y%a`s}mei%J zMJ?U5x6&_{YY4y2^rwevboTvjXeXOmZX5XEq$ z1PjjoF`ja`KE}7?o0?x|vAcwv($kl*-TWHV<3lKcn{?MLG`%}^pW)B6{MPK*%*Qx)C$A)t>?;{knq1S>zsSaPUn`XLm*{uX zYGu41tU!*C*jqs~Hn@;8%*=N*haTfTfM8b()@d9zT=CfOogY}VokiBHieioSMIxqT zKBpc302=iw(v)8%F1z+Uij;!i{N0+{(>;#~mMsZ*8?P2awFjz~!<59gck~)_9t7r_FQHb?M3+*Bj#7i1bL> z&eLg~{%Pf2aDTce!NJ#l(t9nCVWaJzJoZ~0{)ZG7rbs2q%G{*8uor?zBOKZUqd8Y2!)%Zh3(2j$3E~6~TaU4wSQGf^ve&_-G zM896ZR~>q@brOox{Ej-+Ch8>dfguUDNy9MU~LWfBI@3ET{sZ7 zz+oK!0MAcT?OdFbiuT=qLk?L-_q~5YgqE?{PR8V6he(G~ef_7-UYeb-WF%pd`egq?klFGd84N1MB{a)=To9u+SuMoFAFqkr*D+|atJsh*S8+^ z<<*?070P+_B<7bX=+o&I+LwWJHiqCuZxzkkx1I8ykZ=!7*PiN15^JgF^SI6FuAiyF zOJi}ac!C>7Zz2-GBHX|ZPxp@;`qyk4r%ReTws%HKoja{rbK)n0rttQirOKXMsdiY! zBqwlfq^ayXiZGR%oVnjYVQTYAT*oyiYgj(gq_xb0%akGcLHG5~^sdOhXUWj&Ui0PX zR?{;itoMo@*&obl8}BK`IQKsJtt#0hp}Wx1rIwJ~msyiZ5L(T$<&nV&8oGdheiTqu zZz$<-q^e!54zI&7_(t|SRMaNEvW1uimPydANbELtt~#=<89OWb9F-kZ-zrU%{A;Df zp?H&2(P5Cy6f7oz_XggjK?ftQRD)Gc@{DTyi=_FX8lNMU0j{866^n)dV0Es&AtS2% ztnBgl9DgeM zTt2ylM7txu4%^4njr(*wW=u-C>PH5?ooIbJ(?O|+!2T}Ap2KccSmSSgPjz&#HsmAw6&Q#-mWOY&a*8YDC!=k$<*&>w6i?D9p&ws?%l<+j8 zhHpybU~$;>2?+zU+byLoZ@5bNN@v)ywBP)hk-f z+m)xPvg@YLw#Ug;%j(XxO3Oy=X03H)Z@HWojIA`OFD_q7n&N9dS~GBg9R?2#fPIbF8BkStTzgfAT%-6ziy^Sy}mQ@;L>Md{8Qa#4+R!pIY_qlWm^G?AvD4HzMBo zWf7#o95Ic)>tOWbv92jYnjE*a&KX6@9JgxzMQ;{rNvvvj7qD7IVHD0>TU+Eu9)E>> z1!;t&=+ji?E@ryD*|rj!qfJwkoSN$QW@eNR+5<2ldF@?QZOdeI)_(1gQt37`uu`f| z85Oi$>}>~hwHRj101Wg1gVT)DQTMJ@wIh*%0AoG=wMi6{77$s-r?n?*1hhw0Wqh{U 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
    l!_7ye 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%0A&GpRJmn}OvkjwLL$6hNa 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 diff --git a/docs/blog/newlang/index.html b/docs/blog/newlang/index.html deleted file mode 100644 index b7edfd13..00000000 --- a/docs/blog/newlang/index.html +++ /dev/null @@ -1,879 +0,0 @@ -<!doctype html> -<html itemscope itemtype="http://schema.org/WebPage" lang="en" class="no-js"> - <head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script> - <meta charset="utf-8"> -<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> -<meta name="robots" content="noindex, nofollow"> - - -<link rel="shortcut icon" href="/favicons/favicon.ico" > -<link rel="apple-touch-icon" href="/favicons/apple-touch-icon-180x180.png" sizes="180x180"> -<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16"> -<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32"> -<link rel="icon" type="image/png" href="/favicons/android-36x36.png" sizes="36x36"> -<link rel="icon" type="image/png" href="/favicons/android-48x48.png" sizes="48x48"> -<link rel="icon" type="image/png" href="/favicons/android-72x72.png" sizes="72x72"> -<link rel="icon" type="image/png" href="/favicons/android-96x96.png" sizes="96x96"> -<link rel="icon" type="image/png" href="/favicons/android-144x144.png" sizes="144x144"> -<link rel="icon" type="image/png" href="/favicons/android-192x192.png" sizes="192x192"> - -<title>Новый язык программирования | NewLang</title> -<meta name="description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -Более года назад я начал публикацию статей с описанием особенностей нового языка программирования. С тех пор утекло много воды, было протестировано множество идей, в итоге несколько раз все поменялось кардинальным образом и сейчас представляю на суд читателей описание предфинальной версии языка и его особенностей. -Данная статья предназначена в первую очередь для проверки основных концепций нового языка программирования, а также для получения обратной связи от читателей Хабра."> -<meta property="og:title" content="Новый язык программирования" /> -<meta property="og:description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -Более года назад я начал публикацию статей с описанием особенностей нового языка программирования. С тех пор утекло много воды, было протестировано множество идей, в итоге несколько раз все поменялось кардинальным образом и сейчас представляю на суд читателей описание предфинальной версии языка и его особенностей. -Данная статья предназначена в первую очередь для проверки основных концепций нового языка программирования, а также для получения обратной связи от читателей Хабра." /> -<meta property="og:type" content="article" /> -<meta property="og:url" content="http://localhost:1313/blog/newlang/" /><meta property="article:section" content="blog" /> -<meta property="article:published_time" content="2022-02-18T00:00:00+00:00" /> -<meta property="article:modified_time" content="2024-03-22T23:57:08+03:00" /><meta property="og:site_name" content="NewLang" /> -<meta itemprop="name" content="Новый язык программирования"> -<meta itemprop="description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -Более года назад я начал публикацию статей с описанием особенностей нового языка программирования. С тех пор утекло много воды, было протестировано множество идей, в итоге несколько раз все поменялось кардинальным образом и сейчас представляю на суд читателей описание предфинальной версии языка и его особенностей. -Данная статья предназначена в первую очередь для проверки основных концепций нового языка программирования, а также для получения обратной связи от читателей Хабра."><meta itemprop="datePublished" content="2022-02-18T00:00:00+00:00" /> -<meta itemprop="dateModified" content="2024-03-22T23:57:08+03:00" /> -<meta itemprop="wordCount" content="5445"> -<meta itemprop="keywords" content="" /><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Новый язык программирования"/> -<meta name="twitter:description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -Более года назад я начал публикацию статей с описанием особенностей нового языка программирования. С тех пор утекло много воды, было протестировано множество идей, в итоге несколько раз все поменялось кардинальным образом и сейчас представляю на суд читателей описание предфинальной версии языка и его особенностей. -Данная статья предназначена в первую очередь для проверки основных концепций нового языка программирования, а также для получения обратной связи от читателей Хабра."/> - - - - - -<link href="/scss/main.css" rel="stylesheet"> - -<script - src="https://code.jquery.com/jquery-3.6.3.min.js" - integrity="sha512-STof4xm1wgkfm7heWqFJVn58Hm3EtS31XFaagaa8VMReCXAkQnJZ+jEy8PCC/iT18dFy95WcExNHFTqLyp72eQ==" - crossorigin="anonymous"></script> -<script defer - src="https://unpkg.com/lunr@2.3.9/lunr.min.js" - integrity="sha384-203J0SNzyqHby3iU6hzvzltrWi/M41wOP5Gu+BiJMz5nwKykbkUx8Kp7iti0Lpli" - crossorigin="anonymous"></script> - - </head> - <body class="td-page td-blog"> - <header> - <nav class="td-navbar navbar-dark js-navbar-scroll"> -<div class="container-fluid flex-column flex-md-row"> - <a class="navbar-brand" href="/"><span class="navbar-brand__logo navbar-logo"><svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500" style="enable-background:new 0 0 500 500"><g><path style="fill:#fff" d="M116.8525 421.9722c-5.7041.0-10.3442-4.3127-10.3442-9.6129V88.183c0-5.3002 4.6401-9.6117 10.3442-9.6117H320.858c3.0347.0 9.3959.5498 11.7506 2.6302l.3545.3442 58.905 63.2912c2.3101 2.491 2.9202 8.4928 2.9202 11.3184v256.2039c0 5.3002-4.6407 9.6129-10.3436 9.6129H116.8525z"/><g><g><g><path style="fill:#767676" d="M384.4445 423.2066H116.852c-6.3839.0-11.5786-4.8658-11.5786-10.8474V88.1831c0-5.9804 5.1947-10.8461 11.5786-10.8461h204.0062c.377.0 9.2786.0329 12.568 2.9389l.3947.3833 58.9508 63.337c3.2135 3.4652 3.2514 11.7924 3.2514 12.1593v256.2036C396.0231 418.3408 390.8284 423.2066 384.4445 423.2066zM116.5079 411.9189c.0848.0278.1999.0531.3441.0531h267.5925c.1442.0.2581-.0253.3441-.0531V156.1556c-.0076-.9033-.3593-3.7347-.7034-5.0037l-57.6527-61.9416c-1.4651-.3176-4.4533-.6389-5.5742-.6389H116.852c-.143.0-.2594.024-.3441.0531V411.9189zm267.4533-261.149zM327.0321 89.371v.0013V89.371z"/></g></g></g><g><g><path style="fill:#5b7fc0" d="M189.0874 210.1754l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.025 2.454-11.4897 6.4116-15.4473C177.5953 212.627 183.0601 210.1742 189.0874 210.1754zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403S197.0816 234.1722 197.0804 232.033z"/><path style="opacity:.3;fill:#fff" d="M189.0898 210.176c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 212.6276 183.0612 210.176 189.0898 210.176zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 236.239 197.0839 234.2399 197.0839 232.0372z"/><g><defs><path id="SVGID_1_" d="M194.7376 237.6875c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.999 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 234.2399 196.1861 236.239 194.7376 237.6875z"/></defs><clipPath id="SVGID_2_"><use xlink:href="#SVGID_1_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_2_);fill:#fff" d="M190.0704 225.0237c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 225.7247 191.9774 225.0237 190.0704 225.0237z"/><path style="opacity:.13;clip-path:url(#SVGID_2_);fill:#020202" d="M190.0704 225.0237c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 225.7247 191.9774 225.0237 190.0704 225.0237z"/></g><g><defs><path id="SVGID_3_" d="M189.0898 210.176c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 212.6276 183.0612 210.176 189.0898 210.176zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 236.239 197.0839 234.2399 197.0839 232.0372z"/></defs><clipPath id="SVGID_4_"><use xlink:href="#SVGID_3_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_4_);fill:#5b7fc0" d="M172.6595 215.6045c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8612 12.0547.0024 21.8636-9.797 21.8613-21.8612.0024-3.8475-1.0151-7.6326-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 209.1953 176.6171 211.647 172.6595 215.6045z"/></g></g><rect x="198.8952" y="225.1043" style="fill:#5b7fc0" width="122.6266" height="13.8671"/></g><g><path style="fill:#d95140" d="M189.0874 155.7611l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.0249 2.454-11.4897 6.4116-15.4473C177.5953 158.2128 183.0601 155.7599 189.0874 155.7611zm7.993 21.8577c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403C196.2508 181.7667 197.0816 179.758 197.0804 177.6188z"/><path style="opacity:.3;fill:#fff" d="M189.0898 155.7617c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 158.2134 183.0612 155.7617 189.0898 155.7617zm7.9941 21.8613c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 181.8248 197.0839 179.8256 197.0839 177.623z"/><g><defs><path id="SVGID_5_" d="M194.7376 183.2733c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.9989 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 179.8256 196.1861 181.8248 194.7376 183.2733z"/></defs><clipPath id="SVGID_6_"><use xlink:href="#SVGID_5_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_6_);fill:#fff" d="M190.0704 170.6095c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 171.3104 191.9774 170.6095 190.0704 170.6095z"/><path style="opacity:.13;clip-path:url(#SVGID_6_);fill:#020202" d="M190.0704 170.6095c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 171.3104 191.9774 170.6095 190.0704 170.6095z"/></g><g><defs><path id="SVGID_7_" d="M189.0898 155.7617c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 158.2134 183.0612 155.7617 189.0898 155.7617zm7.9941 21.8613c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 181.8248 197.0839 179.8256 197.0839 177.623z"/></defs><clipPath id="SVGID_8_"><use xlink:href="#SVGID_7_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_8_);fill:#d95140" d="M172.6595 161.1903c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8613 12.0547.0024 21.8636-9.797 21.8613-21.8613.0024-3.8474-1.0151-7.6326-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 154.7811 176.6171 157.2327 172.6595 161.1903z"/></g><rect x="198.8952" y="170.69" style="fill:#d95140" width="122.6266" height="13.8671"/></g><g><g><path style="fill:#56a55c" d="M189.5379 264.6147l.0012-.0012c7.7751.0012 15.0294 4.1862 18.932 10.9235 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032-5.8394.0-11.3281-2.2733-15.458-6.4032-4.13-4.13-6.4032-9.6186-6.4056-15.4628.0012-6.0249 2.454-11.4897 6.4116-15.4472C178.0458 267.0663 183.5105 264.6135 189.5379 264.6147zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6538 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403C196.7013 290.6202 197.5321 288.6115 197.5309 286.4723z"/><path style="opacity:.3;fill:#fff" d="M189.5403 264.6153c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8065-21.8612-21.8613.0-6.0285 2.4516-11.492 6.4116-15.452C178.0482 267.0669 183.5117 264.6153 189.5403 264.6153zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.6366 290.6783 197.5344 288.6792 197.5344 286.4765z"/><g><defs><path id="SVGID_9_" d="M195.1881 292.1268c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.9989 7.9942-7.9941 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.5344 288.6792 196.6366 290.6783 195.1881 292.1268z"/></defs><clipPath id="SVGID_10_"><use xlink:href="#SVGID_9_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_10_);fill:#fff" d="M190.5209 279.463c-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7446-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9941 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C194.239 280.164 192.4279 279.463 190.5209 279.463z"/><path style="opacity:.13;clip-path:url(#SVGID_10_);fill:#020202" d="M190.5209 279.463c-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7446-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9941 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C194.239 280.164 192.4279 279.463 190.5209 279.463z"/></g><g><defs><path id="SVGID_11_" d="M189.5403 264.6153c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8065-21.8612-21.8613.0-6.0285 2.4516-11.492 6.4116-15.452C178.0482 267.0669 183.5117 264.6153 189.5403 264.6153zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.6366 290.6783 197.5344 288.6792 197.5344 286.4765z"/></defs><clipPath id="SVGID_12_"><use xlink:href="#SVGID_11_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_12_);fill:#56a55c" d="M173.11 270.0439c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8613 12.0547.0024 21.8636-9.797 21.8613-21.8613.0024-3.8474-1.0151-7.6326-2.9353-10.9462-3.8977-6.7325-11.1497-10.9151-18.926-10.9151C182.5311 263.6346 177.0676 266.0863 173.11 270.0439z"/></g></g><rect x="199.3456" y="279.5436" style="fill:#56a55c" width="122.6266" height="13.8671"/></g><g><g><path style="fill:#f1bc42" d="M189.0874 318.7208l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3305-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.025 2.454-11.4897 6.4116-15.4472C177.5953 321.1724 183.0601 318.7196 189.0874 318.7208zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403S197.0816 342.7176 197.0804 340.5784z"/><path style="opacity:.3;fill:#fff" d="M189.0898 318.7214c7.7763.0 15.0283 4.1826 18.926 10.915 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8612-12.0547.0024-21.8636-9.8065-21.8612-21.8612.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 321.173 183.0612 318.7214 189.0898 318.7214zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 344.7844 197.0839 342.7853 197.0839 340.5826z"/><g><defs><path id="SVGID_13_" d="M194.7376 346.2329c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.999 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 342.7853 196.1861 344.7844 194.7376 346.2329z"/></defs><clipPath id="SVGID_14_"><use xlink:href="#SVGID_13_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_14_);fill:#fff" d="M190.0704 333.5691c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0834 6.1218 2.8788C193.7885 334.2701 191.9774 333.5691 190.0704 333.5691z"/><path style="opacity:.13;clip-path:url(#SVGID_14_);fill:#020202" d="M190.0704 333.5691c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0834 6.1218 2.8788C193.7885 334.2701 191.9774 333.5691 190.0704 333.5691z"/></g><g><defs><path id="SVGID_15_" d="M189.0898 318.7214c7.7763.0 15.0283 4.1826 18.926 10.915 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8612-12.0547.0024-21.8636-9.8065-21.8612-21.8612.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 321.173 183.0612 318.7214 189.0898 318.7214zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 344.7844 197.0839 342.7853 197.0839 340.5826z"/></defs><clipPath id="SVGID_16_"><use xlink:href="#SVGID_15_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_16_);fill:#f1bc42" d="M172.6595 324.15c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8612 12.0547.0024 21.8636-9.797 21.8613-21.8612.0024-3.8474-1.0151-7.6327-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 317.7407 176.6171 320.1924 172.6595 324.15z"/></g></g><rect x="198.8952" y="333.6497" style="fill:#f1bc42" width="122.6266" height="13.8671"/></g></g></svg></span><span class="navbar-brand__name">NewLang</span></a> - <div class="td-navbar-nav-scroll ms-md-auto" id="main_navbar"> - <ul class="navbar-nav"> - <li class="nav-item"> - <a class="nav-link" href="/docs/"><span>Documentation</span></a> - </li> - <li class="nav-item"> - <a class="nav-link" href="/playground/"><span>Playground</span></a> - </li> - <li class="nav-item"> - <a class="nav-link active" href="/blog/"><span>Articles</span></a> - </li> - <li class="nav-item dropdown d-none d-lg-block"> - <div class="dropdown"> - <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">English</a> - <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/ru/blog/newlang/">Русский</a></li> - </ul> -</div></li> - </ul> - </div> - <div class="d-none d-lg-block"> - <div class="td-search td-search--offline"> - <div class="td-search__icon"></div> - <input - type="search" - class="td-search__input form-control" - placeholder="Search this site…" - aria-label="Search this site…" - autocomplete="off" - - data-offline-search-index-json-src="/offline-search-index.json" - data-offline-search-base-href="/" - data-offline-search-max-results="10" - > -</div> - </div> -</div> -</nav> - </header> - <div class="container-fluid td-outer"> - <div class="td-main"> - <div class="row flex-xl-nowrap"> - <aside class="col-12 col-md-3 col-xl-2 td-sidebar d-print-none"> - <div id="td-sidebar-menu" class="td-sidebar__inner"> - <form class="td-sidebar__search d-flex align-items-center"> - <div class="td-search td-search--offline"> - <div class="td-search__icon"></div> - <input - type="search" - class="td-search__input form-control" - placeholder="Search this site…" - aria-label="Search this site…" - autocomplete="off" - - data-offline-search-index-json-src="/offline-search-index.json" - data-offline-search-base-href="/" - data-offline-search-max-results="10" - > -</div> - <button class="btn btn-link td-sidebar__toggle d-md-none p-0 ms-3 fas fa-bars" type="button" data-bs-toggle="collapse" data-bs-target="#td-section-nav" aria-controls="td-section-nav" aria-expanded="false" aria-label="Toggle section navigation"> - </button> - </form> - <nav class="td-sidebar-nav collapse" id="td-section-nav"> - <div class="td-sidebar-nav__section nav-item dropdown d-block d-lg-none"> - <div class="dropdown"> - <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">English</a> - <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/ru/blog/newlang/">Русский</a></li> - </ul> -</div> - </div> - <ul class="td-sidebar-nav__section pe-md-3 ul-0"> - <li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child active-path" id="m-blog-li"> - <a href="/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-blog"><span class="">Articles</span></a> - <ul class="ul-1"> - <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v04-li"> - <a href="/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogparser-nuances-li"> - <a href="/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogdsl-domain-specific-language-implementation-with-macros-li"> - <a href="/blog/dsl-domain-specific-language-implementation-with-macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogdsl-domain-specific-language-implementation-with-macros"><span class="">DSL (domain-specific language) implementation with macros</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v03-li"> - <a href="/blog/release-v0.3/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v03"><span class="">Релиз языка программрования NewLang 0.3</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v02-li"> - <a href="/blog/release-v0.2/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v02"><span class="">Релиз языка программрования NewLang 0.2</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v01-li"> - <a href="/blog/release-v0.1/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v01"><span class="">Релиз языка программрования NewLang</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child active-path" id="m-blognewlang-li"> - <a href="/blog/newlang/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__page" id="m-blognewlang"><span class="td-sidebar-nav-active-item">Новый язык программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogprog-styles-same-time-li"> - <a href="/blog/prog-styles-same-time/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogprog-styles-same-time"><span class="">Можно ли использовать декларативный и императивный стили написания программ одновременно?</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogunusual-prog-li"> - <a href="/blog/unusual-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogunusual-prog"><span class="">Необычная концепция синтаксиса языка программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogcomplex-prog-li"> - <a href="/blog/complex-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogcomplex-prog"><span class="">Простое сложное программирование</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloglang-final-li"> - <a href="/blog/lang-final/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloglang-final"><span class="">Какая «идеальная» цель развития у языков программирования?</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloglogic-prog-li"> - <a href="/blog/logic-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloglogic-prog"><span class="">Проблема логических языков программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloginter-prog-li"> - <a href="/blog/inter-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloginter-prog"><span class="">Интернациональное программирование на естественных языках</span></a> -</li> - </ul> -</li> - </ul> - </nav> -</div> - - </aside> - <aside class="d-none d-xl-block col-xl-2 td-sidebar-toc d-print-none"> - <div class="td-page-meta ms-2 pb-1 pt-2 mb-0"> -<a id="print" href="/blog/_print/"><i class="fa-solid fa-print fa-fw"></i> Print entire section</a> - -</div> - - <div class="td-toc"> - <nav id="TableOfContents"> - <ul> - <li><a href="#зачем-нужен-newlang">Зачем нужен NewLang?</a> - <ul> - <li><a href="#основной-синтаксис">Основной синтаксис</a></li> - <li><a href="#расширенный-синтаксис">Расширенный синтаксис</a></li> - <li><a href="#еще-немного-примеров">Еще немного примеров:</a></li> - <li><a href="#преобразование-тензоров">Преобразование тензоров</a></li> - </ul> - </li> - <li><a href="#синтаксис-newlang">Синтаксис NewLang:</a> - <ul> - <li><a href="#основы">Основы</a></li> - <li><a href="#создания-объектов-и-присвоения-новых-значений">Создания объектов и присвоения новых значений</a></li> - <li><a href="#идентификаторы-объектов-и-модификаторы">Идентификаторы объектов и модификаторы</a></li> - </ul> - </li> - <li><a href="#система-типов">Система типов</a> - <ul> - <li><a href="#арифметические-типы">Арифметические типы:</a></li> - <li><a href="#строковые-типы-данных">Строковые типы данных:</a></li> - <li><a href="#составные-типы-данных">Составные типы данных:</a></li> - <li><a href="#перечисление">Перечисление</a></li> - <li><a href="#функции">Функции</a></li> - <li><a href="#специальные-типы-данных">Специальные типы данных:</a></li> - <li><a href="#преобразование-типов">Преобразование типов</a></li> - </ul> - </li> - <li><a href="#операторы-и-управляющие-конструкции">Операторы и управляющие конструкции</a> - <ul> - <li></li> - <li><a href="#проверки-типов--в-разработке">Проверки типов (в разработке):</a></li> - </ul> - </li> - <li><a href="#управляющие-конструкции-в-разработке">Управляющие конструкции (в разработке)</a> - <ul> - <li><a href="#условный-оператор">Условный оператор</a></li> - <li><a href="#операторы-циклов-в-планах">Операторы циклов (в планах)</a></li> - <li><a href="#обработка-ошибок-в-планах">Обработка ошибок (в планах)</a></li> - </ul> - </li> - <li><a href="#как-все-это-попробовать">Как все это попробовать?</a> - <ul> - <li><a href="#сборка-repl-из-исходников-пока-только-под-linux">Сборка REPL из исходников (пока только под Linux)</a></li> - </ul> - </li> - <li><a href="#утилита-nlc-newlangcompiler">Утилита nlc (NewLangCompiler)</a></li> - <li><a href="#планы-на-будущее">Планы на будущее</a></li> - </ul> -</nav> - </div> - - <div class="taxonomy taxonomy-terms-cloud taxo-tags"> - <h5 class="taxonomy-title">Tag Cloud</h5> - <ul class="taxonomy-terms"> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B/" data-taxonomy-term="%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B"><span class="taxonomy-label">Итераторы</span><span class="taxonomy-count">1</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8/" data-taxonomy-term="%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8"><span class="taxonomy-label">Коллекции</span><span class="taxonomy-count">4</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%BE%D0%BE%D0%BF/" data-taxonomy-term="%D0%BE%D0%BE%D0%BF"><span class="taxonomy-label">ООП</span><span class="taxonomy-count">3</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B/" data-taxonomy-term="%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B"><span class="taxonomy-label">Системые Типы</span><span class="taxonomy-count">1</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85/" data-taxonomy-term="%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85"><span class="taxonomy-label">Типы Данных</span><span class="taxonomy-count">8</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8/" data-taxonomy-term="%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8"><span class="taxonomy-label">Функции</span><span class="taxonomy-count">1</span></a></li> - </ul> - </div> - - - </aside> - <main class="col-12 col-md-9 col-xl-8 ps-md-5 pe-md-4" role="main"> - <a class="td-rss-button" title="RSS" href="/blog/index.xml" target="_blank" rel="noopener"> - <i class="fa-solid fa-rss" aria-hidden="true"></i> - </a> - -<div class="td-content"> - <h1>Новый язык программирования</h1> - - <div class="td-byline mb-4"> - - <time datetime="2022-02-18" class="text-muted">Friday, February 18, 2022</time> - </div> - <header class="article-meta"> - - </header> - <p><img alt="КДПВ" src="/blog/langs.jpeg"></p> - - -<div class="pageinfo pageinfo-primary"> -<p>Внимание!!!</p> -<p>Данная статья содержит описание синтаксиса NewLnag предыдущей версии.</p> -<p>Актуальную версию синтаксиса языка можно посмотреть <a href="/docs/">тут</a>.</p> - -</div> - -<p>Более года назад я начал публикацию статей с описанием особенностей нового языка программирования. -С тех пор утекло много воды, было протестировано множество идей, в итоге несколько раз все поменялось кардинальным образом -и сейчас представляю на суд читателей описание предфинальной версии языка и его особенностей.</p> -<p>Данная статья предназначена в первую очередь для проверки основных концепций нового языка программирования, а также для получения обратной связи от читателей Хабра. -Ведь согласно наблюдению <a href="https://habr.com/post/539674/">Хабр-ума палата</a>, не замыленный взгляд со стороны очень сильно помогает в проработке новых идей.</p> -<p>Этот проект очень долго был без собственного названия и в публикациях назывался просто и абстрактно &ldquo;новый язык&rdquo;. -Но после нескольких статей, временное название &ldquo;новый язык&rdquo; постепенно превратилось в имя собственное <em>NewLang</em>, -которое я и решил в конечном итоге оставить (что еще раз подтверждает поговорку, что нет ничего более постоянного, чем что-то временное).</p> -<p><strong>NewLang</strong> - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические конструкции -с декларативным программированием и тензорными вычислениями для задач машинного обучения.</p> -<p>Основной особенностью языка является легкий, логичный и непротиворечивый синтаксис, который основан не на использовании зарезервированных ключевых слов, -а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка). -Основные свойства и особенности языка:</p> -<ul> -<li>Возможность работы как в режиме интерпретатора, так и компилятора.</li> -<li>Динамическая и статическая типизация с возможностью указания типов в явном виде.</li> -<li>Статическая типизация является условно строгой (автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных, например, целое число может быть автоматически преобразовано в вещественное, но не наоборот)</li> -<li>Автоматическое управление памятью.</li> -<li>ООП в виде явного наследования классов и <a href="https://ru.wikipedia.org/wiki/%D0%A3%D1%82%D0%B8%D0%BD%D0%B0%D1%8F_%D1%82%D0%B8%D0%BF%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F">утиная</a> типизация.</li> -<li>На уровне синтаксиса поддержка нескольких типов функций (обычные и <a href="https://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D1%82%D0%BE%D1%82%D0%B0_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8">чистые функции без побочных эффектов</a>).</li> -<li>Необязательные и именованные параметры функций.</li> -<li>Возможны вставки кода на языке реализации (С/С++).</li> -<li>Простая интеграция с уже существующими программными библиотеками (в том числе импорт нативных переменных и функций из С/С++).</li> -<li>Имеется REPL <a href="https://ru.wikipedia.org/wiki/REPL">read-eval-print loop — «цикл: чтение — вычисление — вывод»</a>.</li> -</ul> -<h2 id="зачем-нужен-newlang">Зачем нужен NewLang?<a class="td-heading-self-link" href="#%d0%b7%d0%b0%d1%87%d0%b5%d0%bc-%d0%bd%d1%83%d0%b6%d0%b5%d0%bd-newlang" aria-label="Heading self-link"></a></h2> -<p>У всех современных языков программирования происходит постоянное развитие (читай усложнение) синтаксиса по мере выхода новых версий. -Это является своего рода, платой за появление новых возможностей и воспринимается пользователями как естественное явление.</p> -<p>Но одновременно является и серьезной проблемой, т.к. с выходом новых версий добавляются новые ключевые слова и синтаксические конструкции, -что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки -и трудоемкости поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.</p> -<p>У NewLang сложность языковых конструкций естественно ограничена за счет разделения синтаксиса языка на две части, -что упрощает его изучение и использование. <em>Основной синтаксис</em> — для написания программ в объектно-ориентированном (императивном) -и декларативном стилях, который основан не на зарезервированных ключевых словах, а на строгих грамматических правилах -и <em>Расширенный синтаксис</em> — когда основного синтаксиса становится недостаточно, или требуется использовать языковую конструкцию языка реализации.</p> -<p>Еще одно неудобство современных мейнстримовых языков, большинство из них были созданы до начала эпохи машинного обучения, -поэтому тензорные вычисления у них выполнены в виде отдельных библиотек, а не встроены в основной синтаксис языка и систему базовых типов. -У <em>NewLang</em> тензорные вычисления доступны «из коробки» (используется библиотека <a href="https://pytorch.org/">libtorch</a>), -а арифметические типы данных являются скалярами (тензорами нулевой размерности).</p> -<h3 id="основной-синтаксис">Основной синтаксис<a class="td-heading-self-link" href="#%d0%be%d1%81%d0%bd%d0%be%d0%b2%d0%bd%d0%be%d0%b9-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81" aria-label="Heading self-link"></a></h3> -<p>Основной синтаксис <em>NewLang</em> - простой и логичный за счет того, что он построен исключительно на грамматических правилах -и не использует каких либо зарезервированных ключевых слов, а все буквенно-символьные последовательности рассматриваются как идентификаторы -в которых можно использовать любые не-ASCII символы.</p> -<blockquote> -<p>Идеализированная цель отказа от ключевых слов, приблизить чтение исходного текста программы к чтению обычного текста за счет использования знаков препинания при описании логики работы алгоритма.</p> -</blockquote> -<blockquote> -<p>Конечно <em>запятая</em> человек может вычленять ключевые управляющие слова языка и <em>слеш</em> или учитывать форматирование программы <em>запятая</em> -чтобы на их основе понимать синтаксические конструкции <em>запятая</em> хотя при обычном чтении мы привыкли опираться именно на семантику -знаков препинания <em>точка</em> мы конечно можем писать знаки препинания и обычным текстом <em>точка</em> но согласитесь <em>запятая</em> что тогда -<em>открытая скобка</em> например <em>запятая</em> вот такой вот текст <em>закрытая скобка</em> будет очень не удобно читать <em>точка</em></p> -</blockquote> -<p>Названия встроенных типов или имена служебных функций системной библиотеки определяются конкретной реализацией языка, -поэтому не являются зарезервированными ключевыми словами и при необходимости могут быть переопределены, например, -для создания собственного, предметно-ориентированного диалекта (<a href="ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%B4%D0%BC%D0%B5%D1%82%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D1%8F%D0%B7%D1%8B%D0%BA">DSL - domain-specific language</a>), если в этом возникнет необходимость. -Но сама структура программы и логика выполняемого алгоритма все равно останутся понятны всем, кто знаком с правилами основного синтаксиса NewLang.</p> -<p><strong>Пример скрипта Hello world! на NewLang</strong></p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic">#!./nlc --eval </span> -</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Определение функции hello</span> -</span></span><span style="display:flex;"><span> hello<span style="color:#ce5c00;font-weight:bold">(</span>str<span style="color:#ce5c00;font-weight:bold">)</span> :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87">printf</span> :<span style="color:#ce5c00;font-weight:bold">=</span> @import<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#39;printf(format:Format, ...):Int&#39;</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Импорт стандартной C функции</span> -</span></span><span style="display:flex;"><span> printf<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#39;%s\n&#39;</span>, <span style="color:#000">$str</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Вызов C функции с проверкой типов аргументов по строке формата</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> hello<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#39;Привет, мир!&#39;</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Вызвать функцию</span> -</span></span></code></pre></div><p>Вывод: Привет, мир!</p> -<h3 id="расширенный-синтаксис">Расширенный синтаксис<a class="td-heading-self-link" href="#%d1%80%d0%b0%d1%81%d1%88%d0%b8%d1%80%d0%b5%d0%bd%d0%bd%d1%8b%d0%b9-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81" aria-label="Heading self-link"></a></h3> -<p>Расширенный синтаксис — это возможность вставить в текст программы NewLang исходный код на языке реализации. -Сейчас это С/С++, что позволяет использовать любые возможности этого мощного языка программирования.</p> -<p>Обработка расширенного синтаксиса происходит на этапе компиляции приложения, а взаимодействие между основным и расширенным синтаксисами происходит за счет совместного использования идентификаторов, -которое полностью прозрачно для пользователя и подчиняется единым грамматическим правилам основного синтаксиса.</p> -<h3 id="еще-немного-примеров">Еще немного примеров:<a class="td-heading-self-link" href="#%d0%b5%d1%89%d0%b5-%d0%bd%d0%b5%d0%bc%d0%bd%d0%be%d0%b3%d0%be-%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80%d0%be%d0%b2" aria-label="Heading self-link"></a></h3> -<p>Любая последовательность вычислений возвращает результат выполнения последнего оператора. -Поэтому выполнение одной команды или последовательности команд всегда возвращает какой-либо результат, -а оператор возврата из функции необязателен, так как результатом будет значение последнего вычисленного выражения.</p> -<p><strong>Создание переменных</strong></p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> scalar :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#0000cf;font-weight:bold">42</span> -</span></span><span style="display:flex;"><span> <span style="color:#0000cf;font-weight:bold">42</span> -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> tensor :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">[</span>1,2,3,4,5,<span style="color:#ce5c00;font-weight:bold">]</span> <span style="color:#8f5902;font-style:italic"># Тип тензора выводится автоматически</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>1, 2, 3, 4, 5,<span style="color:#ce5c00;font-weight:bold">]</span>:Char -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> str :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#4e9a06">&#39;$1 string&#39;</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$1</span> string -</span></span></code></pre></div><p><strong>Арифметические операции</strong></p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> tensor * <span style="color:#0000cf;font-weight:bold">2</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>2, 4, 6, 8, 10,<span style="color:#ce5c00;font-weight:bold">]</span>:Short -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> tensor * <span style="color:#0000cf;font-weight:bold">20</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>20, 40, 60, 80, 100,<span style="color:#ce5c00;font-weight:bold">]</span>:Short -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> tensor * 0.5 -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>0.5, 1, 1.5, 2, 2.5,<span style="color:#ce5c00;font-weight:bold">]</span>:Double -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> tensor / <span style="color:#0000cf;font-weight:bold">2</span> <span style="color:#8f5902;font-style:italic"># Результат деления — число с плавающей точкой</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>0.5, 1, 1.5, 2, 2.5,<span style="color:#ce5c00;font-weight:bold">]</span>:Double -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> tensor // <span style="color:#0000cf;font-weight:bold">2</span> <span style="color:#8f5902;font-style:italic"># Целочисленное деление без остатка</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>0, 1, 1, 2, 2,<span style="color:#ce5c00;font-weight:bold">]</span>:Char&lt;/source&gt; -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> tensor % <span style="color:#0000cf;font-weight:bold">2</span> <span style="color:#8f5902;font-style:italic"># Целочисленный остаток от деления</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>1, 0, 1, 0, 1,<span style="color:#ce5c00;font-weight:bold">]</span>:Char&lt;/source&gt; -</span></span></code></pre></div><p><strong>Строковые операции</strong></p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#000">str</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#4e9a06">&#39;сцепеление строк &#39;</span> ++ str<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> сцепеление строк <span style="color:#000">$1</span> string -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> str<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#39;строка как шаблон&#39;</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> сцепеление строк строка как шаблон string -</span></span></code></pre></div><h3 id="преобразование-тензоров">Преобразование тензоров<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b5%d0%be%d0%b1%d1%80%d0%b0%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d1%82%d0%b5%d0%bd%d0%b7%d0%be%d1%80%d0%be%d0%b2" aria-label="Heading self-link"></a></h3> -<p>В эпоху машинного обучения тензоры являются основными элементами вычислений, -поэтому для конвертирования <em>данных</em> в тензоры используется отдельная синтаксическая конструкция, -состоящая из двойных квадратных скобок <strong>[[</strong> <em>данные</em> <strong>]]</strong>. Подробнее про особенности преобразования типов можно прочитать далее.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> tstr :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">[[</span><span style="color:#4e9a06">&#34;Тест&#34;</span><span style="color:#ce5c00;font-weight:bold">]]</span> <span style="color:#8f5902;font-style:italic"># Создать тензор из строки широких символов</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>1058, 1077, 1089, 1090,<span style="color:#ce5c00;font-weight:bold">]</span>:Int -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> t2 :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">[[</span> <span style="color:#4e9a06">&#34;Тест&#34;</span> <span style="color:#ce5c00;font-weight:bold">]]</span>:Int<span style="color:#ce5c00;font-weight:bold">[</span>2,2<span style="color:#ce5c00;font-weight:bold">]</span> <span style="color:#8f5902;font-style:italic"># Тоже самое, но тензор двухмерный</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>1058, 1077,<span style="color:#ce5c00;font-weight:bold">]</span>, <span style="color:#ce5c00;font-weight:bold">[</span>1089, 1090,<span style="color:#ce5c00;font-weight:bold">]</span>, -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">]</span>:Int&lt;/source&gt; -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> StrWide<span style="color:#ce5c00;font-weight:bold">(</span>tstr<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#8f5902;font-style:italic"># Конвертировать тензор обратно в строку</span> -</span></span><span style="display:flex;"><span> Тест -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> Double<span style="color:#ce5c00;font-weight:bold">(</span>t2<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#8f5902;font-style:italic"># Изменить тип данных тезора</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>1058, 1077,<span style="color:#ce5c00;font-weight:bold">]</span>, <span style="color:#ce5c00;font-weight:bold">[</span>1089, 1090,<span style="color:#ce5c00;font-weight:bold">]</span>, -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">]</span>:Double -</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> t3 :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">[[</span> t2 <span style="color:#ce5c00;font-weight:bold">]]</span>:Char<span style="color:#ce5c00;font-weight:bold">[</span>4<span style="color:#ce5c00;font-weight:bold">]</span> <span style="color:#8f5902;font-style:italic"># Преобразовать тип данных тензора и его размерность</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">[</span>34, 53, 65, 66,<span style="color:#ce5c00;font-weight:bold">]</span>:Char -</span></span></code></pre></div><h2 id="синтаксис-newlang">Синтаксис NewLang:<a class="td-heading-self-link" href="#%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81-newlang" aria-label="Heading self-link"></a></h2> -<p>При разработке синтаксиса я старался придерживаться уже сложившихся правил, чтобы не создавать множественных смыслов, -зависящих от контекста. <del>И одновременно «объять необъятное»</del></p> -<h3 id="основы">Основы<a class="td-heading-self-link" href="#%d0%be%d1%81%d0%bd%d0%be%d0%b2%d1%8b" aria-label="Heading self-link"></a></h3> -<ul> -<li>Операторы разделяются точкой с запятой «;».</li> -<li>Отступы и переводы строк игнорируются (очень хотелось иметь возможность автоматического форматирование кода).</li> -<li>Многострочные комментарии в исходном коде соответствуют стилю С/С++ и должны располагаться между символами /* и */. Вложенность многострочных комментариев не поддерживается.</li> -<li>Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash.</li> -<li>Последовательность выполняемых команд, которая должна выполняться как единое целое, заключается в фигурные скобки «{}».</li> -<li>Программные вставки расширенного синтаксиса на языке реализации заключается в фигурные скобки со знаком процента <strong>%{</strong> <em>/* тут может быть любой код на C/C++*/</em> <strong>%}</strong>.</li> -</ul> -<h3 id="создания-объектов-и-присвоения-новых-значений">Создания объектов и присвоения новых значений<a class="td-heading-self-link" href="#%d1%81%d0%be%d0%b7%d0%b4%d0%b0%d0%bd%d0%b8%d1%8f-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%be%d0%b2-%d0%b8-%d0%bf%d1%80%d0%b8%d1%81%d0%b2%d0%be%d0%b5%d0%bd%d0%b8%d1%8f-%d0%bd%d0%be%d0%b2%d1%8b%d1%85-%d0%b7%d0%bd%d0%b0%d1%87%d0%b5%d0%bd%d0%b8%d0%b9" aria-label="Heading self-link"></a></h3> -<p>Для создания объектов и присвоения им новых значений в NewLang используется сразу три разных оператора.<br> -Оператор «<strong>::=</strong>» используется только для создания новых объектов, а если объект с таким именем уже существует, то генерируется ошибка.<br> -Оператор «<strong>:=</strong>» используется для тех же целей, но если объект с таким именем уже существует, то ошибки не происходит, -а новое значение присваивается уже существующему объекту.<br> -И последний оператор «<strong>=</strong>» применяется только для присвоения значения уже существующим объектам, и если объект с указанным именем отсутствует, то тоже происходит ошибка.</p> -<p>Использование трех разных операторов для создания/изменения объектов позволяет более гибко контролировать подобные операции и выявлять логические ошибки в коде на более раннем этапе.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span> <span style="color:#000">var</span> <span style="color:#ce5c00;font-weight:bold">::=</span> <span style="color:#0000cf;font-weight:bold">1.0</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#a40000">#</span> <span style="color:#a40000">Создать</span> <span style="color:#a40000">новую</span> <span style="color:#a40000">переменную</span> <span style="color:#000">var</span> <span style="color:#a40000">без</span> <span style="color:#a40000">указания</span> <span style="color:#a40000">типа</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">var</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#0000cf;font-weight:bold">100</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#a40000">#</span> <span style="color:#a40000">Присвоить</span> <span style="color:#a40000">новое</span> <span style="color:#a40000">значение</span> <span style="color:#a40000">уже</span> <span style="color:#a40000">существующей</span> <span style="color:#a40000">переменной</span> -</span></span><span style="display:flex;"><span> <span style="color:#f57900">printf</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#a40000">@</span><span style="color:#000">import</span><span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">&#39;</span><span style="color:#000">printf</span><span style="color:#000;font-weight:bold">(</span><span style="color:#f57900">format</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">Format</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000;font-weight:bold">...)</span><span style="color:#ce5c00;font-weight:bold">:</span><span style="color:#000">Int</span><span style="color:#a40000">&#39;</span><span style="color:#000;font-weight:bold">);</span> <span style="color:#8f5902;font-style:italic">/* Создать новый или переопределить -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> объект printf, который будет результатом выполнения глобальной функции @import */</span> -</span></span></code></pre></div><h3 id="идентификаторы-объектов-и-модификаторы">Идентификаторы объектов и модификаторы<a class="td-heading-self-link" href="#%d0%b8%d0%b4%d0%b5%d0%bd%d1%82%d0%b8%d1%84%d0%b8%d0%ba%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%be%d0%b2-%d0%b8-%d0%bc%d0%be%d0%b4%d0%b8%d1%84%d0%b8%d0%ba%d0%b0%d1%82%d0%be%d1%80%d1%8b" aria-label="Heading self-link"></a></h3> -<p>В качестве идентификаторов можно использовать буквы, цифры и знаки подчеркивания в любых комбинациях, при условии, -что первый символ идентификатора не является цифрой.</p> -<p>В NewLang существует возможность указания области видимости и времени жизни объекта с помощью модификатора — специального символа перед -именем переменной. Это может показаться немного похожим на венгерскую нотацию, но в отличие от нее, -модификатор не имеет отношения к типу объекта и не является частью имени идентификатора. -К тому же в качестве модификаторов используется строго определённые символы, назначение которых определено заранее.</p> -<p>Так, символ «<strong>$</strong>» в начале имени обозначает локальную переменную, время жизни которой ограничено текущей областью видимости и при её завершении локальная переменная уничтожается. -Символ «<strong>@</strong>» обозначает глобальную переменную, а сам объект сохраняет свое состояние даже после выхода из текущей области видимости. -Так же обозначаются и имена типов данных, например, при создания новых типов, а в качестве модификатора используется символа двоеточия «<strong>:</strong>»</p> -<p>Семантика обращения к аргументам функций очень похоже на работу с аргументами в bash скриптах, где <strong>$1</strong> или <strong>$arg</strong> — порядковый номер -или имя аргумента (происходит обращение к локальным переменным в текущей области видимости).</p> -<p>Использование модификаторов является обязательным только в двух случаях: -- При создании нового типа данных, так как типы всегда создаются в глобальной области видимости, а их символьные имена должны быть уникальными -- При обращении к объектам NewLang внутри программных вставок кода на языке реализации, так как они используется как маркеры при поиске идентификаторов NewLang в коде С/С++.</p> -<p>В остальных случаях, для обращения к переменным указывать их модификаторы не обязательно. -И если при обращении к объекту модификатор не указан, то сперва ищется локальная переменная, а потом глобальная с таким же именем. -Причем, локальная переменная будет перекрывать глобальную.</p> -<p>Так же следует иметь в виду, что компилятор может генерировать код для прямого обращения к локальным объектам уже на этапе компиляции, -тогда как для обращения к глобальным объектам, или если модификатор области видимости отсутствует, компилятор вынужден каждый раз встраивать runtime вызов функции поиска объекта в таблице символов.</p> -<h2 id="система-типов">Система типов<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0-%d1%82%d0%b8%d0%bf%d0%be%d0%b2" aria-label="Heading self-link"></a></h2> -<p>Так как система типов языка динамическая, то явное указание типа не влияет на размер переменной и является только своего рода логическим ограничением на возможность присвоения переменной значения другого типа.</p> -<p>Информация о типах используется при проверке их совместимости, когда существующему объекту присваивается значение другого типа. -Такая операция возможна только когда типы совместимы между собой и допускают автоматическое приведение. -Это справедливо как во время парсинга/компиляции исходного теста, так и во время выполнения в режимах интерпретатора и/или скомпилированного файла.</p> -<h3 id="арифметические-типы">Арифметические типы:<a class="td-heading-self-link" href="#%d0%b0%d1%80%d0%b8%d1%84%d0%bc%d0%b5%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b" aria-label="Heading self-link"></a></h3> -<p>Арифметические типы данных являются тензорами - массивами чисел одного типа с произвольным количеством измерений и одинаковым размером столбцов в каждом. -Единичное число тоже тензор нулевого размера.</p> -<p>Поддерживаются только знаковые целые числа, т.к. в беззнаковых числах особая нужда отсутствует, а проблем с ними можно найти очень много на ровном месте.</p> -<p><strong>Проблемы беззнаковых чисел (из интернета)</strong></p> -<blockquote> -<p>Во-первых, вычитание двух беззнаковых чисел, например 3 и 5. 3 минус 5 равно 4294967294, -т.к. -2 не может быть представлено как беззнаковое число. Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных -значений со знаком и без знака. С++ может свободно преобразовывать числа со знаком и без знака, -но не проверяет диапазон, чтобы убедиться, что вы не переполняете свой тип данных.</p> -<p>В C++ всё же есть несколько случаев, когда можно (или необходимо) использовать беззнаковые числа. -Во-первых, числа без знака предпочтительнее при работе с битами. Во-вторых, использование беззнаковых чисел связаных с индексацией массивов.</p> -</blockquote> -<p>Но это мой случай, так как индекс может быть отрицательным и даже не числом, а диапазоном или многоточием. -З.Ы. И даже зная об этом, все равно умудрился недавно словить баг с отрицательными индексами у словарей!</p> -<p>Имена встроенных арифметических типов говорят сами за себя: Char, Short, Int, Long, Float, Double, ComplexFloat, ComplexDouble. -Отдельным типом идет логический тип Bool, который может принимать значения только 0 или 1 (false/true соответственно), -и в зависимости от выполняемой операции может быть отнесен к целочисленным типам, так и не входить в их состав.</p> -<p><em>(данный подход интерпретации логического типа данных был взят из библиотеки Torch)</em></p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">// Treat bool as a distinct &#34;category,&#34; to be consistent with type promotion -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">// rules (e.g. `bool_tensor + 5 -&gt; int64_tensor`). If `5` was in the same -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">// category as `bool_tensor`, we would not promote. Differing categories -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">// implies `bool_tensor += 5` is disallowed. -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">// -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">// NB: numpy distinguishes &#34;unsigned&#34; as a category to get the desired -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">// `bool_tensor + 5 -&gt; int64_tensor` behavior. We don&#39;t, because: -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">// * We don&#39;t want the performance hit of checking the runtime sign of Scalars. -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic">// * `uint8_tensor + 5 -&gt; int64_tensor` would be undesirable. -</span></span></span></code></pre></div><p>В будущем планируется добавить классы чисел для длинной арифметики и дробей, для чего зарезервированы названия типов BigNum, Currency и Fraction.</p> -<p>Доступ к элементам тензора происходит по целочисленному индексу, который начинается с 0. -Для многомерного тензора, индексы элемента перечисляются в квадратных скобках через запятую. -Поддерживается доступ к элементам через отрицательный индекс, который обрабатывается точно так же, -как в Python (-1 последний элемент, -2 предпоследний и т.д.).</p> -<p>Литерал тензор в тексте программы записывается в квадратных скобках с обязательной завершающей запятой, т.е. [1, 2,] - это литерал одномерный тензор из двух чисел. -После закрывающей скобки тип тензора может быть указан в явном виде. Если тип не указан, то он выводится автоматически на основании указанных данных и выбирается минимально возможный байтовый размер, -который позволяет сохранить все значения без потери точности.</p> -<p>Примеры:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#000">$var_char</span> :<span style="color:#ce5c00;font-weight:bold">=</span> 123<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Тип Char выводится автоматически</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$var_short</span> :<span style="color:#ce5c00;font-weight:bold">=</span> 1000<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Тип Short выводится автоматически</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$var_bool</span> :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">[</span>0, 1, 0, 1,<span style="color:#ce5c00;font-weight:bold">]</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Тензор из 4 элементов. Тип Bool выводится автоматически</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$tensor</span><span style="color:#ce5c00;font-weight:bold">[</span>10,10<span style="color:#ce5c00;font-weight:bold">]</span>:Int :<span style="color:#ce5c00;font-weight:bold">=</span> 1<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Тензор Int размером 2x2 инициализированный 1</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$scalar</span> :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">$tensor</span><span style="color:#ce5c00;font-weight:bold">[</span>5,5<span style="color:#ce5c00;font-weight:bold">]</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Присвоить скаляру значение указанного элемента тензора</span> -</span></span></code></pre></div><h3 id="строковые-типы-данных">Строковые типы данных:<a class="td-heading-self-link" href="#%d1%81%d1%82%d1%80%d0%be%d0%ba%d0%be%d0%b2%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85" aria-label="Heading self-link"></a></h3> -<p>Поддерживаются два типа строк, StrWide - символьные (широкие) и StrChar — байтовые. Различия между ними заключается в типе единичного элемента. -У символьных строк единичным элементом является широкий символ wchar_t, а у байтовой строки единичным элементом является один байт (точнее char, т. е. байт со знаком). -Символьные строки литералы в исходном тексте записывается в «двойных кавычках», а байтовые строки в &lsquo;одинарных кавычках&rsquo;.</p> -<p>Количество элементов символьной строки возвращается в широких символах, а размер байтовой строки в байтах, поэтому и обращение к элементу строки по индексу происходит соответственно либо к символу, либо к байту.</p> -<p>Важный момент. К любой переменной можно обратиться так же, как к функции (записав после её имени круглые скобки). -Результатом этой операции будет создание копии/клона объекта. Причем некоторые типы (словари, классы и символьные строки) можно использовать в качестве шаблона -при создании копии объекта с модифицированными свойствами, если новые и/или изменяемые значения указать в скобках, как аргументы при вызовах функций. -Так, если при создании копии в скобках указать набор новых данных, то результирующая копия будет содержать уже измененные данные.</p> -<p>Например:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#000">$template</span> :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#4e9a06">&#34;</span><span style="color:#4e9a06">${</span><span style="color:#000">name</span><span style="color:#4e9a06">}</span><span style="color:#4e9a06"> </span><span style="color:#000">$1</span><span style="color:#4e9a06">&#34;</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Обычная строка</span> -</span></span><span style="display:flex;"><span><span style="color:#000">$result</span> :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">$template</span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;шаблон&#34;</span>, <span style="color:#000">name</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#4e9a06">&#34;Строка&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># result = &#34;Строка шаблон&#34;</span> -</span></span></code></pre></div><h3 id="составные-типы-данных">Составные типы данных:<a class="td-heading-self-link" href="#%d1%81%d0%be%d1%81%d1%82%d0%b0%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85" aria-label="Heading self-link"></a></h3> -<h4 id="словарь">Словарь<a class="td-heading-self-link" href="#%d1%81%d0%bb%d0%be%d0%b2%d0%b0%d1%80%d1%8c" aria-label="Heading self-link"></a></h4> -<p>Словарь — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии -(он похож и на tuple и на структуру одновременно). Словари от тензоров отличаются тем, что являются только одномерными массивами, -но каждый элемент может содержать произвольное количество элементов любого типа, в том числе и другие словари.</p> -<p>Доступ к элементам словарей происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. -Индекс также начинается с 0 и как у тензоров, тоже может быть отрицательным.</p> -<p>Литерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, -т.е. (,) - пустой словарь, (1, 2= «2», name=3,).</p> -<h3 id="перечисление">Перечисление<a class="td-heading-self-link" href="#%d0%bf%d0%b5%d1%80%d0%b5%d1%87%d0%b8%d1%81%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> -<p>Перечисление - это не отдельный тип данных, а обычный словарь, у которого все элементы имеют уникальные имена и целочисленные значение, -которое явно указывается при определении или вычисляется автоматически (на единицу больше предыдущего элемента). -У перечислений тип значения указывается сразу после закрывающей скобки через двоеточие (ONE=1, TWO=, THREE=): Int.</p> -<h4 id="классы">Классы<a class="td-heading-self-link" href="#%d0%ba%d0%bb%d0%b0%d1%81%d1%81%d1%8b" aria-label="Heading self-link"></a></h4> -<p>Класс (реализовано частично) - тип данных, с помощью которого реализуется один из принципов ООП - наследование. -При создании экземпляра класса создается новая переменная, у которой сохраняется информацию о своем родителе -и которая наследует от него свойства и методы. Тип данных «класс» аналогичен словарю, -но все свойства обязаны иметь имена (хотя доступ к свойствам класса по индексу так же возможен). -Литерал с типом «Класс» в тексте программы записывается в круглых скобках без завершающей запятой, т. е. () - пустой класс, (1, 2= «2», name=3).</p> -<p>Пока остальные детали классов до конца не реализованы, поэтому описывать их не буду, т. к. в итоговом варианте синтаксис классов и определения их методов могут поменяться.</p> -<h3 id="функции">Функции<a class="td-heading-self-link" href="#%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h3> -<p>Синтаксис NewLang поддерживать несколько типов функций (а в будущем и методов классов): обычные функции, чистые функции и простые чистые функции.</p> -<p>Для всех типов функций поддерживаются аргументы по умолчанию. При создании функции, её аргументы указываются как в Питоне, -т.е. вначале идут обязательные аргументы, потом аргументы со значениями по умолчанию, -где имя аргумента отделяется от его значения по умолчанию знаком равно «=». -Если функция допускает обработку произвольного количества аргументов, то последним в списке параметров указывается многоточие.</p> -<h4 id="обычная-функция">Обычная функция<a class="td-heading-self-link" href="#%d0%be%d0%b1%d1%8b%d1%87%d0%bd%d0%b0%d1%8f-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8f" aria-label="Heading self-link"></a></h4> -<p>Обычная функция — такие функции являются именно обычными функциями в понимании С/С++. -Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д.</p> -<p>Внутри обычной функции можно обращаться к локальным и глобальным объектам, и они могут содержаться вставки на языке реализации, например, для вызова функций из внешних библиотек.</p> -<p>Вставки на языке реализации оформляются в виде <strong>%{</strong> <strong>%}</strong> и могут содержать любой текст на С/С++, -а прямо из него можно обращаться к локальным и глобальным объектам NewLang так же, как и в обычном синтаксисе, -указывая первым символом имени соответствующий модификатор (<strong>$</strong> для локальных объектов и <strong>@</strong> для глобальных).</p> -<p>Технически, такая программная вставка просто переносится трансплайтером непосредственно в исходный текст генерируемого файла, -а все идентификаторы NewLang специальным образом декорируются (добавляются специальные маркеры для их идентификации), -после этого исходный текст подается на вход обычному компилятору С++. -Для локальных объектов трансплайтер может генерировать код для прямого доступа к объекту на этапе компиляции, -а для работы с глобальными объектами вынужден использовать runtime вызовы функции поиска в таблице символов.</p> -<p>Например:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#000">print</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">str</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">printf</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;%s&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">static_cast</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#204a87;font-weight:bold">const</span> <span style="color:#204a87;font-weight:bold">char</span> <span style="color:#ce5c00;font-weight:bold">*&gt;</span><span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">$</span><span style="color:#000">str</span><span style="color:#000;font-weight:bold">));</span> <span style="color:#8f5902;font-style:italic">/* Прямой вызов С функции */</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">};</span> -</span></span></code></pre></div><h4 id="чистые-функции">Чистые функции<a class="td-heading-self-link" href="#%d1%87%d0%b8%d1%81%d1%82%d1%8b%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h4> -<p>Чистая функция - это тоже обычная функция, только в том смысле, какой в него вкладывает функциональное программирование. -Создания чистой функции происходит с помощью оператора «:-». У чистой функции отсутствует доступ к контексту и глобальным объектам, -поэтому она может обрабатывать только те данные, которые были ей переданы в качестве аргументов.</p> -<p>Программные вставки на языке реализации внутри чистых функций не запрещены и могут использоваться, например, для отладки. -Но делается это на страх и риск разработчика. Именно он отвечает за их «чистоту», например при вызове функций из внешних библиотек.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> Sum<span style="color:#ce5c00;font-weight:bold">(</span>arg1, arg2<span style="color:#ce5c00;font-weight:bold">)</span> :- <span style="color:#ce5c00;font-weight:bold">{</span><span style="color:#000">$arg1</span>+<span style="color:#000">$arg2</span><span style="color:#000;font-weight:bold">;</span><span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Вернуть сумму аргументов</span> -</span></span></code></pre></div><p>Так как в языке отсутствует оператор возврата данных из текущего блока выполнения (аналог оператора return &lt;данные&gt;), -то возвращаемым значением функции / блока кода всегда является результат выполнения последней операции.</p> -<h4 id="простые-чистые-функции">Простые чистые функции<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%be%d1%81%d1%82%d1%8b%d0%b5-%d1%87%d0%b8%d1%81%d1%82%d1%8b%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h4> -<p>Простые чистые функции — отдельный класс чистых функций, которые предназначены только для вычисления логического результата -(т.е. они являются предикатами) и их отличает упрощенная формой записи. -Тело простой чистой функции состоит из последовательности операторов, которые разделяются запятыми и заканчиваются, -как и любое выражение, точкой с запятой. Все операторы простой чистой функции всегда приводятся к булевому значению, -а итоговый результат функции вычисляется по одной из возможных логических операций: <em>И</em>, <em>ИЛИ</em> и <em>исключающее ИЛИ</em>.</p> -<p>Например:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> func_and<span style="color:#ce5c00;font-weight:bold">(</span>arg1, arg2<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;=</span> <span style="color:#000">arg1</span><span style="color:#ce5c00;font-weight:bold">==</span>3, arg2 &gt; 0<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Простая чистая функция Логическое И</span> -</span></span><span style="display:flex;"><span> func_or<span style="color:#ce5c00;font-weight:bold">(</span>arg1, arg2<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">||=</span> <span style="color:#000">arg1</span><span style="color:#ce5c00;font-weight:bold">==</span>3, arg2 &gt; 0<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Простая чистая функция Логическое ИЛИ</span> -</span></span><span style="display:flex;"><span> func_xor<span style="color:#ce5c00;font-weight:bold">(</span>arg1, arg2<span style="color:#ce5c00;font-weight:bold">)</span> ^^<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">arg1</span><span style="color:#ce5c00;font-weight:bold">==</span>3, arg2 &gt; 0<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Простая чистая функция Исключающее ИЛИ</span> -</span></span></code></pre></div><h3 id="специальные-типы-данных">Специальные типы данных:<a class="td-heading-self-link" href="#%d1%81%d0%bf%d0%b5%d1%86%d0%b8%d0%b0%d0%bb%d1%8c%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85" aria-label="Heading self-link"></a></h3> -<h4 id="none">None<a class="td-heading-self-link" href="#none" aria-label="Heading self-link"></a></h4> -<p>None (пустой тип) — не содержит значения (точнее имеет одно значение None) и совместим с любым другим типом данных. -Указывается в тексте программы как один подчерк «_». Значение None имеют не инициализированные переменные -и при попытке чтения из такой переменной возникает ошибка.</p> -<p>Тип переменной может быть явно указан или выведен автоматически из присваиваемого значения. -Присвоить новое значение уже инициализированной переменной можно только для совместимого типа, так как неявное преобразование типов не допускаются.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#000">$var</span> :<span style="color:#ce5c00;font-weight:bold">=</span> _<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Создать переменную со значением None</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$var2</span> :<span style="color:#ce5c00;font-weight:bold">=</span> var<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Ошибка!!! Нельзя прочитать неинициализированную переменную var</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$var</span> <span style="color:#ce5c00;font-weight:bold">=</span> 1000<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># У переменной будет тип Short (минимальный размер для хранения значения)</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$var</span> <span style="color:#ce5c00;font-weight:bold">=</span> 0,5<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Ошибка!!! Short ← Float не совместимы</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$var</span> <span style="color:#ce5c00;font-weight:bold">=</span> _<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Очистить значение переменной</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$var</span> <span style="color:#ce5c00;font-weight:bold">=</span> 0,5<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Теперь можно, т. к. None совместим с любым типом</span> -</span></span></code></pre></div><h4 id="диапазон-range">Диапазон (Range)<a class="td-heading-self-link" href="#%d0%b4%d0%b8%d0%b0%d0%bf%d0%b0%d0%b7%d0%be%d0%bd-range" aria-label="Heading self-link"></a></h4> -<p>Диапазон (реализовано частично) — специальный тип данных, являющейся приблизительным аналогом типа «генератор» в Python. -К диапазону можно обращаться как к итератору и он будет поочередно выдавать элементы в указанном интервале с заданным шагом. -Диапазон в тексте программы указывается как два или три элемента через две точки, например 1..5 — диапазон от единицы до пяти с шагом по умолчанию 1. -В качестве параметров диапазона можно указывать не только литералы, но и имена переменных. -Например, 0,1..<em>$stop</em>..0,1 — диапазон от значения 0,1 до значения, указанного в переменной <em>$stop</em> с шагом 0,1.</p> -<p>Диапазон для целых чисел можно использовать в качестве индекса у тензоров (точнее, у любых объектов, которые допускают доступ к своим элементам по индексу, -т.е. тензоры, словари и текстовые строки). Фактический, это поведение аналогично slice в языке Python и array[1:5] -в Python означает тоже самое, что и array[1..5] в NewLang.</p> -<p>В качестве индекса у тензоров еще можно указать произвольное количество измерений с помощью многоточия, т.е.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#000">$tensor</span><span style="color:#ce5c00;font-weight:bold">[</span>…, 0<span style="color:#ce5c00;font-weight:bold">]</span> <span style="color:#ce5c00;font-weight:bold">=</span> 0<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Обнулить все первые элементы в каждом измерении.</span> -</span></span></code></pre></div><h4 id="итераторы">Итераторы<a class="td-heading-self-link" href="#%d0%b8%d1%82%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b" aria-label="Heading self-link"></a></h4> -<p>Итераторы (в разработке) - самый сложный и неоднозначный тип данных для работы с элементами коллекций.<br> -Для работы с итераторами зарезервированы символы &ldquo;!&rdquo; и &ldquo;?&rdquo;, но сами итераторы пока не реализованы.</p> -<h3 id="преобразование-типов">Преобразование типов<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b5%d0%be%d0%b1%d1%80%d0%b0%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d1%82%d0%b8%d0%bf%d0%be%d0%b2" aria-label="Heading self-link"></a></h3> -<h4 id="явное-приведение-типов">Явное приведение типов<a class="td-heading-self-link" href="#%d1%8f%d0%b2%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%b8%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5-%d1%82%d0%b8%d0%bf%d0%be%d0%b2" aria-label="Heading self-link"></a></h4> -<p>Несмотря на динамическую типизацию языка, если тип переменной указан явно, то автоматическое приведение типов не выполняется, -и чтобы присвоить переменой значение не совместимого типа, требуется явное преобразование.</p> -<p>Так как символьные названия типов относятся к деталям реализации, то явное преобразование в конкретный тип данных производится с помощью вызова функции с системным именем, -т. е. Bool(), StrWide(), Long и т. д. Причем у тензоров при таком преобразовании изменяется только тип данных, но размерность тензора не меняется.</p> -<p>Для преобразования любого типа данных в строку ещё можно использовать оператор конкатенации строк, которой преобразует любой тип данных в строковое представление. -Но так как строковых типов два (байтовые и широкие строки), то тип строки определяется первым аргументом в операторе конкатенации, т. е.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#4e9a06">&#34;&#34;</span> ++ <span style="color:#0000cf;font-weight:bold">123</span> <span style="color:#8f5902;font-style:italic"># &#34;123&#34; - Строка широких символов</span> -</span></span><span style="display:flex;"><span> <span style="color:#4e9a06">&#39;&#39;</span> ++ <span style="color:#0000cf;font-weight:bold">123</span> <span style="color:#8f5902;font-style:italic"># &#39;123&#39; - Байтовая строка</span> -</span></span></code></pre></div><pre><code>Или преобразовать любое значение в строковое с помощью строки-шаблона: -</code></pre> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> val :<span style="color:#ce5c00;font-weight:bold">=</span> 12345<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#4e9a06">&#34;</span><span style="color:#000">$1</span><span style="color:#4e9a06">&#34;</span><span style="color:#ce5c00;font-weight:bold">(</span>val<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#8f5902;font-style:italic"># Будет строка &#34;12345&#34;</span> -</span></span></code></pre></div><h4 id="tensor-comprehensions">Tensor comprehensions<a class="td-heading-self-link" href="#tensor-comprehensions" aria-label="Heading self-link"></a></h4> -<p>В эпоху машинного обучения тензоры являются основным элементом вычислений, поэтому для конвертирования <em>данных</em> в тензоры используется отдельная синтаксическая конструкция, -состоящая из двойных квадратных скобок <strong>[[</strong> <em>данные</em> <strong>]]</strong>. Фактически это оператор и функция времени выполнения в зависимости от указанных между двойные квадратными скобками выражения.</p> -<p>Чтобы преобразовать любую переменную в тензор (с учетом допустимости такого преобразования), её достаточно указать между двойными квадратными скобками. -Выражение <strong>[[</strong> <em>varibale</em> <strong>]]</strong> - преобразует переменную <em>varibale</em> в одномерный тензор с автоматическим выводом типа данных. -Для преобразования в одномерный тензор конкретного типа используется выражение <strong>[[</strong> <em>varibale</em> <strong>]]</strong>:<em>Type</em>, где _Type- - любой из арифметических типов.</p> -<p>Если требуется преобразовать переменную не в одномерный тензор, а в тензор конкретного типа и заданной размерности, -то это делается выражением [[ varibale ]]:Type[2,2], которая вернет тензор с размерностью 2х2 и типом Type у элементов.</p> -<p>Внутри двойных квадратных скобок может быть не только любое выражение, но и литерал или диапазон. -В этом случае, они также раскрываются в тензор по таким же правилам.<br> -В будущем планирую добавить возможность указания сразу нескольких значений через запятую для их объединения в один тензор.</p> -<p>Примеры:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#000;font-weight:bold">[[(</span><span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">,</span><span style="color:#0000cf;font-weight:bold">2</span><span style="color:#000;font-weight:bold">,</span><span style="color:#0000cf;font-weight:bold">3</span><span style="color:#000;font-weight:bold">)]]</span> <span style="color:#8f5902;font-style:italic"># Тензор из словаря</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">2</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">3</span><span style="color:#000;font-weight:bold">,]:</span><span style="color:#000">Char</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#000;font-weight:bold">[[</span><span style="color:#4e9a06">&#39;first second&#39;</span><span style="color:#000;font-weight:bold">]]</span> <span style="color:#8f5902;font-style:italic"># Байтовая строка в тензор</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">102</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">105</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">114</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">115</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">116</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">32</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">115</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">101</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">99</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">111</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">110</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">100</span><span style="color:#000;font-weight:bold">,]:</span><span style="color:#000">Char</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#000;font-weight:bold">[[(</span><span style="color:#000">first</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#4e9a06">&#39;first&#39;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">space</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#0000cf;font-weight:bold">32</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">second</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#4e9a06">&#39;second&#39;</span><span style="color:#000;font-weight:bold">)]]</span> <span style="color:#8f5902;font-style:italic"># Получаем тензор из словаря с такими же данными</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">102</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">105</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">114</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">115</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">116</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">32</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">115</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">101</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">99</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">111</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">110</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">100</span><span style="color:#000;font-weight:bold">,]:</span><span style="color:#000">Char</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#000;font-weight:bold">[[</span> <span style="color:#0000cf;font-weight:bold">0</span> <span style="color:#ce5c00;font-weight:bold">...</span> <span style="color:#000;font-weight:bold">]]:</span><span style="color:#000">Double</span><span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">10</span><span style="color:#000;font-weight:bold">,</span><span style="color:#0000cf;font-weight:bold">2</span><span style="color:#000;font-weight:bold">]</span> <span style="color:#8f5902;font-style:italic"># Тензор заданного формата с нулями</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">[</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,],</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">]:</span><span style="color:#000">Double</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#000;font-weight:bold">[[</span> <span style="color:#000">rand</span><span style="color:#000;font-weight:bold">()</span> <span style="color:#ce5c00;font-weight:bold">...</span> <span style="color:#000;font-weight:bold">]]:</span> <span style="color:#000">Int</span><span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">3</span><span style="color:#000;font-weight:bold">,</span><span style="color:#0000cf;font-weight:bold">2</span><span style="color:#000;font-weight:bold">]</span> <span style="color:#8f5902;font-style:italic"># Тензор со случайными данными</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">[</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">1804289383</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">846930886</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">1681692777</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">1714636915</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">1957747793</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">424238335</span><span style="color:#000;font-weight:bold">,],</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">]:</span><span style="color:#000">Int</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#000;font-weight:bold">[[</span> <span style="color:#0000cf;font-weight:bold">0..10</span> <span style="color:#000;font-weight:bold">]]:</span> <span style="color:#000">Int</span><span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">5</span><span style="color:#000;font-weight:bold">,</span><span style="color:#0000cf;font-weight:bold">2</span><span style="color:#000;font-weight:bold">]</span> <span style="color:#8f5902;font-style:italic"># Тензор из диапзона</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">[</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">2</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">3</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">4</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">5</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">6</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">7</span><span style="color:#000;font-weight:bold">,],</span> <span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">8</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">9</span><span style="color:#000;font-weight:bold">,],</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">]:</span><span style="color:#000">Int</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">&gt;</span><span style="color:#000;font-weight:bold">[[</span> <span style="color:#0000cf;font-weight:bold">0..0.99</span><span style="color:#ce5c00;font-weight:bold">.</span><span style="color:#0000cf;font-weight:bold">.0.1</span> <span style="color:#000;font-weight:bold">]]</span> <span style="color:#8f5902;font-style:italic"># Или даже так</span> -</span></span><span style="display:flex;"><span><span style="color:#000;font-weight:bold">[</span><span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0.1</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0.2</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0.3</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0.4</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0.5</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0.6</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0.7</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0.8</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#0000cf;font-weight:bold">0.9</span><span style="color:#000;font-weight:bold">,]:</span><span style="color:#000">Double</span><span style="color:#ce5c00;font-weight:bold">&lt;/</span><span style="color:#000">source</span><span style="color:#ce5c00;font-weight:bold">&gt;</span> -</span></span></code></pre></div><h2 id="операторы-и-управляющие-конструкции">Операторы и управляющие конструкции<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d0%b8-%d1%83%d0%bf%d1%80%d0%b0%d0%b2%d0%bb%d1%8f%d1%8e%d1%89%d0%b8%d0%b5-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h2> -<h4 id="операторы">Операторы:<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b" aria-label="Heading self-link"></a></h4> -<p>Все операторы имеют парный оператор с присвоением значения.</p> -<ul> -<li><strong>+</strong> и += сложение арифметических типов данных</li> -<li> -<ul> -<li>и -= вычитание арифметических типов данных</li> -</ul> -</li> -<li>/ и /= деление (результат число с плавающей точкой)</li> -<li>// и //= целочисленное деление с округлением к меньшему числу (как в Python)</li> -<li> -<ul> -<li>и *= умножение</li> -</ul> -</li> -<li>** и **= возведение в степень (он же используется и для повторения текстовых строк)</li> -<li>++ и ++= конкатенация строк с автоматическим приведением аргументов к стоковому типу (символ инкремента специально используется вместо одиночного плюса для того, чтобы в явном виде разделить конкатенацию строк и операторы арифметического сложения)</li> -</ul> -<h4 id="операторы-сравнения">Операторы сравнения:<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d1%81%d1%80%d0%b0%d0%b2%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h4> -<ul> -<li>&lt;, &gt;, &lt;=, &gt;= классические для сравнения скаляров</li> -<li>==, != операторы сравнения с автоматическим приведением совместимых типов для любых объектов</li> -<li>===, !== оператор точного сравнения для любых объектов (автоматического приведения типов не выполняется)s</li> -</ul> -<h3 id="проверки-типов--в-разработке">Проверки типов (в разработке):<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b8-%d1%82%d0%b8%d0%bf%d0%be%d0%b2--%d0%b2-%d1%80%d0%b0%d0%b7%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b5" aria-label="Heading self-link"></a></h3> -<p>Проверка имени класса «~» - немного похож на оператор instanceof в Java. -Левым оператором должен быть проверяемый объект, а правым оператором - название типа, строка литерал или объект строкового типа с именем класса. -Результатом операции будет истина, если правый операнд содержит название класса проверяемого объекта или он присутствует в иерархии наследования у проверяемого класса.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> name :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#4e9a06">&#34;class&#34;</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Строка с именем класса</span> -</span></span><span style="display:flex;"><span> var ~ :class<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> var ~ <span style="color:#4e9a06">&#34;class&#34;</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> var ~ name<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">field1</span><span style="color:#ce5c00;font-weight:bold">=</span>«value», <span style="color:#000">field2</span><span style="color:#ce5c00;font-weight:bold">=</span>2, <span style="color:#000">field3</span><span style="color:#ce5c00;font-weight:bold">=</span>«33»,<span style="color:#ce5c00;font-weight:bold">)</span> ~~ <span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Истина (т. е. левый операнд словарь)</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">field1</span><span style="color:#ce5c00;font-weight:bold">=</span>«value», <span style="color:#000">field2</span><span style="color:#ce5c00;font-weight:bold">=</span>2, <span style="color:#000">field3</span><span style="color:#ce5c00;font-weight:bold">=</span>«33»,<span style="color:#ce5c00;font-weight:bold">)</span> ~~ <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">field1</span><span style="color:#ce5c00;font-weight:bold">=</span>_<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Тоже истина (т. к. поле field1 присутствует у левого операнда)</span> -</span></span></code></pre></div><p>Утиная типизация «~~» - приблизительный аналог функции isinstance() в Python, который для простых типов сравнивает совместимость типа левого операнда по отношению к правому, а для словарей и классов в левом операнде проверяется наличие всех имен полей, присутствующих у правого операнда. т. е.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">field1</span><span style="color:#ce5c00;font-weight:bold">=</span>«value», <span style="color:#000">field2</span><span style="color:#ce5c00;font-weight:bold">=</span>2, <span style="color:#000">field3</span><span style="color:#ce5c00;font-weight:bold">=</span>«33»,<span style="color:#ce5c00;font-weight:bold">)</span> ~~ <span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Истина (т. е. левый операнд словарь)</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">field1</span><span style="color:#ce5c00;font-weight:bold">=</span>«value», <span style="color:#000">field2</span><span style="color:#ce5c00;font-weight:bold">=</span>2, <span style="color:#000">field3</span><span style="color:#ce5c00;font-weight:bold">=</span>«33»,<span style="color:#ce5c00;font-weight:bold">)</span> ~~ <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">field1</span><span style="color:#ce5c00;font-weight:bold">=</span>_<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Тоже истина (т. к. поле field1 присутствует у левого операнда)</span> -</span></span></code></pre></div><p>Строгая утиная типизация «~~~» - для простых типов сравнивается идентичности типов без учета совместимости, -а для составных типов происходит строгое сравнение всех свойств. Для данной операции, пустой тип совместим только с другим пустим типом!</p> -<h2 id="управляющие-конструкции-в-разработке">Управляющие конструкции (в разработке)<a class="td-heading-self-link" href="#%d1%83%d0%bf%d1%80%d0%b0%d0%b2%d0%bb%d1%8f%d1%8e%d1%89%d0%b8%d0%b5-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%86%d0%b8%d0%b8-%d0%b2-%d1%80%d0%b0%d0%b7%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b5" aria-label="Heading self-link"></a></h2> -<h3 id="условный-оператор">Условный оператор<a class="td-heading-self-link" href="#%d1%83%d1%81%d0%bb%d0%be%d0%b2%d0%bd%d1%8b%d0%b9-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80" aria-label="Heading self-link"></a></h3> -<p>В качестве оператора проверки условия используется синтаксическая конструкция, соответствующая по смыслу термину «следует», -т.е. тире и угловая скобка «-&gt;». Такая запись условного оператора очень похожа на математическую и легко объединяется в последовательности для проверки множественных условий вида «else if».</p> -<p>В общем случае условный оператор имеет вид:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> условие -&gt; действие<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> или -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span>условие<span style="color:#ce5c00;font-weight:bold">)</span> -&gt; <span style="color:#ce5c00;font-weight:bold">{</span>действие<span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> или -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span>условие1 <span style="color:#ce5c00;font-weight:bold">||</span> условие2<span style="color:#ce5c00;font-weight:bold">)</span> -&gt; <span style="color:#ce5c00;font-weight:bold">{</span>действие<span style="color:#ce5c00;font-weight:bold">}</span> -&gt; <span style="color:#ce5c00;font-weight:bold">{</span>действие иначе<span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>Или расширенный вариант «else if», для наглядности записанный с отступами:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span>условие1<span style="color:#ce5c00;font-weight:bold">)</span> -&gt; <span style="color:#ce5c00;font-weight:bold">{</span>действие1<span style="color:#ce5c00;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span>условие2<span style="color:#ce5c00;font-weight:bold">)</span> -&gt; <span style="color:#ce5c00;font-weight:bold">{</span>действие2<span style="color:#ce5c00;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span>условие3<span style="color:#ce5c00;font-weight:bold">)</span> -&gt; <span style="color:#ce5c00;font-weight:bold">{</span>действие3<span style="color:#ce5c00;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> -&gt; <span style="color:#ce5c00;font-weight:bold">{</span>действие_иначе<span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><h3 id="операторы-циклов-в-планах">Операторы циклов (в планах)<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d1%86%d0%b8%d0%ba%d0%bb%d0%be%d0%b2-%d0%b2-%d0%bf%d0%bb%d0%b0%d0%bd%d0%b0%d1%85" aria-label="Heading self-link"></a></h3> -<p><em>Операторы циклов пока в разработке , т. к. плотно связаны с итераторами.</em></p> -<p>Пока планирую для циклов использовать конструкции: (условие) <strong>&lt;&ndash;&gt;</strong> {тело цикла};</p> -<p>Или так: (условие) <strong>-&raquo;</strong> {тело цикла};</p> -<p>И хотя синтаксис мне не очень нравится, но я решил пока не ломать над этим голову и планирую попробовать несколько вариантов оформления циклов.</p> -<h4 id="операторы-прерывания-потока-выполнения-команд-реализовано-частично">Операторы прерывания потока выполнения команд (реализовано частично)<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d0%bf%d1%80%d0%b5%d1%80%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%bf%d0%be%d1%82%d0%be%d0%ba%d0%b0-%d0%b2%d1%8b%d0%bf%d0%be%d0%bb%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%ba%d0%be%d0%bc%d0%b0%d0%bd%d0%b4-%d1%80%d0%b5%d0%b0%d0%bb%d0%b8%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%be-%d1%87%d0%b0%d1%81%d1%82%d0%b8%d1%87%d0%bd%d0%be" aria-label="Heading self-link"></a></h4> -<p>Оператором прерывания потока выполнения команд и возврата из текущей функции, т.е. самым близким аналогом оператора return<br> -является оператор два символа минус «&ndash;». Но в отличие от классического return, оператор возврата не возвращает значения, -т.к. значение из любой функции или блока кода возвращается всегда и им является результат выполнения самой последней операции -(или None, если такая операция отсутствует).</p> -<p>Пока не придумал, как оформлять оператор прерывания потока выполнения в случае ошибки (при его выполнении будет происходить генерация исключения), -поэтому, если будут предложения, пишите в комментариях к статье (и про оформление циклов тоже).</p> -<h3 id="обработка-ошибок-в-планах">Обработка ошибок (в планах)<a class="td-heading-self-link" href="#%d0%be%d0%b1%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b0-%d0%be%d1%88%d0%b8%d0%b1%d0%be%d0%ba-%d0%b2-%d0%bf%d0%bb%d0%b0%d0%bd%d0%b0%d1%85" aria-label="Heading self-link"></a></h3> -<p>В самом начале работ я ориентировался на классический вариант обработки исключений, -который в обычных языках программирования обычно оформляется ключевыми словами <em>try</em> .. <em>catch</em> .. <em>finally</em> с различными вариациями. -Но в условиях жестких ограничений на синтаксис языка, и невозможности использовать ключевые слова, -комбинировать символы для указания разных типов блоков при обработке исключений, было бы крайне сомнительной затеей. -Ведь основная цель разработки NewLang — простота и понятность кода, а тут с самого начала могут появиться комбинации скобочек, стрелочек, -палочек и других подобных символов.</p> -<p>И тут в голову пришла очень простая мысль. А ненужно повторять логику обработки ошибок из классических языков программирования! -Ведь основная цель подобных синтаксических конструкций - выделить участок кода где возможно возникновение ошибки, -перехватить и обработать правильный тип исключения. -Ведь классические языки программирования изначально были жестко привязаны к машинному представлению данных в оперативной памяти компьютера -и тип данных для них играл принципиально важное значение. -Но это не является ограничением для языков с динамической типизацией!</p> -<p>Поэтому, подход к обработке исключений планируется следующий: Программный код, который может привести к ошибке, заключается в двойные фигурные скобки -<strong>{{</strong> <i>любой код или вызов одиночной функции</i> <strong>}}</strong>, -а результат выполнения такого блока кода присваивается переменной. После этого анализируется возвращенное значение и тип исключения может обрабатываться обычным условным оператором.</p> -<p>Наверно, это проще показать на примере:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#000">$error</span> :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">{{</span> <span style="color:#8f5902;font-style:italic"># начало блока try</span> -</span></span><span style="display:flex;"><span> call_or_exception1<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> call_or_exception2<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}}</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># конец блока try</span> -</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Обычные условные операторы вместо типизированных блоков catch</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">$error</span> ~ :type1<span style="color:#ce5c00;font-weight:bold">)</span>-&gt;<span style="color:#ce5c00;font-weight:bold">{</span> код обработки ошибки 1<span style="color:#ce5c00;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">$error</span> ~ :type2<span style="color:#ce5c00;font-weight:bold">)</span>-&gt;<span style="color:#ce5c00;font-weight:bold">{</span> код обработки ошибки 2<span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>Самое удивительное, что при таком подходе значительно упрощается и семантика блоков <em>try</em> <strong>…</strong> <em>finally</em>, которые вообще становятся не нужны.</p> -<p>Исходный код на Java:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">try</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">{</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">try</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">{</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">throw</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">new</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">Exception</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;a&#34;</span><span style="color:#000;font-weight:bold">);</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">}</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">finally</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">{</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">throw</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">new</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">IOException</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;b&#34;</span><span style="color:#000;font-weight:bold">);</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">}</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">}</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">catch</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">IOException</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">ex</span><span style="color:#000;font-weight:bold">)</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">{</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">System</span><span style="color:#000;font-weight:bold">.</span><span style="color:#c4a000">err</span><span style="color:#000;font-weight:bold">.</span><span style="color:#c4a000">println</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">ex</span><span style="color:#000;font-weight:bold">.</span><span style="color:#c4a000">getMessage</span><span style="color:#000;font-weight:bold">());</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">}</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">catch</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">Exception</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">ex</span><span style="color:#000;font-weight:bold">)</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">{</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">System</span><span style="color:#000;font-weight:bold">.</span><span style="color:#c4a000">err</span><span style="color:#000;font-weight:bold">.</span><span style="color:#c4a000">println</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">ex</span><span style="color:#000;font-weight:bold">.</span><span style="color:#c4a000">getMessage</span><span style="color:#000;font-weight:bold">());</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span><span style="display:flex;"><span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000;font-weight:bold">}</span><span style="color:#f8f8f8;text-decoration:underline"> -</span></span></span></code></pre></div><p>Эквивалентный ему на NewLang:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#000">$catch</span> :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">{{</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$finally</span> :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">{{</span> -</span></span><span style="display:flex;"><span> Error1<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;1&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}}</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Error2<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;2&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Строка выполнится даже при возникновении исключении Error1</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">$finally</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Error1 вернется, если не будет Error2</span> -</span></span><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">}}</span> -</span></span><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">$catch</span> ~ :Error1<span style="color:#ce5c00;font-weight:bold">)</span> -&gt; printf<span style="color:#ce5c00;font-weight:bold">(</span>«%s», <span style="color:#000">$catch</span><span style="color:#ce5c00;font-weight:bold">)</span> -</span></span><span style="display:flex;"><span><span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">$catch</span> ~ :Error2<span style="color:#ce5c00;font-weight:bold">)</span> -&gt; printf<span style="color:#ce5c00;font-weight:bold">(</span>«%s», <span style="color:#000">$catch</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><h2 id="как-все-это-попробовать">Как все это попробовать?<a class="td-heading-self-link" href="#%d0%ba%d0%b0%d0%ba-%d0%b2%d1%81%d0%b5-%d1%8d%d1%82%d0%be-%d0%bf%d0%be%d0%bf%d1%80%d0%be%d0%b1%d0%be%d0%b2%d0%b0%d1%82%d1%8c" aria-label="Heading self-link"></a></h2> -<p>Сейчас сборка проекта реализована только под Linux и если кроме текстового описания захочется в живую поэкспериментировать на своей машине, то придется собрать интерпретатор из исходников самостоятельно.</p> -<p>Так как текущий вариант предназначен первую очередь для отработки концепции, то часть из описанных возможностей пока не реализована (алгоритмические конструкции, наследование классов, итераторы, некоторые операции и т. д).</p> -<p>Но можно поиграться с созданием переменных, вызовом функций и выполнением арифметических операций над данными, чтобы оценить синтаксис, основанный на правилах, и может быть, предложить свои собственные мысли и доработки для его улучшения.</p> -<h3 id="сборка-repl-из-исходников-пока-только-под-linux">Сборка REPL из исходников (пока только под Linux)<a class="td-heading-self-link" href="#%d1%81%d0%b1%d0%be%d1%80%d0%ba%d0%b0-repl-%d0%b8%d0%b7-%d0%b8%d1%81%d1%85%d0%be%d0%b4%d0%bd%d0%b8%d0%ba%d0%be%d0%b2-%d0%bf%d0%be%d0%ba%d0%b0-%d1%82%d0%be%d0%bb%d1%8c%d0%ba%d0%be-%d0%bf%d0%be%d0%b4-linux" aria-label="Heading self-link"></a></h3> -<h4 id="подготовка-репозитория">Подготовка репозитория<a class="td-heading-self-link" href="#%d0%bf%d0%be%d0%b4%d0%b3%d0%be%d1%82%d0%be%d0%b2%d0%ba%d0%b0-%d1%80%d0%b5%d0%bf%d0%be%d0%b7%d0%b8%d1%82%d0%be%d1%80%d0%b8%d1%8f" aria-label="Heading self-link"></a></h4> -<ul> -<li>Скачать <a href="https://github.com/rsashka/newlang">исходники</a></li> -<li>Скачать и развернуть архив libtorch в каталоге contrib (PyTorch Build: Stable (1.10.*) -&gt; Your OS: Linux -&gt; Package: LibTorch -&gt; Language: C++ / Java -&gt; Compute Platform: CPU -&gt; Download here (cxx11 ABI): libtorch-cxx11-abi-shared-with-deps-1.10.2+cpu.zip)</li> -<li>Активировать и скачать исходники субмодулей (git submodule init &amp;&amp; git submodule update)</li> -<li>В каталоге <em>contrib</em> запустить файл <em>build.sh</em> для сборки библиотеки libffi</li> -<li>В каталоге <em>core</em> запустить файл <em>compile_syntax.sh</em> для генерации файлов парсера и лексического анализатора. Может потребоваться установка утилит flex и bison. Если что, у меня установлены flex 2.6.4 и bison (GNU Bison) 3.7.4</li> -</ul> -<h4 id="собрать">Собрать<a class="td-heading-self-link" href="#%d1%81%d0%be%d0%b1%d1%80%d0%b0%d1%82%d1%8c" aria-label="Heading self-link"></a></h4> -<ul> -<li>Юнит-тесты (newlang_test): в каталоге core выполнить команду <em>make CONF=UnitTest</em></li> -<li>Интерпретатор (nlc): в каталоге core выполнить команду <em>make CONF=Debug</em></li> -</ul> -<h2 id="утилита-nlc-newlangcompiler">Утилита nlc (NewLangCompiler)<a class="td-heading-self-link" href="#%d1%83%d1%82%d0%b8%d0%bb%d0%b8%d1%82%d0%b0-nlc-newlangcompiler" aria-label="Heading self-link"></a></h2> -<p>В текущее время nlc поддерживать работу только в режиме интерпретатора (несмотря на название). -Для тестирования и простой проверки компилятор не нужен, хотя на первых порах я делал именно его. -Но трудоемкость работ по постоянной переделке под новый синтаксис оказалась очень высокой, поэтому на время первичной отладки языковых конструкций было принято волевое решение ограничиться интерпретатором, -как более простым и быстрым способом проверки различных гипотез, а разработку настоящего компилятора (в виде трансплайтера на язык С++), -отложить до окончательной проработки синтаксиса.</p> -<h2 id="планы-на-будущее">Планы на будущее<a class="td-heading-self-link" href="#%d0%bf%d0%bb%d0%b0%d0%bd%d1%8b-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5" aria-label="Heading self-link"></a></h2> -<p>Естественное, одна статья и несколько маленьких примеров не дают исчерпывающей информации о возможностях языка. -Да и сами возможности пока не раскрыты в полной мере. -Ведь текущая версия, это скорее тестовая платформа для проверки декларируемых концепций и основного синтаксиса.</p> -<p>Пока остаются не реализованными некоторые из заявленных возможностей и очень важных хотелок. -Но протестировать основной подход можно уже сейчас, и я буду благодарен за любую обратную связь и предложения.</p> -<p>Если говорить о планах (естественно, в будущих версиях что-то может добавиться или измениться порядок их реализации), но в настоящий момент роадмап развития NewLang мне видится следующим образом:</p> -<ul> -<li>Доделать стандартные управляющие конструкции, обработку ошибок и итераторы.</li> -<li>Доработать систему типов с учетом множественного наследования классов.</li> -<li>Реализовать длинную арифметику и дроби.</li> -<li>Сделать какую нибудь логическую игру (крестики нолики, судоку или что-то похожее) с алгоритмическим выбором следующего хода и его вычислением с помощью машинного обучения.</li> -<li>Написать много разных примеров для оценки синтаксиса.</li> -<li>Доработать синтаксис с учетом полученного опыта и обратной связи.</li> -<li>Восстановить работоспособность компилятора для генерации исполняемых файлов.</li> -<li>Сделать очередную большую чистку кода.</li> -<li>Переработать и задокументировать получившуюся семантику языка с учетом всех возможностей и выпустить первую полнофункциональную версию NewLang.</li> -</ul> -<p><a href="https://habr.com/companies/timeweb/articles/651999/">Ссылка на первую публикаци</a></p> - - <ul class="list-unstyled d-flex justify-content-between align-items-center mb-0 pt-5"> - <li> - <a href="/blog/prog-styles-same-time/" aria-label="Previous - Можно ли использовать декларативный и императивный стили написания программ одновременно?" class="btn btn-primary"><span class="me-1">←</span>Previous</a> - </li> - <li> - <a href="/blog/release-v0.1/" aria-label="Next - Релиз языка программрования NewLang" class="btn btn-primary">Next<span class="ms-1">→</span></a> - </li> -</ul> - - </div> - - - </main> - </div> - </div> - <footer class="td-footer row d-print-none"> - <div class="container-fluid"> - <div class="row mx-md-2"> - <div class="td-footer__left col-6 col-sm-4 order-sm-1"> - <ul class="td-footer__links-list"> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="User mailing list" aria-label="User mailing list"> - <a target="_blank" rel="noopener" href="mailto:mail@newlang.net" aria-label="User mailing list"> - <i class="fa fa-envelope"></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - -</ul> - - </div><div class="td-footer__right col-6 col-sm-4 order-sm-3"> - <ul class="td-footer__links-list"> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="GitHub" aria-label="GitHub"> - <a target="_blank" rel="noopener" href="https://github.com/rsashka/newlang" aria-label="GitHub"> - <i class="fab fa-github"></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - -</ul> - - </div><div class="td-footer__center col-12 col-sm-4 py-2 order-sm-2"> - <span class="td-footer__copyright">&copy; - 2024 - <span class="td-footer__authors">The NewLang Authors</span></span><span class="td-footer__all_rights_reserved">All Rights Reserved</span> - </div> - </div> - </div> -</footer> - - </div> - <script src="/js/main.js"></script> -<script defer src="/js/click-to-copy.js" crossorigin="anonymous"></script> -<script src='/js/tabpane-persist.js'></script> - - </body> -</html> \ No newline at end of file diff --git a/docs/blog/page/2/index.html b/docs/blog/page/2/index.html deleted file mode 100644 index e30d3b00..00000000 --- a/docs/blog/page/2/index.html +++ /dev/null @@ -1,342 +0,0 @@ -<!doctype html> -<html itemscope itemtype="http://schema.org/WebPage" lang="en" class="no-js"> - <head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script> - <meta charset="utf-8"> -<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> -<link rel="alternate" type="text/html" href="http://localhost:1313/blog/_print/"> -<link rel="alternate" type="application/rss&#43;xml" href="http://localhost:1313/blog/index.xml"> -<meta name="robots" content="noindex, nofollow"> - - -<link rel="shortcut icon" href="/favicons/favicon.ico" > -<link rel="apple-touch-icon" href="/favicons/apple-touch-icon-180x180.png" sizes="180x180"> -<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16"> -<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32"> -<link rel="icon" type="image/png" href="/favicons/android-36x36.png" sizes="36x36"> -<link rel="icon" type="image/png" href="/favicons/android-48x48.png" sizes="48x48"> -<link rel="icon" type="image/png" href="/favicons/android-72x72.png" sizes="72x72"> -<link rel="icon" type="image/png" href="/favicons/android-96x96.png" sizes="96x96"> -<link rel="icon" type="image/png" href="/favicons/android-144x144.png" sizes="144x144"> -<link rel="icon" type="image/png" href="/favicons/android-192x192.png" sizes="192x192"> - -<title>Articles | NewLang</title> -<meta name="description" content="NewLang site"> -<meta property="og:title" content="Articles" /> -<meta property="og:description" content="NewLang site" /> -<meta property="og:type" content="website" /> -<meta property="og:url" content="http://localhost:1313/blog/" /><meta property="og:site_name" content="NewLang" /> -<meta itemprop="name" content="Articles"> -<meta itemprop="description" content="NewLang site"><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Articles"/> -<meta name="twitter:description" content="NewLang site"/> - - - - - -<link href="/scss/main.css" rel="stylesheet"> - -<script - src="https://code.jquery.com/jquery-3.6.3.min.js" - integrity="sha512-STof4xm1wgkfm7heWqFJVn58Hm3EtS31XFaagaa8VMReCXAkQnJZ+jEy8PCC/iT18dFy95WcExNHFTqLyp72eQ==" - crossorigin="anonymous"></script> -<script defer - src="https://unpkg.com/lunr@2.3.9/lunr.min.js" - integrity="sha384-203J0SNzyqHby3iU6hzvzltrWi/M41wOP5Gu+BiJMz5nwKykbkUx8Kp7iti0Lpli" - crossorigin="anonymous"></script> - - </head> - <body class="td-section td-blog"> - <header> - <nav class="td-navbar navbar-dark js-navbar-scroll"> -<div class="container-fluid flex-column flex-md-row"> - <a class="navbar-brand" href="/"><span class="navbar-brand__logo navbar-logo"><svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500" style="enable-background:new 0 0 500 500"><g><path style="fill:#fff" d="M116.8525 421.9722c-5.7041.0-10.3442-4.3127-10.3442-9.6129V88.183c0-5.3002 4.6401-9.6117 10.3442-9.6117H320.858c3.0347.0 9.3959.5498 11.7506 2.6302l.3545.3442 58.905 63.2912c2.3101 2.491 2.9202 8.4928 2.9202 11.3184v256.2039c0 5.3002-4.6407 9.6129-10.3436 9.6129H116.8525z"/><g><g><g><path style="fill:#767676" d="M384.4445 423.2066H116.852c-6.3839.0-11.5786-4.8658-11.5786-10.8474V88.1831c0-5.9804 5.1947-10.8461 11.5786-10.8461h204.0062c.377.0 9.2786.0329 12.568 2.9389l.3947.3833 58.9508 63.337c3.2135 3.4652 3.2514 11.7924 3.2514 12.1593v256.2036C396.0231 418.3408 390.8284 423.2066 384.4445 423.2066zM116.5079 411.9189c.0848.0278.1999.0531.3441.0531h267.5925c.1442.0.2581-.0253.3441-.0531V156.1556c-.0076-.9033-.3593-3.7347-.7034-5.0037l-57.6527-61.9416c-1.4651-.3176-4.4533-.6389-5.5742-.6389H116.852c-.143.0-.2594.024-.3441.0531V411.9189zm267.4533-261.149zM327.0321 89.371v.0013V89.371z"/></g></g></g><g><g><path style="fill:#5b7fc0" d="M189.0874 210.1754l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.025 2.454-11.4897 6.4116-15.4473C177.5953 212.627 183.0601 210.1742 189.0874 210.1754zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403S197.0816 234.1722 197.0804 232.033z"/><path style="opacity:.3;fill:#fff" d="M189.0898 210.176c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 212.6276 183.0612 210.176 189.0898 210.176zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 236.239 197.0839 234.2399 197.0839 232.0372z"/><g><defs><path id="SVGID_1_" d="M194.7376 237.6875c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.999 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 234.2399 196.1861 236.239 194.7376 237.6875z"/></defs><clipPath id="SVGID_2_"><use xlink:href="#SVGID_1_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_2_);fill:#fff" d="M190.0704 225.0237c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 225.7247 191.9774 225.0237 190.0704 225.0237z"/><path style="opacity:.13;clip-path:url(#SVGID_2_);fill:#020202" d="M190.0704 225.0237c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 225.7247 191.9774 225.0237 190.0704 225.0237z"/></g><g><defs><path id="SVGID_3_" d="M189.0898 210.176c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 212.6276 183.0612 210.176 189.0898 210.176zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 236.239 197.0839 234.2399 197.0839 232.0372z"/></defs><clipPath id="SVGID_4_"><use xlink:href="#SVGID_3_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_4_);fill:#5b7fc0" d="M172.6595 215.6045c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8612 12.0547.0024 21.8636-9.797 21.8613-21.8612.0024-3.8475-1.0151-7.6326-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 209.1953 176.6171 211.647 172.6595 215.6045z"/></g></g><rect x="198.8952" y="225.1043" style="fill:#5b7fc0" width="122.6266" height="13.8671"/></g><g><path style="fill:#d95140" d="M189.0874 155.7611l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.0249 2.454-11.4897 6.4116-15.4473C177.5953 158.2128 183.0601 155.7599 189.0874 155.7611zm7.993 21.8577c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403C196.2508 181.7667 197.0816 179.758 197.0804 177.6188z"/><path style="opacity:.3;fill:#fff" d="M189.0898 155.7617c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 158.2134 183.0612 155.7617 189.0898 155.7617zm7.9941 21.8613c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 181.8248 197.0839 179.8256 197.0839 177.623z"/><g><defs><path id="SVGID_5_" d="M194.7376 183.2733c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.9989 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 179.8256 196.1861 181.8248 194.7376 183.2733z"/></defs><clipPath id="SVGID_6_"><use xlink:href="#SVGID_5_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_6_);fill:#fff" d="M190.0704 170.6095c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 171.3104 191.9774 170.6095 190.0704 170.6095z"/><path style="opacity:.13;clip-path:url(#SVGID_6_);fill:#020202" d="M190.0704 170.6095c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 171.3104 191.9774 170.6095 190.0704 170.6095z"/></g><g><defs><path id="SVGID_7_" d="M189.0898 155.7617c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 158.2134 183.0612 155.7617 189.0898 155.7617zm7.9941 21.8613c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 181.8248 197.0839 179.8256 197.0839 177.623z"/></defs><clipPath id="SVGID_8_"><use xlink:href="#SVGID_7_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_8_);fill:#d95140" d="M172.6595 161.1903c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8613 12.0547.0024 21.8636-9.797 21.8613-21.8613.0024-3.8474-1.0151-7.6326-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 154.7811 176.6171 157.2327 172.6595 161.1903z"/></g><rect x="198.8952" y="170.69" style="fill:#d95140" width="122.6266" height="13.8671"/></g><g><g><path style="fill:#56a55c" d="M189.5379 264.6147l.0012-.0012c7.7751.0012 15.0294 4.1862 18.932 10.9235 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032-5.8394.0-11.3281-2.2733-15.458-6.4032-4.13-4.13-6.4032-9.6186-6.4056-15.4628.0012-6.0249 2.454-11.4897 6.4116-15.4472C178.0458 267.0663 183.5105 264.6135 189.5379 264.6147zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6538 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403C196.7013 290.6202 197.5321 288.6115 197.5309 286.4723z"/><path style="opacity:.3;fill:#fff" d="M189.5403 264.6153c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8065-21.8612-21.8613.0-6.0285 2.4516-11.492 6.4116-15.452C178.0482 267.0669 183.5117 264.6153 189.5403 264.6153zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.6366 290.6783 197.5344 288.6792 197.5344 286.4765z"/><g><defs><path id="SVGID_9_" d="M195.1881 292.1268c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.9989 7.9942-7.9941 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.5344 288.6792 196.6366 290.6783 195.1881 292.1268z"/></defs><clipPath id="SVGID_10_"><use xlink:href="#SVGID_9_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_10_);fill:#fff" d="M190.5209 279.463c-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7446-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9941 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C194.239 280.164 192.4279 279.463 190.5209 279.463z"/><path style="opacity:.13;clip-path:url(#SVGID_10_);fill:#020202" d="M190.5209 279.463c-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7446-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9941 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C194.239 280.164 192.4279 279.463 190.5209 279.463z"/></g><g><defs><path id="SVGID_11_" d="M189.5403 264.6153c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8065-21.8612-21.8613.0-6.0285 2.4516-11.492 6.4116-15.452C178.0482 267.0669 183.5117 264.6153 189.5403 264.6153zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.6366 290.6783 197.5344 288.6792 197.5344 286.4765z"/></defs><clipPath id="SVGID_12_"><use xlink:href="#SVGID_11_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_12_);fill:#56a55c" d="M173.11 270.0439c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8613 12.0547.0024 21.8636-9.797 21.8613-21.8613.0024-3.8474-1.0151-7.6326-2.9353-10.9462-3.8977-6.7325-11.1497-10.9151-18.926-10.9151C182.5311 263.6346 177.0676 266.0863 173.11 270.0439z"/></g></g><rect x="199.3456" y="279.5436" style="fill:#56a55c" width="122.6266" height="13.8671"/></g><g><g><path style="fill:#f1bc42" d="M189.0874 318.7208l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3305-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.025 2.454-11.4897 6.4116-15.4472C177.5953 321.1724 183.0601 318.7196 189.0874 318.7208zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403S197.0816 342.7176 197.0804 340.5784z"/><path style="opacity:.3;fill:#fff" d="M189.0898 318.7214c7.7763.0 15.0283 4.1826 18.926 10.915 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8612-12.0547.0024-21.8636-9.8065-21.8612-21.8612.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 321.173 183.0612 318.7214 189.0898 318.7214zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 344.7844 197.0839 342.7853 197.0839 340.5826z"/><g><defs><path id="SVGID_13_" d="M194.7376 346.2329c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.999 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 342.7853 196.1861 344.7844 194.7376 346.2329z"/></defs><clipPath id="SVGID_14_"><use xlink:href="#SVGID_13_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_14_);fill:#fff" d="M190.0704 333.5691c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0834 6.1218 2.8788C193.7885 334.2701 191.9774 333.5691 190.0704 333.5691z"/><path style="opacity:.13;clip-path:url(#SVGID_14_);fill:#020202" d="M190.0704 333.5691c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0834 6.1218 2.8788C193.7885 334.2701 191.9774 333.5691 190.0704 333.5691z"/></g><g><defs><path id="SVGID_15_" d="M189.0898 318.7214c7.7763.0 15.0283 4.1826 18.926 10.915 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8612-12.0547.0024-21.8636-9.8065-21.8612-21.8612.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 321.173 183.0612 318.7214 189.0898 318.7214zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 344.7844 197.0839 342.7853 197.0839 340.5826z"/></defs><clipPath id="SVGID_16_"><use xlink:href="#SVGID_15_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_16_);fill:#f1bc42" d="M172.6595 324.15c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8612 12.0547.0024 21.8636-9.797 21.8613-21.8612.0024-3.8474-1.0151-7.6327-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 317.7407 176.6171 320.1924 172.6595 324.15z"/></g></g><rect x="198.8952" y="333.6497" style="fill:#f1bc42" width="122.6266" height="13.8671"/></g></g></svg></span><span class="navbar-brand__name">NewLang</span></a> - <div class="td-navbar-nav-scroll ms-md-auto" id="main_navbar"> - <ul class="navbar-nav"> - <li class="nav-item"> - <a class="nav-link" href="/docs/"><span>Documentation</span></a> - </li> - <li class="nav-item"> - <a class="nav-link" href="/playground/"><span>Playground</span></a> - </li> - <li class="nav-item"> - <a class="nav-link active" href="/blog/"><span>Articles</span></a> - </li> - <li class="nav-item dropdown d-none d-lg-block"> - <div class="dropdown"> - <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">English</a> - <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/ru/blog/">Русский</a></li> - </ul> -</div></li> - </ul> - </div> - <div class="d-none d-lg-block"> - <div class="td-search td-search--offline"> - <div class="td-search__icon"></div> - <input - type="search" - class="td-search__input form-control" - placeholder="Search this site…" - aria-label="Search this site…" - autocomplete="off" - - data-offline-search-index-json-src="/offline-search-index.json" - data-offline-search-base-href="/" - data-offline-search-max-results="10" - > -</div> - </div> -</div> -</nav> - </header> - <div class="container-fluid td-outer"> - <div class="td-main"> - <div class="row flex-xl-nowrap"> - <aside class="col-12 col-md-3 col-xl-2 td-sidebar d-print-none"> - <div id="td-sidebar-menu" class="td-sidebar__inner"> - <form class="td-sidebar__search d-flex align-items-center"> - <div class="td-search td-search--offline"> - <div class="td-search__icon"></div> - <input - type="search" - class="td-search__input form-control" - placeholder="Search this site…" - aria-label="Search this site…" - autocomplete="off" - - data-offline-search-index-json-src="/offline-search-index.json" - data-offline-search-base-href="/" - data-offline-search-max-results="10" - > -</div> - <button class="btn btn-link td-sidebar__toggle d-md-none p-0 ms-3 fas fa-bars" type="button" data-bs-toggle="collapse" data-bs-target="#td-section-nav" aria-controls="td-section-nav" aria-expanded="false" aria-label="Toggle section navigation"> - </button> - </form> - <nav class="td-sidebar-nav collapse" id="td-section-nav"> - <div class="td-sidebar-nav__section nav-item dropdown d-block d-lg-none"> - <div class="dropdown"> - <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">English</a> - <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/ru/blog/">Русский</a></li> - </ul> -</div> - </div> - <ul class="td-sidebar-nav__section pe-md-3 ul-0"> - <li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child active-path" id="m-blog-li"> - <a href="/blog/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__section tree-root" id="m-blog"><span class="td-sidebar-nav-active-item">Articles</span></a> - <ul class="ul-1"> - <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v04-li"> - <a href="/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogparser-nuances-li"> - <a href="/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogdsl-domain-specific-language-implementation-with-macros-li"> - <a href="/blog/dsl-domain-specific-language-implementation-with-macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogdsl-domain-specific-language-implementation-with-macros"><span class="">DSL (domain-specific language) implementation with macros</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v03-li"> - <a href="/blog/release-v0.3/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v03"><span class="">Релиз языка программрования NewLang 0.3</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v02-li"> - <a href="/blog/release-v0.2/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v02"><span class="">Релиз языка программрования NewLang 0.2</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v01-li"> - <a href="/blog/release-v0.1/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v01"><span class="">Релиз языка программрования NewLang</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blognewlang-li"> - <a href="/blog/newlang/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blognewlang"><span class="">Новый язык программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogprog-styles-same-time-li"> - <a href="/blog/prog-styles-same-time/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogprog-styles-same-time"><span class="">Можно ли использовать декларативный и императивный стили написания программ одновременно?</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogunusual-prog-li"> - <a href="/blog/unusual-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogunusual-prog"><span class="">Необычная концепция синтаксиса языка программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogcomplex-prog-li"> - <a href="/blog/complex-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogcomplex-prog"><span class="">Простое сложное программирование</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloglang-final-li"> - <a href="/blog/lang-final/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloglang-final"><span class="">Какая «идеальная» цель развития у языков программирования?</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloglogic-prog-li"> - <a href="/blog/logic-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloglogic-prog"><span class="">Проблема логических языков программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloginter-prog-li"> - <a href="/blog/inter-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloginter-prog"><span class="">Интернациональное программирование на естественных языках</span></a> -</li> - </ul> -</li> - </ul> - </nav> -</div> - - </aside> - <aside class="d-none d-xl-block col-xl-2 td-sidebar-toc d-print-none"> - <div class="td-page-meta ms-2 pb-1 pt-2 mb-0"> -<a id="print" href="/blog/_print/"><i class="fa-solid fa-print fa-fw"></i> Print entire section</a> - -</div> - - - <div class="taxonomy taxonomy-terms-cloud taxo-tags"> - <h5 class="taxonomy-title">Tag Cloud</h5> - <ul class="taxonomy-terms"> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B/" data-taxonomy-term="%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B"><span class="taxonomy-label">Итераторы</span><span class="taxonomy-count">1</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8/" data-taxonomy-term="%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8"><span class="taxonomy-label">Коллекции</span><span class="taxonomy-count">4</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%BE%D0%BE%D0%BF/" data-taxonomy-term="%D0%BE%D0%BE%D0%BF"><span class="taxonomy-label">ООП</span><span class="taxonomy-count">3</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B/" data-taxonomy-term="%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B"><span class="taxonomy-label">Системые Типы</span><span class="taxonomy-count">1</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85/" data-taxonomy-term="%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85"><span class="taxonomy-label">Типы Данных</span><span class="taxonomy-count">8</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8/" data-taxonomy-term="%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8"><span class="taxonomy-label">Функции</span><span class="taxonomy-count">1</span></a></li> - </ul> - </div> - - - </aside> - <main class="col-12 col-md-9 col-xl-8 ps-md-5 pe-md-4" role="main"> - <a class="td-rss-button" title="RSS" href="/blog/index.xml" target="_blank" rel="noopener"> - <i class="fa-solid fa-rss" aria-hidden="true"></i> - </a> - -<div class="td-blog-posts"> - <div class="h2">Posts in 2021</div> - <ul class="td-blog-posts-list"> - <li class="td-blog-posts-list__item"> - <div class="td-blog-posts-list__body"> - <h5 class="mt-0 mb-1"><a href="/blog/lang-final/">Какая «идеальная» цель развития у языков программирования?</a></h5> - <p class="mb-2 mb-md-3"><small class="text-muted">Wednesday, April 07, 2021 in Articles</small></p> - <header class="article-meta"> - - </header> - - - - - -<p class="pt-0 mt-0"> -С постоянной периодичностью появляется информация о выходе новой версии того или иного языка программирования. И с каждой новой версией расширяются его возможности, добавляются новые синтаксические конструкции или иные улучшения. -И это очень сильно …</p> - <p class="pt-0"><a href="/blog/lang-final/" aria-label="Read more - Какая «идеальная» цель развития у языков программирования?">Read more</a></p> - </div> - </li> - <li class="td-blog-posts-list__item"> - <div class="td-blog-posts-list__body"> - <h5 class="mt-0 mb-1"><a href="/blog/logic-prog/">Проблема логических языков программирования</a></h5> - <p class="mb-2 mb-md-3"><small class="text-muted">Saturday, January 09, 2021 in Articles</small></p> - <header class="article-meta"> - - </header> - - - - - -<p class="pt-0 mt-0"> -Некоторое время назад я писал про «Интернациональное программирование на естественных языках», в которой попытался представить достойную цель для абстрактного языка программирования, попробовав примерить на него роль связующего звена между миром …</p> - <p class="pt-0"><a href="/blog/logic-prog/" aria-label="Read more - Проблема логических языков программирования">Read more</a></p> - </div> - </li> - </ul> - <div class="h2">Posts in 2020</div> - <ul class="td-blog-posts-list"> - <li class="td-blog-posts-list__item"> - <div class="td-blog-posts-list__body"> - <h5 class="mt-0 mb-1"><a href="/blog/inter-prog/">Интернациональное программирование на естественных языках</a></h5> - <p class="mb-2 mb-md-3"><small class="text-muted">Saturday, December 05, 2020 in Articles</small></p> - <header class="article-meta"> - - </header> - - - - - -<p class="pt-0 mt-0"> -Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -В последнее время часто попадаются на глаза статьи о новых языках программирования, а так же различные …</p> - <p class="pt-0"><a href="/blog/inter-prog/" aria-label="Read more - Интернациональное программирование на естественных языках">Read more</a></p> - </div> - </li> - </ul> - -</div> -<div class="td-blog-posts__pagination"> - - <ul class="pagination pagination-default"> - <li class="page-item"> - <a href="/blog/" aria-label="First" class="page-link" role="button"><span aria-hidden="true">&laquo;&laquo;</span></a> - </li> - <li class="page-item"> - <a href="/blog/" aria-label="Previous" class="page-link" role="button"><span aria-hidden="true">&laquo;</span></a> - </li> - <li class="page-item"> - <a href="/blog/" aria-label="Page 1" class="page-link" role="button">1</a> - </li> - <li class="page-item active"> - <a aria-current="page" aria-label="Page 2" class="page-link" role="button">2</a> - </li> - <li class="page-item disabled"> - <a aria-disabled="true" aria-label="Next" class="page-link" role="button" tabindex="-1"><span aria-hidden="true">&raquo;</span></a> - </li> - <li class="page-item disabled"> - <a aria-disabled="true" aria-label="Last" class="page-link" role="button" tabindex="-1"><span aria-hidden="true">&raquo;&raquo;</span></a> - </li> - </ul></div> - - </main> - </div> - </div> - <footer class="td-footer row d-print-none"> - <div class="container-fluid"> - <div class="row mx-md-2"> - <div class="td-footer__left col-6 col-sm-4 order-sm-1"> - <ul class="td-footer__links-list"> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="User mailing list" aria-label="User mailing list"> - <a target="_blank" rel="noopener" href="mailto:mail@newlang.net" aria-label="User mailing list"> - <i class="fa fa-envelope"></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - -</ul> - - </div><div class="td-footer__right col-6 col-sm-4 order-sm-3"> - <ul class="td-footer__links-list"> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="GitHub" aria-label="GitHub"> - <a target="_blank" rel="noopener" href="https://github.com/rsashka/newlang" aria-label="GitHub"> - <i class="fab fa-github"></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - -</ul> - - </div><div class="td-footer__center col-12 col-sm-4 py-2 order-sm-2"> - <span class="td-footer__copyright">&copy; - 2024 - <span class="td-footer__authors">The NewLang Authors</span></span><span class="td-footer__all_rights_reserved">All Rights Reserved</span> - </div> - </div> - </div> -</footer> - - </div> - <script src="/js/main.js"></script> -<script defer src="/js/click-to-copy.js" crossorigin="anonymous"></script> -<script src='/js/tabpane-persist.js'></script> - - </body> -</html> \ No newline at end of file diff --git a/docs/blog/parser-nuances/index.html b/docs/blog/parser-nuances/index.html deleted file mode 100644 index c6723793..00000000 --- a/docs/blog/parser-nuances/index.html +++ /dev/null @@ -1,391 +0,0 @@ -<!doctype html> -<html itemscope itemtype="http://schema.org/WebPage" lang="en" class="no-js"> - <head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script> - <meta charset="utf-8"> -<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> -<meta name="robots" content="noindex, nofollow"> - - -<link rel="shortcut icon" href="/favicons/favicon.ico" > -<link rel="apple-touch-icon" href="/favicons/apple-touch-icon-180x180.png" sizes="180x180"> -<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16"> -<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32"> -<link rel="icon" type="image/png" href="/favicons/android-36x36.png" sizes="36x36"> -<link rel="icon" type="image/png" href="/favicons/android-48x48.png" sizes="48x48"> -<link rel="icon" type="image/png" href="/favicons/android-72x72.png" sizes="72x72"> -<link rel="icon" type="image/png" href="/favicons/android-96x96.png" sizes="96x96"> -<link rel="icon" type="image/png" href="/favicons/android-144x144.png" sizes="144x144"> -<link rel="icon" type="image/png" href="/favicons/android-192x192.png" sizes="192x192"> - -<title>Нюансы разработки парсера для своего языка программирования | NewLang</title> -<meta name="description" content="Недавно прочитал на Хабре статью Свой язык, или как я устал от ассемблера и С, и невольно взглядом зацепился за один абзац: -Я решил не сильно париться, поэтому использовал библиотеку parglare. Она очень легкая и удобная, всем рекомендую. Для описания синтаксиса парсер принимает строку в соответствующем формате, использует регулярные выражения (не надо осуждать регулярки, они всесильны!). -В результате решил опубликовать статью на основе своих старых записей еще с тех времен, когда идея NewLang до конца еще не выкристаллизовалась, но уже хотелось писать реальный код и тестировать разные концепции."> -<meta property="og:title" content="Нюансы разработки парсера для своего языка программирования" /> -<meta property="og:description" content="Недавно прочитал на Хабре статью Свой язык, или как я устал от ассемблера и С, и невольно взглядом зацепился за один абзац: -Я решил не сильно париться, поэтому использовал библиотеку parglare. Она очень легкая и удобная, всем рекомендую. Для описания синтаксиса парсер принимает строку в соответствующем формате, использует регулярные выражения (не надо осуждать регулярки, они всесильны!). -В результате решил опубликовать статью на основе своих старых записей еще с тех времен, когда идея NewLang до конца еще не выкристаллизовалась, но уже хотелось писать реальный код и тестировать разные концепции." /> -<meta property="og:type" content="article" /> -<meta property="og:url" content="http://localhost:1313/blog/parser-nuances/" /><meta property="article:section" content="blog" /> -<meta property="article:published_time" content="2023-03-29T00:00:00+00:00" /> -<meta property="article:modified_time" content="2024-03-22T23:57:08+03:00" /><meta property="og:site_name" content="NewLang" /> -<meta itemprop="name" content="Нюансы разработки парсера для своего языка программирования"> -<meta itemprop="description" content="Недавно прочитал на Хабре статью Свой язык, или как я устал от ассемблера и С, и невольно взглядом зацепился за один абзац: -Я решил не сильно париться, поэтому использовал библиотеку parglare. Она очень легкая и удобная, всем рекомендую. Для описания синтаксиса парсер принимает строку в соответствующем формате, использует регулярные выражения (не надо осуждать регулярки, они всесильны!). -В результате решил опубликовать статью на основе своих старых записей еще с тех времен, когда идея NewLang до конца еще не выкристаллизовалась, но уже хотелось писать реальный код и тестировать разные концепции."><meta itemprop="datePublished" content="2023-03-29T00:00:00+00:00" /> -<meta itemprop="dateModified" content="2024-03-22T23:57:08+03:00" /> -<meta itemprop="wordCount" content="1589"> -<meta itemprop="keywords" content="" /><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Нюансы разработки парсера для своего языка программирования"/> -<meta name="twitter:description" content="Недавно прочитал на Хабре статью Свой язык, или как я устал от ассемблера и С, и невольно взглядом зацепился за один абзац: -Я решил не сильно париться, поэтому использовал библиотеку parglare. Она очень легкая и удобная, всем рекомендую. Для описания синтаксиса парсер принимает строку в соответствующем формате, использует регулярные выражения (не надо осуждать регулярки, они всесильны!). -В результате решил опубликовать статью на основе своих старых записей еще с тех времен, когда идея NewLang до конца еще не выкристаллизовалась, но уже хотелось писать реальный код и тестировать разные концепции."/> - - - - - -<link href="/scss/main.css" rel="stylesheet"> - -<script - src="https://code.jquery.com/jquery-3.6.3.min.js" - integrity="sha512-STof4xm1wgkfm7heWqFJVn58Hm3EtS31XFaagaa8VMReCXAkQnJZ+jEy8PCC/iT18dFy95WcExNHFTqLyp72eQ==" - crossorigin="anonymous"></script> -<script defer - src="https://unpkg.com/lunr@2.3.9/lunr.min.js" - integrity="sha384-203J0SNzyqHby3iU6hzvzltrWi/M41wOP5Gu+BiJMz5nwKykbkUx8Kp7iti0Lpli" - crossorigin="anonymous"></script> - - </head> - <body class="td-page td-blog"> - <header> - <nav class="td-navbar navbar-dark js-navbar-scroll"> -<div class="container-fluid flex-column flex-md-row"> - <a class="navbar-brand" href="/"><span class="navbar-brand__logo navbar-logo"><svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500" style="enable-background:new 0 0 500 500"><g><path style="fill:#fff" d="M116.8525 421.9722c-5.7041.0-10.3442-4.3127-10.3442-9.6129V88.183c0-5.3002 4.6401-9.6117 10.3442-9.6117H320.858c3.0347.0 9.3959.5498 11.7506 2.6302l.3545.3442 58.905 63.2912c2.3101 2.491 2.9202 8.4928 2.9202 11.3184v256.2039c0 5.3002-4.6407 9.6129-10.3436 9.6129H116.8525z"/><g><g><g><path style="fill:#767676" d="M384.4445 423.2066H116.852c-6.3839.0-11.5786-4.8658-11.5786-10.8474V88.1831c0-5.9804 5.1947-10.8461 11.5786-10.8461h204.0062c.377.0 9.2786.0329 12.568 2.9389l.3947.3833 58.9508 63.337c3.2135 3.4652 3.2514 11.7924 3.2514 12.1593v256.2036C396.0231 418.3408 390.8284 423.2066 384.4445 423.2066zM116.5079 411.9189c.0848.0278.1999.0531.3441.0531h267.5925c.1442.0.2581-.0253.3441-.0531V156.1556c-.0076-.9033-.3593-3.7347-.7034-5.0037l-57.6527-61.9416c-1.4651-.3176-4.4533-.6389-5.5742-.6389H116.852c-.143.0-.2594.024-.3441.0531V411.9189zm267.4533-261.149zM327.0321 89.371v.0013V89.371z"/></g></g></g><g><g><path style="fill:#5b7fc0" d="M189.0874 210.1754l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.025 2.454-11.4897 6.4116-15.4473C177.5953 212.627 183.0601 210.1742 189.0874 210.1754zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403S197.0816 234.1722 197.0804 232.033z"/><path style="opacity:.3;fill:#fff" d="M189.0898 210.176c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 212.6276 183.0612 210.176 189.0898 210.176zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 236.239 197.0839 234.2399 197.0839 232.0372z"/><g><defs><path id="SVGID_1_" d="M194.7376 237.6875c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.999 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 234.2399 196.1861 236.239 194.7376 237.6875z"/></defs><clipPath id="SVGID_2_"><use xlink:href="#SVGID_1_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_2_);fill:#fff" d="M190.0704 225.0237c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 225.7247 191.9774 225.0237 190.0704 225.0237z"/><path style="opacity:.13;clip-path:url(#SVGID_2_);fill:#020202" d="M190.0704 225.0237c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 225.7247 191.9774 225.0237 190.0704 225.0237z"/></g><g><defs><path id="SVGID_3_" d="M189.0898 210.176c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 212.6276 183.0612 210.176 189.0898 210.176zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 236.239 197.0839 234.2399 197.0839 232.0372z"/></defs><clipPath id="SVGID_4_"><use xlink:href="#SVGID_3_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_4_);fill:#5b7fc0" d="M172.6595 215.6045c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8612 12.0547.0024 21.8636-9.797 21.8613-21.8612.0024-3.8475-1.0151-7.6326-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 209.1953 176.6171 211.647 172.6595 215.6045z"/></g></g><rect x="198.8952" y="225.1043" style="fill:#5b7fc0" width="122.6266" height="13.8671"/></g><g><path style="fill:#d95140" d="M189.0874 155.7611l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.0249 2.454-11.4897 6.4116-15.4473C177.5953 158.2128 183.0601 155.7599 189.0874 155.7611zm7.993 21.8577c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403C196.2508 181.7667 197.0816 179.758 197.0804 177.6188z"/><path style="opacity:.3;fill:#fff" d="M189.0898 155.7617c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 158.2134 183.0612 155.7617 189.0898 155.7617zm7.9941 21.8613c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 181.8248 197.0839 179.8256 197.0839 177.623z"/><g><defs><path id="SVGID_5_" d="M194.7376 183.2733c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.9989 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 179.8256 196.1861 181.8248 194.7376 183.2733z"/></defs><clipPath id="SVGID_6_"><use xlink:href="#SVGID_5_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_6_);fill:#fff" d="M190.0704 170.6095c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 171.3104 191.9774 170.6095 190.0704 170.6095z"/><path style="opacity:.13;clip-path:url(#SVGID_6_);fill:#020202" d="M190.0704 170.6095c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 171.3104 191.9774 170.6095 190.0704 170.6095z"/></g><g><defs><path id="SVGID_7_" d="M189.0898 155.7617c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 158.2134 183.0612 155.7617 189.0898 155.7617zm7.9941 21.8613c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 181.8248 197.0839 179.8256 197.0839 177.623z"/></defs><clipPath id="SVGID_8_"><use xlink:href="#SVGID_7_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_8_);fill:#d95140" d="M172.6595 161.1903c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8613 12.0547.0024 21.8636-9.797 21.8613-21.8613.0024-3.8474-1.0151-7.6326-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 154.7811 176.6171 157.2327 172.6595 161.1903z"/></g><rect x="198.8952" y="170.69" style="fill:#d95140" width="122.6266" height="13.8671"/></g><g><g><path style="fill:#56a55c" d="M189.5379 264.6147l.0012-.0012c7.7751.0012 15.0294 4.1862 18.932 10.9235 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032-5.8394.0-11.3281-2.2733-15.458-6.4032-4.13-4.13-6.4032-9.6186-6.4056-15.4628.0012-6.0249 2.454-11.4897 6.4116-15.4472C178.0458 267.0663 183.5105 264.6135 189.5379 264.6147zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6538 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403C196.7013 290.6202 197.5321 288.6115 197.5309 286.4723z"/><path style="opacity:.3;fill:#fff" d="M189.5403 264.6153c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8065-21.8612-21.8613.0-6.0285 2.4516-11.492 6.4116-15.452C178.0482 267.0669 183.5117 264.6153 189.5403 264.6153zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.6366 290.6783 197.5344 288.6792 197.5344 286.4765z"/><g><defs><path id="SVGID_9_" d="M195.1881 292.1268c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.9989 7.9942-7.9941 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.5344 288.6792 196.6366 290.6783 195.1881 292.1268z"/></defs><clipPath id="SVGID_10_"><use xlink:href="#SVGID_9_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_10_);fill:#fff" d="M190.5209 279.463c-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7446-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9941 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C194.239 280.164 192.4279 279.463 190.5209 279.463z"/><path style="opacity:.13;clip-path:url(#SVGID_10_);fill:#020202" d="M190.5209 279.463c-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7446-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9941 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C194.239 280.164 192.4279 279.463 190.5209 279.463z"/></g><g><defs><path id="SVGID_11_" d="M189.5403 264.6153c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8065-21.8612-21.8613.0-6.0285 2.4516-11.492 6.4116-15.452C178.0482 267.0669 183.5117 264.6153 189.5403 264.6153zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.6366 290.6783 197.5344 288.6792 197.5344 286.4765z"/></defs><clipPath id="SVGID_12_"><use xlink:href="#SVGID_11_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_12_);fill:#56a55c" d="M173.11 270.0439c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8613 12.0547.0024 21.8636-9.797 21.8613-21.8613.0024-3.8474-1.0151-7.6326-2.9353-10.9462-3.8977-6.7325-11.1497-10.9151-18.926-10.9151C182.5311 263.6346 177.0676 266.0863 173.11 270.0439z"/></g></g><rect x="199.3456" y="279.5436" style="fill:#56a55c" width="122.6266" height="13.8671"/></g><g><g><path style="fill:#f1bc42" d="M189.0874 318.7208l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3305-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.025 2.454-11.4897 6.4116-15.4472C177.5953 321.1724 183.0601 318.7196 189.0874 318.7208zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403S197.0816 342.7176 197.0804 340.5784z"/><path style="opacity:.3;fill:#fff" d="M189.0898 318.7214c7.7763.0 15.0283 4.1826 18.926 10.915 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8612-12.0547.0024-21.8636-9.8065-21.8612-21.8612.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 321.173 183.0612 318.7214 189.0898 318.7214zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 344.7844 197.0839 342.7853 197.0839 340.5826z"/><g><defs><path id="SVGID_13_" d="M194.7376 346.2329c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.999 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 342.7853 196.1861 344.7844 194.7376 346.2329z"/></defs><clipPath id="SVGID_14_"><use xlink:href="#SVGID_13_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_14_);fill:#fff" d="M190.0704 333.5691c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0834 6.1218 2.8788C193.7885 334.2701 191.9774 333.5691 190.0704 333.5691z"/><path style="opacity:.13;clip-path:url(#SVGID_14_);fill:#020202" d="M190.0704 333.5691c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0834 6.1218 2.8788C193.7885 334.2701 191.9774 333.5691 190.0704 333.5691z"/></g><g><defs><path id="SVGID_15_" d="M189.0898 318.7214c7.7763.0 15.0283 4.1826 18.926 10.915 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8612-12.0547.0024-21.8636-9.8065-21.8612-21.8612.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 321.173 183.0612 318.7214 189.0898 318.7214zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 344.7844 197.0839 342.7853 197.0839 340.5826z"/></defs><clipPath id="SVGID_16_"><use xlink:href="#SVGID_15_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_16_);fill:#f1bc42" d="M172.6595 324.15c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8612 12.0547.0024 21.8636-9.797 21.8613-21.8612.0024-3.8474-1.0151-7.6327-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 317.7407 176.6171 320.1924 172.6595 324.15z"/></g></g><rect x="198.8952" y="333.6497" style="fill:#f1bc42" width="122.6266" height="13.8671"/></g></g></svg></span><span class="navbar-brand__name">NewLang</span></a> - <div class="td-navbar-nav-scroll ms-md-auto" id="main_navbar"> - <ul class="navbar-nav"> - <li class="nav-item"> - <a class="nav-link" href="/docs/"><span>Documentation</span></a> - </li> - <li class="nav-item"> - <a class="nav-link" href="/playground/"><span>Playground</span></a> - </li> - <li class="nav-item"> - <a class="nav-link active" href="/blog/"><span>Articles</span></a> - </li> - <li class="nav-item dropdown d-none d-lg-block"> - <div class="dropdown"> - <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">English</a> - <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/ru/blog/parser-nuances/">Русский</a></li> - </ul> -</div></li> - </ul> - </div> - <div class="d-none d-lg-block"> - <div class="td-search td-search--offline"> - <div class="td-search__icon"></div> - <input - type="search" - class="td-search__input form-control" - placeholder="Search this site…" - aria-label="Search this site…" - autocomplete="off" - - data-offline-search-index-json-src="/offline-search-index.json" - data-offline-search-base-href="/" - data-offline-search-max-results="10" - > -</div> - </div> -</div> -</nav> - </header> - <div class="container-fluid td-outer"> - <div class="td-main"> - <div class="row flex-xl-nowrap"> - <aside class="col-12 col-md-3 col-xl-2 td-sidebar d-print-none"> - <div id="td-sidebar-menu" class="td-sidebar__inner"> - <form class="td-sidebar__search d-flex align-items-center"> - <div class="td-search td-search--offline"> - <div class="td-search__icon"></div> - <input - type="search" - class="td-search__input form-control" - placeholder="Search this site…" - aria-label="Search this site…" - autocomplete="off" - - data-offline-search-index-json-src="/offline-search-index.json" - data-offline-search-base-href="/" - data-offline-search-max-results="10" - > -</div> - <button class="btn btn-link td-sidebar__toggle d-md-none p-0 ms-3 fas fa-bars" type="button" data-bs-toggle="collapse" data-bs-target="#td-section-nav" aria-controls="td-section-nav" aria-expanded="false" aria-label="Toggle section navigation"> - </button> - </form> - <nav class="td-sidebar-nav collapse" id="td-section-nav"> - <div class="td-sidebar-nav__section nav-item dropdown d-block d-lg-none"> - <div class="dropdown"> - <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">English</a> - <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/ru/blog/parser-nuances/">Русский</a></li> - </ul> -</div> - </div> - <ul class="td-sidebar-nav__section pe-md-3 ul-0"> - <li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child active-path" id="m-blog-li"> - <a href="/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-blog"><span class="">Articles</span></a> - <ul class="ul-1"> - <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v04-li"> - <a href="/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child active-path" id="m-blogparser-nuances-li"> - <a href="/blog/parser-nuances/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__page" id="m-blogparser-nuances"><span class="td-sidebar-nav-active-item">Нюансы разработки парсера для своего языка программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogdsl-domain-specific-language-implementation-with-macros-li"> - <a href="/blog/dsl-domain-specific-language-implementation-with-macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogdsl-domain-specific-language-implementation-with-macros"><span class="">DSL (domain-specific language) implementation with macros</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v03-li"> - <a href="/blog/release-v0.3/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v03"><span class="">Релиз языка программрования NewLang 0.3</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v02-li"> - <a href="/blog/release-v0.2/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v02"><span class="">Релиз языка программрования NewLang 0.2</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v01-li"> - <a href="/blog/release-v0.1/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v01"><span class="">Релиз языка программрования NewLang</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blognewlang-li"> - <a href="/blog/newlang/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blognewlang"><span class="">Новый язык программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogprog-styles-same-time-li"> - <a href="/blog/prog-styles-same-time/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogprog-styles-same-time"><span class="">Можно ли использовать декларативный и императивный стили написания программ одновременно?</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogunusual-prog-li"> - <a href="/blog/unusual-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogunusual-prog"><span class="">Необычная концепция синтаксиса языка программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogcomplex-prog-li"> - <a href="/blog/complex-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogcomplex-prog"><span class="">Простое сложное программирование</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloglang-final-li"> - <a href="/blog/lang-final/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloglang-final"><span class="">Какая «идеальная» цель развития у языков программирования?</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloglogic-prog-li"> - <a href="/blog/logic-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloglogic-prog"><span class="">Проблема логических языков программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloginter-prog-li"> - <a href="/blog/inter-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloginter-prog"><span class="">Интернациональное программирование на естественных языках</span></a> -</li> - </ul> -</li> - </ul> - </nav> -</div> - - </aside> - <aside class="d-none d-xl-block col-xl-2 td-sidebar-toc d-print-none"> - <div class="td-page-meta ms-2 pb-1 pt-2 mb-0"> -<a id="print" href="/blog/_print/"><i class="fa-solid fa-print fa-fw"></i> Print entire section</a> - -</div> - - <div class="td-toc"> - <nav id="TableOfContents"> - <ul> - <li> - <ul> - <li><a href="#используемые-термины">Используемые термины.</a></li> - </ul> - </li> - <li><a href="#заход--1---flex--bison">Заход № 1 - Flex + Bison</a></li> - <li><a href="#заход--2---flex--lemon">Заход № 2 - Flex + Lemon</a></li> - <li><a href="#заход--3-парсер-на-регулярках-re2c">Заход № 3 парсер на регулярках re2c</a></li> - <li><a href="#заход--4---flex-flexcpp--bisoncpp">Заход № 4 - flex (flexcpp) + bisoncpp</a></li> - <li><a href="#заход--5---неродной-парсер-antlr">Заход № 5 - неродной парсер ANTLR</a></li> - <li><a href="#заход--6-последний---возвращение-к-flex--bison">Заход № 6, последний - возвращение к Flex + Bison</a></li> - <li><a href="#выводы-на-память">Выводы на память</a></li> - <li><a href="#стратегия-обработки-ошибок-синтаксиса">Стратегия обработки ошибок синтаксиса</a></li> - <li><a href="#макросы-и-модификация-грамматики-в-runtime">Макросы и модификация грамматики в Runtime</a></li> - <li><a href="#самое-главное-при-разработке-грамматики">Самое главное при разработке грамматики!</a></li> - </ul> -</nav> - </div> - - <div class="taxonomy taxonomy-terms-cloud taxo-tags"> - <h5 class="taxonomy-title">Tag Cloud</h5> - <ul class="taxonomy-terms"> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B/" data-taxonomy-term="%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B"><span class="taxonomy-label">Итераторы</span><span class="taxonomy-count">1</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8/" data-taxonomy-term="%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8"><span class="taxonomy-label">Коллекции</span><span class="taxonomy-count">4</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%BE%D0%BE%D0%BF/" data-taxonomy-term="%D0%BE%D0%BE%D0%BF"><span class="taxonomy-label">ООП</span><span class="taxonomy-count">3</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B/" data-taxonomy-term="%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B"><span class="taxonomy-label">Системые Типы</span><span class="taxonomy-count">1</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85/" data-taxonomy-term="%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85"><span class="taxonomy-label">Типы Данных</span><span class="taxonomy-count">8</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8/" data-taxonomy-term="%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8"><span class="taxonomy-label">Функции</span><span class="taxonomy-count">1</span></a></li> - </ul> - </div> - - - </aside> - <main class="col-12 col-md-9 col-xl-8 ps-md-5 pe-md-4" role="main"> - <a class="td-rss-button" title="RSS" href="/blog/index.xml" target="_blank" rel="noopener"> - <i class="fa-solid fa-rss" aria-hidden="true"></i> - </a> - -<div class="td-content"> - <h1>Нюансы разработки парсера для своего языка программирования</h1> - - <div class="td-byline mb-4"> - - <time datetime="2023-03-29" class="text-muted">Wednesday, March 29, 2023</time> - </div> - <header class="article-meta"> - - </header> - <p><img alt="КДПВ" src="/blog/langs.jpeg"></p> -<p>Недавно прочитал на Хабре статью <a href="https://habr.com/post/723400/">Свой язык, или как я устал от ассемблера и С</a>, и невольно взглядом зацепился за один абзац:</p> -<blockquote> -<p>Я решил не сильно париться, поэтому использовал библиотеку parglare. Она очень легкая и удобная, всем рекомендую. Для описания синтаксиса парсер принимает строку в соответствующем формате, использует регулярные выражения (не надо осуждать регулярки, они всесильны!).</p> -</blockquote> -<p>В результате решил опубликовать статью на основе своих старых записей еще с тех времен, когда идея <a href="https://newlang.net/">NewLang</a> до конца еще не выкристаллизовалась, но уже хотелось писать реальный код и тестировать разные концепции.</p> -<p>Ведь в жизни практически любого программиста может наступить момент, когда ему в голову приходит светлая идея - разработать свой собственный язык программирования. Может быть и не ради захвата мира, наравне с C/C++, Python или хотя бы PHP, а в качестве личного пет-проекта, с которым он, длинными зимними вечерами будет оттачивать собственное мастерство.</p> -<p>А так как у любого языка (не только программирования), все начинается с анализа его грамматики, то самой первой задачей создателя будет выбор инструментов для синтаксического анализа исходного текста.</p> -<p>Это история — заметки на память о муках выбора связки лексер-парсер для разбора грамматики NewLang. А так же попытка описать и систематизировать выводы об особенностях разных анализаторов с которыми пришлось поработать при выборе парсера для разбора грамматики у своего языка программирования.</p> -<h3 id="используемые-термины">Используемые термины.<a class="td-heading-self-link" href="#%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d0%b5%d0%bc%d1%8b%d0%b5-%d1%82%d0%b5%d1%80%d0%bc%d0%b8%d0%bd%d1%8b" aria-label="Heading self-link"></a></h3> -<p>Чтобы было понятно, о чем в дальнейшем пойдет речь.</p> -<blockquote> -<p>Лексер — компьютерная программа или библиотека, в задачи которой входит разделить входной поток данных на отдельные, не связанные между собой отдельные фрагменты, которые принято называть токенами или лексемами.</p> -<p>Парсер — на основе последовательности токенов выполняется синтаксический анализ, например строит абстрактное синтаксическое дерево (AST).</p> -</blockquote> -<h2 id="заход--1---flex--bison">Заход № 1 - Flex + Bison<a class="td-heading-self-link" href="#%d0%b7%d0%b0%d1%85%d0%be%d0%b4--1---flex--bison" aria-label="Heading self-link"></a></h2> -<p><a href="https://github.com/westes/flex">GitHub - westes/flex: The Fast Lexical Analyzer - scanner generator for lexing in C and C++</a> -<a href="https://www.gnu.org/software/bison/">Bison - GNU Project - Free Software Foundation</a></p> -<p>После прочтения умных книжек я начал с классики Flex + Bison. Это старые и давно отработанные приложения с широчайшими возможностями по настройке с помощью которых можно описать синтаксис и получить исходные файлы лексера и парсера для языка практически с любой грамматикой.</p> -<p>К сожалению, у этих старичков очень большой порог входа и тяжелая наследственность. Чего только стоит определение собственного класса лексера через <code>#define</code>, а так же отсутствие нормальной поддержки С++. Вынужденные танцы с бубном для пасинга отдельной строки, когда не требуется анализировать файл целиком и прочие не всегда очевидные проблемы и разные не понятные условности.</p> -<p>Другими словами, через несколько недель безуспешных мучений я решил посмотреть альтернативы, а так как начальный файл лексики после экспериментов с Flex + Bison кое-как уже был сделан, то следующая связка была Flex + lemon.</p> -<h2 id="заход--2---flex--lemon">Заход № 2 - Flex + Lemon<a class="td-heading-self-link" href="#%d0%b7%d0%b0%d1%85%d0%be%d0%b4--2---flex--lemon" aria-label="Heading self-link"></a></h2> -<p><a href="https://www.sqlite.org/lemon.html">The Lemon LALR(1) Parser Generator</a></p> -<p>Тут все оказалось до примитивности просто и понятно. Реально очень быстрый старт с боевыми примерами, очень наглядный и понятный способ записи правил (по сравнению с Bison). Все хорошо кроме одного, хорошее быстро заканчивается, если приходится анализировать более одной строки.</p> -<p>По сути, Lemon с Bison, это как Инь и Янь. Lemon простой и удобный для работы с одной строкой (для этого он и создавался), а Bison супер-пупер-мега комбайн для парсинга файлов любых размеров.</p> -<p>Поэтому, поиски связки лексер + парсер продолжились и после прочтения очередной статьи, что парсеры языков можно делать на регулярках, решил посмотреть, что есть в этом направлении:</p> -<h2 id="заход--3-парсер-на-регулярках-re2c">Заход № 3 парсер на регулярках re2c<a class="td-heading-self-link" href="#%d0%b7%d0%b0%d1%85%d0%be%d0%b4--3-%d0%bf%d0%b0%d1%80%d1%81%d0%b5%d1%80-%d0%bd%d0%b0-%d1%80%d0%b5%d0%b3%d1%83%d0%bb%d1%8f%d1%80%d0%ba%d0%b0%d1%85-re2c" aria-label="Heading self-link"></a></h2> -<p>Из описания <a href="https://re2c.org/">re2c</a>:</p> -<blockquote> -<p>По сути, на этой штуке можно писать лексические анализаторы прямо на коленке за несколько минут.</p> -</blockquote> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c++" data-lang="c++"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic">/*!re2c -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYPEEK = &#34;*cursor&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYSKIP = &#34;++cursor;&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYBACKUP = &#34;marker = cursor;&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYRESTORE = &#34;cursor = marker;&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYBACKUPCTX = &#34;ctxmarker = cursor;&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYRESTORECTX = &#34;cursor = ctxmarker;&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYRESTORETAG = &#34;cursor = ${tag};&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYLESSTHAN = &#34;limit - cursor &lt; @@{len}&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYSTAGP = &#34;@@{tag} = cursor;&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYSTAGN = &#34;@@{tag} = NULL;&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYSHIFT = &#34;cursor += @@{shift};&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> re2c:define:YYSHIFTSTAG = &#34;@@{tag} += @@{shift};&#34;; -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"> */</span> -</span></span></code></pre></div><p>Показалось, что это самый удобный способ указания шаблонов для парсера! Достаточно описать в комментариях нужные шаблоны, напустить на исходный файл компилятор регулярок и все готово! Но нет, действительно, это только показалось.</p> -<p>Ведь для простеньких парсеров или регулярных выражений <strong>re2c</strong> может быть и действительно хорош, но отлаживать синтаксис большого языка на регулярках слишком хлопотное занятие.</p> -<p>После этого решил с ним не заморачиваться и посмотреть альтернативы классическим лексерам и парсерам.</p> -<h2 id="заход--4---flex-flexcpp--bisoncpp">Заход № 4 - flex (flexcpp) + bisoncpp<a class="td-heading-self-link" href="#%d0%b7%d0%b0%d1%85%d0%be%d0%b4--4---flex-flexcpp--bisoncpp" aria-label="Heading self-link"></a></h2> -<p>Тогда как у традиционных flex + bison поддержка С++ реализована <del>через одно место</del> на уровне - работает и не трогай, то решил посмотреть их альтернативную реализация <a href="https://gitlab.com/fbb-git/flexcpp">flexcpp</a> + <a href="https://gitlab.com/fbb-git/bisoncpp">bisoncpp</a> с нативной поддержкой С++.</p> -<p>Первое впечатление было, то что доктор прописал!</p> -<p>Синтаксис записи лексики хоть немного и отличается от классической, но это не принципиально. Зато есть нативная и логичная поддержка С++ без оберток и выкрутасов, и как дополнительный плюс - более удобный синтаксис указания правил в парсере. Но и тут не обошлось без шероховатостей.</p> -<p>В шаблонах правил bisoncpp не поддерживает юникод (хотя сам лексер-парсер с ним справляется на ура), и совсем не понятная ситуация с поддержкой. Как я понял, разработчиком является вроде бы один человек, но пообщаться с ним насчет ошибок при обработке русских символов так и не получилось.*</p> -<p>Потом еще одно непонятное поведение вылезло в другом месте. В результате решил отказаться от недружелюбной поддержки и посмотреть, какие есть еще варианты парсеров.</p> -<hr> -<p>*) Через два года мой тикет был закрыт с комментарием, что поддерживаются только ascii символы.</p> -<h2 id="заход--5---неродной-парсер-antlr">Заход № 5 - неродной парсер ANTLR<a class="td-heading-self-link" href="#%d0%b7%d0%b0%d1%85%d0%be%d0%b4--5---%d0%bd%d0%b5%d1%80%d0%be%d0%b4%d0%bd%d0%be%d0%b9-%d0%bf%d0%b0%d1%80%d1%81%d0%b5%d1%80-antlr" aria-label="Heading self-link"></a></h2> -<p>От использования <a href="https://www.antlr.org/">ANTLR</a> (от англ. ANother Tool for Language Recognition — «ещё одно средство распознавания языков») — генератора нисходящих анализаторов для формальных языков, я решил сразу отказать из-за того, что он написан на Java,.</p> -<p>В этом нет никаких религиозных предпочтений, так как я искал генератор парсеров, который можно было бы сделать встроенным прямо в среду выполнения, а в случае с ANTLR и JRE это было бы затруднительно.</p> -<p>Таким образом я опять вернулся к старичкам Flex и Bison, с которых все и начиналось.</p> -<h2 id="заход--6-последний---возвращение-к-flex--bison">Заход № 6, последний - возвращение к Flex + Bison<a class="td-heading-self-link" href="#%d0%b7%d0%b0%d1%85%d0%be%d0%b4--6-%d0%bf%d0%be%d1%81%d0%bb%d0%b5%d0%b4%d0%bd%d0%b8%d0%b9---%d0%b2%d0%be%d0%b7%d0%b2%d1%80%d0%b0%d1%89%d0%b5%d0%bd%d0%b8%d0%b5-%d0%ba-flex--bison" aria-label="Heading self-link"></a></h2> -<p>Все описанные выше эксперименты заняли в общем итоге несколько месяцев, в результате которых были написаны килобайты исходного кода и тестовых примеров, прочитано десятки статей и как результат - возврат к изначальной связке Flex + Bison, но уже с солидным багажом опыта в применении различных вариантов лексеров-парсеров.</p> -<p>Но самое главное, с пониманием того, что же в результате хочется получить, и очень большой базой тестовых примеров синтаксиса.</p> -<h2 id="выводы-на-память">Выводы на память<a class="td-heading-self-link" href="#%d0%b2%d1%8b%d0%b2%d0%be%d0%b4%d1%8b-%d0%bd%d0%b0-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d1%8c" aria-label="Heading self-link"></a></h2> -<p>В итоге для себя решил следующее: если нужен простенький шаблонизатор, то идеальный вариант <strong>re2c</strong> (если почему-то не подходит <strong>regexp</strong>). Если требуется анализировать синтаксис сложнее обычных регулярок, но в одну строку, то идеальной будет связка flex+lemon, а если нужна серьезная артиллерия, то тут однозначно flex + bison.</p> -<p>От связки flexcpp + bisoncpp отказался совсем. Что с поддержкой — не понятно, синтаксис от классики отличается не очень сильно (хотя тоже нужно ломать голову), а обход выявленных косяков не стоят того синтаксического сахара.</p> -<p>И по итогам множества экспериментов с разными вариантами синтаксиса удалось сформулировать пару важных архитектурных моментов, которые могут очень сильно упростить жизнь создателям языком программирования:</p> -<h2 id="стратегия-обработки-ошибок-синтаксиса">Стратегия обработки ошибок синтаксиса<a class="td-heading-self-link" href="#%d1%81%d1%82%d1%80%d0%b0%d1%82%d0%b5%d0%b3%d0%b8%d1%8f-%d0%be%d0%b1%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b8-%d0%be%d1%88%d0%b8%d0%b1%d0%be%d0%ba-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81%d0%b0" aria-label="Heading self-link"></a></h2> -<p>Обычно принято обрабатывать синтаксические ошибки непосредственно в парсере и для этого есть определенный резон — в этом случае нет необходимости в каких либо дальнейших действиях, нужна только полностью описанная корректная грамматика.</p> -<p>Но если грамматика языка очень сложная (привет C++), и её описание становится сложной задачей, то можно отказался и от анализа ошибок синтаксиса непосредственно в парсере! То есть, лучше сделать максимально широкую лексику (даже с теми вариантами, которые являются для языка ошибочными), но ловить эти ошибки уже при анализе AST!</p> -<p>В этом случае, поддерживать описание грамматики языка становится значительно проще (меньше синтаксических правил, проще их формальное описание и т.д.), а самое главное, при описании грамматики не нужно думать про lval или rval, где можно указывать ссылку, а где нет — т. е. можно указывать все и везде, а вот анализ допустимости использования конкретных терминов будет выполняться позднее при анализе AST.</p> -<p><em>Отказа от полного анализа грамматики языка на уровне лексера — парсера и перенос проверки корректности синтаксических конструкций на этап разбора синтаксического дерева позволяет в разы, если не на порядки сократить и значительно упростить описание грамматических правил!</em></p> -<p>Подобное допущение очень полезно на начальном этапе создания языка (можно сосредоточиться на общей концепции, вместо постоянных правок в грамматике), а так же значительно упростить в будущем поддержку и/или расширение синтаксиса.</p> -<h2 id="макросы-и-модификация-грамматики-в-runtime">Макросы и модификация грамматики в Runtime<a class="td-heading-self-link" href="#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b8-%d0%bc%d0%be%d0%b4%d0%b8%d1%84%d0%b8%d0%ba%d0%b0%d1%86%d0%b8%d1%8f-%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b0%d1%82%d0%b8%d0%ba%d0%b8-%d0%b2-runtime" aria-label="Heading self-link"></a></h2> -<p>Какими бы мощными не были flex+bison, но у этой связки есть одна архитектурная проблема. Логика flex и bison построена на конечных автоматах и изменить грамматику языка во время выполнения приложения невозможно, тем более Bison сам вызывает лексер для получения очередной порции данных и ему очень непросто подсунуть измененные данные прямо во время работы. А так хотелось сделать возможность раскрытия макросов и модификации синтаксиса за один проход анализатора!</p> -<p>Для этого пришлось переделать логику работы flex+bison, чтобы парсер получал данные из лексера не напрямую из yylex, а через функцию — прокси. Эта промежуточная функция, складывает считанные лексемы во внутренний буфер. Данные в буфере анализируется на предмет наличия макросов и только после их раскрытия, лексемы отдаются в парсер из вершины буфера по одной за раз. Подробнее о макросах NewLang можно почитать <a href="/blog/2023/03/01/%D0%B2%D0%B0%D1%80%D0%B8%D0%B0%D0%BD%D1%82-%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8-dsl-domain-specific-language-%D1%81-%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E-%D0%BC%D0%B0%D0%BA%D1%80%D0%BE%D1%81%D0%BE%D0%B2/">тут</a>.</p> -<h2 id="самое-главное-при-разработке-грамматики">Самое главное при разработке грамматики!<a class="td-heading-self-link" href="#%d1%81%d0%b0%d0%bc%d0%be%d0%b5-%d0%b3%d0%bb%d0%b0%d0%b2%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%b8-%d1%80%d0%b0%d0%b7%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b5-%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b0%d1%82%d0%b8%d0%ba%d0%b8" aria-label="Heading self-link"></a></h2> -<p>Но самый важный совет мне подсказал друг, который некогда участвовал в проекте по разработке парсера для языка программирования. И в правильности его совета - <strong>пиши тесты для грамматики</strong> - я убеждался уже множество раз. Даже так, <strong>ПИШИ ТЕСТЫ ДЛЯ ГРАММАТИКИ</strong>.</p> -<p>Тесты для грамматики языка гораздо более важная вещь, чем любой из используемых инструментов. Только тесты позволяют убедиться в том, что новая фича в языке не сломала старые наработки. А если все же сломала, то в первую очередь нужно добавить новый тест, который бы фиксировал сломавшийся сценарий и только после этого можно будет со спокойной душой продолжать эксперименты с новыми грамматическими конструкциями.</p> -<p>И удачи всем языкописателям!</p> -<p><a href="https://habr.com/companies/timeweb/articles/724146/">Ссылка на первую публикаци</a></p> - - <ul class="list-unstyled d-flex justify-content-between align-items-center mb-0 pt-5"> - <li> - <a href="/blog/dsl-domain-specific-language-implementation-with-macros/" aria-label="Previous - DSL (domain-specific language) implementation with macros" class="btn btn-primary"><span class="me-1">←</span>Previous</a> - </li> - <li> - <a href="/blog/release-v0.4/" aria-label="Next - Релиз языка программрования NewLang 0.4" class="btn btn-primary">Next<span class="ms-1">→</span></a> - </li> -</ul> - - </div> - - - </main> - </div> - </div> - <footer class="td-footer row d-print-none"> - <div class="container-fluid"> - <div class="row mx-md-2"> - <div class="td-footer__left col-6 col-sm-4 order-sm-1"> - <ul class="td-footer__links-list"> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="User mailing list" aria-label="User mailing list"> - <a target="_blank" rel="noopener" href="mailto:mail@newlang.net" aria-label="User mailing list"> - <i class="fa fa-envelope"></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - -</ul> - - </div><div class="td-footer__right col-6 col-sm-4 order-sm-3"> - <ul class="td-footer__links-list"> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="GitHub" aria-label="GitHub"> - <a target="_blank" rel="noopener" href="https://github.com/rsashka/newlang" aria-label="GitHub"> - <i class="fab fa-github"></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - -</ul> - - </div><div class="td-footer__center col-12 col-sm-4 py-2 order-sm-2"> - <span class="td-footer__copyright">&copy; - 2024 - <span class="td-footer__authors">The NewLang Authors</span></span><span class="td-footer__all_rights_reserved">All Rights Reserved</span> - </div> - </div> - </div> -</footer> - - </div> - <script src="/js/main.js"></script> -<script defer src="/js/click-to-copy.js" crossorigin="anonymous"></script> -<script src='/js/tabpane-persist.js'></script> - - </body> -</html> \ No newline at end of file diff --git a/docs/blog/prog-styles-same-time/index.html b/docs/blog/prog-styles-same-time/index.html deleted file mode 100644 index 74574973..00000000 --- a/docs/blog/prog-styles-same-time/index.html +++ /dev/null @@ -1,511 +0,0 @@ -<!doctype html> -<html itemscope itemtype="http://schema.org/WebPage" lang="en" class="no-js"> - <head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script> - <meta charset="utf-8"> -<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> -<meta name="robots" content="noindex, nofollow"> - - -<link rel="shortcut icon" href="/favicons/favicon.ico" > -<link rel="apple-touch-icon" href="/favicons/apple-touch-icon-180x180.png" sizes="180x180"> -<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16"> -<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32"> -<link rel="icon" type="image/png" href="/favicons/android-36x36.png" sizes="36x36"> -<link rel="icon" type="image/png" href="/favicons/android-48x48.png" sizes="48x48"> -<link rel="icon" type="image/png" href="/favicons/android-72x72.png" sizes="72x72"> -<link rel="icon" type="image/png" href="/favicons/android-96x96.png" sizes="96x96"> -<link rel="icon" type="image/png" href="/favicons/android-144x144.png" sizes="144x144"> -<link rel="icon" type="image/png" href="/favicons/android-192x192.png" sizes="192x192"> - -<title>Можно ли использовать декларативный и императивный стили написания программ одновременно? | NewLang</title> -<meta name="description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -При разработке своего собственного языка программирования автор должен определиться, какими свойствами его язык должен обладать, ведь в конечном итоге именно это и будет определять назначение языка и особенности его использования. Причем некоторые свойства настолько сильно влияют на итоговую концепцию языка и его синтаксис, что впоследствии их изменение невозможно в принципе, либо новый синтаксис получается очень запутанным и непонятным."> -<meta property="og:title" content="Можно ли использовать декларативный и императивный стили написания программ одновременно?" /> -<meta property="og:description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -При разработке своего собственного языка программирования автор должен определиться, какими свойствами его язык должен обладать, ведь в конечном итоге именно это и будет определять назначение языка и особенности его использования. Причем некоторые свойства настолько сильно влияют на итоговую концепцию языка и его синтаксис, что впоследствии их изменение невозможно в принципе, либо новый синтаксис получается очень запутанным и непонятным." /> -<meta property="og:type" content="article" /> -<meta property="og:url" content="http://localhost:1313/blog/prog-styles-same-time/" /><meta property="article:section" content="blog" /> -<meta property="article:published_time" content="2021-07-26T00:00:00+00:00" /> -<meta property="article:modified_time" content="2024-03-22T23:57:08+03:00" /><meta property="og:site_name" content="NewLang" /> -<meta itemprop="name" content="Можно ли использовать декларативный и императивный стили написания программ одновременно?"> -<meta itemprop="description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -При разработке своего собственного языка программирования автор должен определиться, какими свойствами его язык должен обладать, ведь в конечном итоге именно это и будет определять назначение языка и особенности его использования. Причем некоторые свойства настолько сильно влияют на итоговую концепцию языка и его синтаксис, что впоследствии их изменение невозможно в принципе, либо новый синтаксис получается очень запутанным и непонятным."><meta itemprop="datePublished" content="2021-07-26T00:00:00+00:00" /> -<meta itemprop="dateModified" content="2024-03-22T23:57:08+03:00" /> -<meta itemprop="wordCount" content="1823"> -<meta itemprop="keywords" content="" /><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Можно ли использовать декларативный и императивный стили написания программ одновременно?"/> -<meta name="twitter:description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -При разработке своего собственного языка программирования автор должен определиться, какими свойствами его язык должен обладать, ведь в конечном итоге именно это и будет определять назначение языка и особенности его использования. Причем некоторые свойства настолько сильно влияют на итоговую концепцию языка и его синтаксис, что впоследствии их изменение невозможно в принципе, либо новый синтаксис получается очень запутанным и непонятным."/> - - - - - -<link href="/scss/main.css" rel="stylesheet"> - -<script - src="https://code.jquery.com/jquery-3.6.3.min.js" - integrity="sha512-STof4xm1wgkfm7heWqFJVn58Hm3EtS31XFaagaa8VMReCXAkQnJZ+jEy8PCC/iT18dFy95WcExNHFTqLyp72eQ==" - crossorigin="anonymous"></script> -<script defer - src="https://unpkg.com/lunr@2.3.9/lunr.min.js" - integrity="sha384-203J0SNzyqHby3iU6hzvzltrWi/M41wOP5Gu+BiJMz5nwKykbkUx8Kp7iti0Lpli" - crossorigin="anonymous"></script> - - </head> - <body class="td-page td-blog"> - <header> - <nav class="td-navbar navbar-dark js-navbar-scroll"> -<div class="container-fluid flex-column flex-md-row"> - <a class="navbar-brand" href="/"><span class="navbar-brand__logo navbar-logo"><svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500" style="enable-background:new 0 0 500 500"><g><path style="fill:#fff" d="M116.8525 421.9722c-5.7041.0-10.3442-4.3127-10.3442-9.6129V88.183c0-5.3002 4.6401-9.6117 10.3442-9.6117H320.858c3.0347.0 9.3959.5498 11.7506 2.6302l.3545.3442 58.905 63.2912c2.3101 2.491 2.9202 8.4928 2.9202 11.3184v256.2039c0 5.3002-4.6407 9.6129-10.3436 9.6129H116.8525z"/><g><g><g><path style="fill:#767676" d="M384.4445 423.2066H116.852c-6.3839.0-11.5786-4.8658-11.5786-10.8474V88.1831c0-5.9804 5.1947-10.8461 11.5786-10.8461h204.0062c.377.0 9.2786.0329 12.568 2.9389l.3947.3833 58.9508 63.337c3.2135 3.4652 3.2514 11.7924 3.2514 12.1593v256.2036C396.0231 418.3408 390.8284 423.2066 384.4445 423.2066zM116.5079 411.9189c.0848.0278.1999.0531.3441.0531h267.5925c.1442.0.2581-.0253.3441-.0531V156.1556c-.0076-.9033-.3593-3.7347-.7034-5.0037l-57.6527-61.9416c-1.4651-.3176-4.4533-.6389-5.5742-.6389H116.852c-.143.0-.2594.024-.3441.0531V411.9189zm267.4533-261.149zM327.0321 89.371v.0013V89.371z"/></g></g></g><g><g><path style="fill:#5b7fc0" d="M189.0874 210.1754l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.025 2.454-11.4897 6.4116-15.4473C177.5953 212.627 183.0601 210.1742 189.0874 210.1754zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403S197.0816 234.1722 197.0804 232.033z"/><path style="opacity:.3;fill:#fff" d="M189.0898 210.176c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 212.6276 183.0612 210.176 189.0898 210.176zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 236.239 197.0839 234.2399 197.0839 232.0372z"/><g><defs><path id="SVGID_1_" d="M194.7376 237.6875c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.999 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 234.2399 196.1861 236.239 194.7376 237.6875z"/></defs><clipPath id="SVGID_2_"><use xlink:href="#SVGID_1_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_2_);fill:#fff" d="M190.0704 225.0237c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 225.7247 191.9774 225.0237 190.0704 225.0237z"/><path style="opacity:.13;clip-path:url(#SVGID_2_);fill:#020202" d="M190.0704 225.0237c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 225.7247 191.9774 225.0237 190.0704 225.0237z"/></g><g><defs><path id="SVGID_3_" d="M189.0898 210.176c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 212.6276 183.0612 210.176 189.0898 210.176zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 236.239 197.0839 234.2399 197.0839 232.0372z"/></defs><clipPath id="SVGID_4_"><use xlink:href="#SVGID_3_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_4_);fill:#5b7fc0" d="M172.6595 215.6045c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8612 12.0547.0024 21.8636-9.797 21.8613-21.8612.0024-3.8475-1.0151-7.6326-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 209.1953 176.6171 211.647 172.6595 215.6045z"/></g></g><rect x="198.8952" y="225.1043" style="fill:#5b7fc0" width="122.6266" height="13.8671"/></g><g><path style="fill:#d95140" d="M189.0874 155.7611l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.0249 2.454-11.4897 6.4116-15.4473C177.5953 158.2128 183.0601 155.7599 189.0874 155.7611zm7.993 21.8577c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403C196.2508 181.7667 197.0816 179.758 197.0804 177.6188z"/><path style="opacity:.3;fill:#fff" d="M189.0898 155.7617c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 158.2134 183.0612 155.7617 189.0898 155.7617zm7.9941 21.8613c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 181.8248 197.0839 179.8256 197.0839 177.623z"/><g><defs><path id="SVGID_5_" d="M194.7376 183.2733c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.9989 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 179.8256 196.1861 181.8248 194.7376 183.2733z"/></defs><clipPath id="SVGID_6_"><use xlink:href="#SVGID_5_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_6_);fill:#fff" d="M190.0704 170.6095c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 171.3104 191.9774 170.6095 190.0704 170.6095z"/><path style="opacity:.13;clip-path:url(#SVGID_6_);fill:#020202" d="M190.0704 170.6095c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 171.3104 191.9774 170.6095 190.0704 170.6095z"/></g><g><defs><path id="SVGID_7_" d="M189.0898 155.7617c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 158.2134 183.0612 155.7617 189.0898 155.7617zm7.9941 21.8613c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 181.8248 197.0839 179.8256 197.0839 177.623z"/></defs><clipPath id="SVGID_8_"><use xlink:href="#SVGID_7_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_8_);fill:#d95140" d="M172.6595 161.1903c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8613 12.0547.0024 21.8636-9.797 21.8613-21.8613.0024-3.8474-1.0151-7.6326-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 154.7811 176.6171 157.2327 172.6595 161.1903z"/></g><rect x="198.8952" y="170.69" style="fill:#d95140" width="122.6266" height="13.8671"/></g><g><g><path style="fill:#56a55c" d="M189.5379 264.6147l.0012-.0012c7.7751.0012 15.0294 4.1862 18.932 10.9235 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032-5.8394.0-11.3281-2.2733-15.458-6.4032-4.13-4.13-6.4032-9.6186-6.4056-15.4628.0012-6.0249 2.454-11.4897 6.4116-15.4472C178.0458 267.0663 183.5105 264.6135 189.5379 264.6147zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6538 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403C196.7013 290.6202 197.5321 288.6115 197.5309 286.4723z"/><path style="opacity:.3;fill:#fff" d="M189.5403 264.6153c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8065-21.8612-21.8613.0-6.0285 2.4516-11.492 6.4116-15.452C178.0482 267.0669 183.5117 264.6153 189.5403 264.6153zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.6366 290.6783 197.5344 288.6792 197.5344 286.4765z"/><g><defs><path id="SVGID_9_" d="M195.1881 292.1268c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.9989 7.9942-7.9941 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.5344 288.6792 196.6366 290.6783 195.1881 292.1268z"/></defs><clipPath id="SVGID_10_"><use xlink:href="#SVGID_9_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_10_);fill:#fff" d="M190.5209 279.463c-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7446-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9941 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C194.239 280.164 192.4279 279.463 190.5209 279.463z"/><path style="opacity:.13;clip-path:url(#SVGID_10_);fill:#020202" d="M190.5209 279.463c-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7446-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9941 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C194.239 280.164 192.4279 279.463 190.5209 279.463z"/></g><g><defs><path id="SVGID_11_" d="M189.5403 264.6153c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8065-21.8612-21.8613.0-6.0285 2.4516-11.492 6.4116-15.452C178.0482 267.0669 183.5117 264.6153 189.5403 264.6153zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.6366 290.6783 197.5344 288.6792 197.5344 286.4765z"/></defs><clipPath id="SVGID_12_"><use xlink:href="#SVGID_11_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_12_);fill:#56a55c" d="M173.11 270.0439c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8613 12.0547.0024 21.8636-9.797 21.8613-21.8613.0024-3.8474-1.0151-7.6326-2.9353-10.9462-3.8977-6.7325-11.1497-10.9151-18.926-10.9151C182.5311 263.6346 177.0676 266.0863 173.11 270.0439z"/></g></g><rect x="199.3456" y="279.5436" style="fill:#56a55c" width="122.6266" height="13.8671"/></g><g><g><path style="fill:#f1bc42" d="M189.0874 318.7208l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3305-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.025 2.454-11.4897 6.4116-15.4472C177.5953 321.1724 183.0601 318.7196 189.0874 318.7208zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403S197.0816 342.7176 197.0804 340.5784z"/><path style="opacity:.3;fill:#fff" d="M189.0898 318.7214c7.7763.0 15.0283 4.1826 18.926 10.915 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8612-12.0547.0024-21.8636-9.8065-21.8612-21.8612.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 321.173 183.0612 318.7214 189.0898 318.7214zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 344.7844 197.0839 342.7853 197.0839 340.5826z"/><g><defs><path id="SVGID_13_" d="M194.7376 346.2329c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.999 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 342.7853 196.1861 344.7844 194.7376 346.2329z"/></defs><clipPath id="SVGID_14_"><use xlink:href="#SVGID_13_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_14_);fill:#fff" d="M190.0704 333.5691c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0834 6.1218 2.8788C193.7885 334.2701 191.9774 333.5691 190.0704 333.5691z"/><path style="opacity:.13;clip-path:url(#SVGID_14_);fill:#020202" d="M190.0704 333.5691c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0834 6.1218 2.8788C193.7885 334.2701 191.9774 333.5691 190.0704 333.5691z"/></g><g><defs><path id="SVGID_15_" d="M189.0898 318.7214c7.7763.0 15.0283 4.1826 18.926 10.915 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8612-12.0547.0024-21.8636-9.8065-21.8612-21.8612.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 321.173 183.0612 318.7214 189.0898 318.7214zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 344.7844 197.0839 342.7853 197.0839 340.5826z"/></defs><clipPath id="SVGID_16_"><use xlink:href="#SVGID_15_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_16_);fill:#f1bc42" d="M172.6595 324.15c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8612 12.0547.0024 21.8636-9.797 21.8613-21.8612.0024-3.8474-1.0151-7.6327-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 317.7407 176.6171 320.1924 172.6595 324.15z"/></g></g><rect x="198.8952" y="333.6497" style="fill:#f1bc42" width="122.6266" height="13.8671"/></g></g></svg></span><span class="navbar-brand__name">NewLang</span></a> - <div class="td-navbar-nav-scroll ms-md-auto" id="main_navbar"> - <ul class="navbar-nav"> - <li class="nav-item"> - <a class="nav-link" href="/docs/"><span>Documentation</span></a> - </li> - <li class="nav-item"> - <a class="nav-link" href="/playground/"><span>Playground</span></a> - </li> - <li class="nav-item"> - <a class="nav-link active" href="/blog/"><span>Articles</span></a> - </li> - <li class="nav-item dropdown d-none d-lg-block"> - <div class="dropdown"> - <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">English</a> - <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/ru/blog/prog-styles-same-time/">Русский</a></li> - </ul> -</div></li> - </ul> - </div> - <div class="d-none d-lg-block"> - <div class="td-search td-search--offline"> - <div class="td-search__icon"></div> - <input - type="search" - class="td-search__input form-control" - placeholder="Search this site…" - aria-label="Search this site…" - autocomplete="off" - - data-offline-search-index-json-src="/offline-search-index.json" - data-offline-search-base-href="/" - data-offline-search-max-results="10" - > -</div> - </div> -</div> -</nav> - </header> - <div class="container-fluid td-outer"> - <div class="td-main"> - <div class="row flex-xl-nowrap"> - <aside class="col-12 col-md-3 col-xl-2 td-sidebar d-print-none"> - <div id="td-sidebar-menu" class="td-sidebar__inner"> - <form class="td-sidebar__search d-flex align-items-center"> - <div class="td-search td-search--offline"> - <div class="td-search__icon"></div> - <input - type="search" - class="td-search__input form-control" - placeholder="Search this site…" - aria-label="Search this site…" - autocomplete="off" - - data-offline-search-index-json-src="/offline-search-index.json" - data-offline-search-base-href="/" - data-offline-search-max-results="10" - > -</div> - <button class="btn btn-link td-sidebar__toggle d-md-none p-0 ms-3 fas fa-bars" type="button" data-bs-toggle="collapse" data-bs-target="#td-section-nav" aria-controls="td-section-nav" aria-expanded="false" aria-label="Toggle section navigation"> - </button> - </form> - <nav class="td-sidebar-nav collapse" id="td-section-nav"> - <div class="td-sidebar-nav__section nav-item dropdown d-block d-lg-none"> - <div class="dropdown"> - <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">English</a> - <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/ru/blog/prog-styles-same-time/">Русский</a></li> - </ul> -</div> - </div> - <ul class="td-sidebar-nav__section pe-md-3 ul-0"> - <li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child active-path" id="m-blog-li"> - <a href="/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-blog"><span class="">Articles</span></a> - <ul class="ul-1"> - <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v04-li"> - <a href="/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogparser-nuances-li"> - <a href="/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogdsl-domain-specific-language-implementation-with-macros-li"> - <a href="/blog/dsl-domain-specific-language-implementation-with-macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogdsl-domain-specific-language-implementation-with-macros"><span class="">DSL (domain-specific language) implementation with macros</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v03-li"> - <a href="/blog/release-v0.3/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v03"><span class="">Релиз языка программрования NewLang 0.3</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v02-li"> - <a href="/blog/release-v0.2/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v02"><span class="">Релиз языка программрования NewLang 0.2</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v01-li"> - <a href="/blog/release-v0.1/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v01"><span class="">Релиз языка программрования NewLang</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blognewlang-li"> - <a href="/blog/newlang/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blognewlang"><span class="">Новый язык программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child active-path" id="m-blogprog-styles-same-time-li"> - <a href="/blog/prog-styles-same-time/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__page" id="m-blogprog-styles-same-time"><span class="td-sidebar-nav-active-item">Можно ли использовать декларативный и императивный стили написания программ одновременно?</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogunusual-prog-li"> - <a href="/blog/unusual-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogunusual-prog"><span class="">Необычная концепция синтаксиса языка программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogcomplex-prog-li"> - <a href="/blog/complex-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogcomplex-prog"><span class="">Простое сложное программирование</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloglang-final-li"> - <a href="/blog/lang-final/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloglang-final"><span class="">Какая «идеальная» цель развития у языков программирования?</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloglogic-prog-li"> - <a href="/blog/logic-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloglogic-prog"><span class="">Проблема логических языков программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloginter-prog-li"> - <a href="/blog/inter-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloginter-prog"><span class="">Интернациональное программирование на естественных языках</span></a> -</li> - </ul> -</li> - </ul> - </nav> -</div> - - </aside> - <aside class="d-none d-xl-block col-xl-2 td-sidebar-toc d-print-none"> - <div class="td-page-meta ms-2 pb-1 pt-2 mb-0"> -<a id="print" href="/blog/_print/"><i class="fa-solid fa-print fa-fw"></i> Print entire section</a> - -</div> - - <div class="td-toc"> - <nav id="TableOfContents"> - <ul> - <li><a href="#что-такое-декларативное-программирование">Что такое &ldquo;Декларативное программирование&rdquo;?</a></li> - <li><a href="#а-что-отличает-декларативные-языки-программирования-от-императивных">А что отличает декларативные языки программирования от императивных?</a></li> - <li><a href="#что-мешает-совместить-императивный-и-декларативный-стили-написания-в-рамках-одной-программы">Что мешает совместить императивный и декларативный стили написания в рамках одной программы?</a></li> - <li><a href="#проверка-гипотезы-в-новом-языке-программирования">Проверка гипотезы в новом языке программирования</a> - <ul> - <li><a href="#зы">З.Ы.</a></li> - <li><a href="#ззы">З.З.Ы</a></li> - </ul> - </li> - </ul> -</nav> - </div> - - <div class="taxonomy taxonomy-terms-cloud taxo-tags"> - <h5 class="taxonomy-title">Tag Cloud</h5> - <ul class="taxonomy-terms"> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B/" data-taxonomy-term="%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B"><span class="taxonomy-label">Итераторы</span><span class="taxonomy-count">1</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8/" data-taxonomy-term="%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8"><span class="taxonomy-label">Коллекции</span><span class="taxonomy-count">4</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%BE%D0%BE%D0%BF/" data-taxonomy-term="%D0%BE%D0%BE%D0%BF"><span class="taxonomy-label">ООП</span><span class="taxonomy-count">3</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B/" data-taxonomy-term="%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B"><span class="taxonomy-label">Системые Типы</span><span class="taxonomy-count">1</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85/" data-taxonomy-term="%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85"><span class="taxonomy-label">Типы Данных</span><span class="taxonomy-count">8</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8/" data-taxonomy-term="%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8"><span class="taxonomy-label">Функции</span><span class="taxonomy-count">1</span></a></li> - </ul> - </div> - - - </aside> - <main class="col-12 col-md-9 col-xl-8 ps-md-5 pe-md-4" role="main"> - <a class="td-rss-button" title="RSS" href="/blog/index.xml" target="_blank" rel="noopener"> - <i class="fa-solid fa-rss" aria-hidden="true"></i> - </a> - -<div class="td-content"> - <h1>Можно ли использовать декларативный и императивный стили написания программ одновременно?</h1> - - <div class="td-byline mb-4"> - - <time datetime="2021-07-26" class="text-muted">Monday, July 26, 2021</time> - </div> - <header class="article-meta"> - - </header> - <p><img alt="КДПВ" src="/blog/matrix.jpeg"></p> - - -<div class="pageinfo pageinfo-primary"> -<p>Внимание!!!</p> -<p>Данная статья содержит описание синтаксиса NewLnag предыдущей версии.</p> -<p>Актуальную версию синтаксиса языка можно посмотреть <a href="/docs/">тут</a>.</p> - -</div> - -<p>При разработке своего собственного языка программирования автор должен определиться, какими свойствами его язык должен обладать, -ведь в конечном итоге именно это и будет определять назначение языка и особенности его использования. -Причем некоторые свойства настолько сильно влияют на итоговую концепцию языка и его синтаксис, -что впоследствии их изменение невозможно в принципе, либо новый синтаксис получается очень запутанным и непонятным. -Наверно из-за этого многие свойства языков программирования рассматриваются и изучаются как взаимоисключающие.</p> -<p>До недавнего времени я считал, что императивная и декларативная парадигмы написания программ являются антагонистами и взаимоисключающими понятиями. -Ведь выбор стиля написания кода, изначально определяется автором языка еще на стадии его проектирования и оказывает влияние на все последующие аспекты.</p> -<p>Но сейчас я думаю, что это не верно. Императивный и декларативный стили программирования не являются взаимоисключающими, -а писать программы только в одной из указанных парадигм подталкивают правила синтаксиса, реализованные в языке!</p> -<p>Другими словами, использовать только императивную или только декларативную парадигмы разработчик вынужден не потому, что он не умеет или не хочет писать код по другому, а из-за того, -что все более-менее мейнстримные языки программирования ориентированы на использование только одной парадигмы. -И выбор только одной парадигмы написания кода, это ограничение, которое навязано программистам создателями языка. -Ведь если они изначально ориентировались только на одну концепцию разработки кода, то и разрабатывали синтаксис языка в соответствии с этой парадигмой.</p> -<p>Данная статья — размышление о совместимости декларативной и императивной парадигм программирования и возможности их одновременного использования в рамках одного языка программирования одновременно.</p> -<h2 id="что-такое-декларативное-программирование">Что такое &ldquo;Декларативное программирование&rdquo;?<a class="td-heading-self-link" href="#%d1%87%d1%82%d0%be-%d1%82%d0%b0%d0%ba%d0%be%d0%b5-%d0%b4%d0%b5%d0%ba%d0%bb%d0%b0%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h2> -<p>Вначале мне захотелось разобраться, а существуют ли чисто декларативные языки программирования? -Такие, которые могут полностью обходятся без императивных конструкций?</p> -<p>Но чуть не споткнулся уже в самом начале, т.к. даже само определение «декларативное программировании», в вики описывается <a href="https://ru.wikipedia.org/wiki/%D0%94%D0%B5%D0%BA%D0%BB%D0%B0%D1%80%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5">следующим образом</a>:</p> -<blockquote> -<p>Декларати́вное программи́рование — парадигма программирования, в которой задаётся спецификация решения задачи, то есть описывается, что представляет собой проблема и ожидаемый результат. Противоположностью декларативного является императивное программирование, описывающее на том или ином уровне детализации, как решить задачу и представить результат.</p> -</blockquote> -<p>Уже в изначальном определении закладывается противопоставление парадигм, а дальше идут рассуждения о «направлении» программирования. -И хоть вики сама и не является авторитетным источником информации, но даже такая заготовка статьи смогла показать направление поиска ответов на первый поставленный вопрос.</p> -<p>И заставил задуматься один абзац в конце статьи следующего содержания:</p> -<blockquote> -<p>«Чисто декларативные» компьютерные языки зачастую неполны по Тьюрингу — так как теоретически не всегда возможно порождение исполняемого кода по декларативному описанию. -Это иногда приводит к спорам о корректности термина «декларативное программирование» (менее спорным является «декларативное описание решения» или, что то же самое, «декларативное описание задачи»).</p> -</blockquote> -<p>Судя по наличию такой оговорки, ставится под сомнение наличие «чисто декларативных» языков. -И как только пришлось задуматься над это мыслью, то сразу стало очевидным, что какой бы декларативный язык программирования не существовал, -то в нем должна быть как минимум одна императивная конструкция, которая будет запускать поиск решения! -Ведь любой синоним слова «выполнить» или «запустить» по определению будет императивом!</p> -<p>Например в языке Prolog, который обычно и приводят в качестве примера декларативного языка программирования, &ldquo;замаскированным&rdquo; императивным оператором является знак вопроса. -Он кажется естественным и логичным, как же без него? Но по своей сути, это императивная конструкция!</p> -<p>Тоже самое касается и языка SQL. Он тоже как бы декларативный, но неожиданно все его команды являются императивными по сути. <em>SELECT</em>, <em>CREATE</em>, <em>ALTER</em>, <em>DROP</em>, <em>INSERT</em>, <em>UPDATE</em>, <em>DELETE</em> и т. д., а декларативными являются только описания условий их выполнения!</p> -<p>В результате, у меня так и не получилось найти чисто-декларативный язык программирования без императивных операторов (может быть, Вики права и такого языка программирования и вовсе не существует?).</p> -<h2 id="а-что-отличает-декларативные-языки-программирования-от-императивных">А что отличает декларативные языки программирования от императивных?<a class="td-heading-self-link" href="#%d0%b0-%d1%87%d1%82%d0%be-%d0%be%d1%82%d0%bb%d0%b8%d1%87%d0%b0%d0%b5%d1%82-%d0%b4%d0%b5%d0%ba%d0%bb%d0%b0%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b5-%d1%8f%d0%b7%d1%8b%d0%ba%d0%b8-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%be%d1%82-%d0%b8%d0%bc%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d1%85" aria-label="Heading self-link"></a></h2> -<p>Согласно определению, декларативными языками программирования их называют из-за возможности записать некие условия в декларативном стиле. -Но кроме этого, в декларативных языках как правило присутствует и некий внутренний механизм поиска решений. -Подобный &ldquo;вычислитель&rdquo; есть и в SQL и Prolog и во многих других декларативных языках.</p> -<p>Интересно, а является ли внутренняя система поиска решений обязательным признаком декларативного стиля программирования или это только особенность конкретного языка программирования, которая не зависит от декларативного стиля написания кода?</p> -<p>Чтобы проверить данные предположения, можно было попробовать написать классическую декларативную программу на императивном языке, у которого отсутствует внутренний механизм поиска решений.</p> -<p>А заодно, таким образом можно будет и изучить вопрос, получится ли написать программу в декларативном стиле используя обычный императивный язык программирования?</p> -<p>Для примера, решил попробовать повторить уже классическую программу в декларативном стиле на Прологе.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span> <span style="color:#000">parent</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Tom&#34;</span><span style="color:#000;font-weight:bold">,</span><span style="color:#4e9a06">&#34;Jake&#34;</span><span style="color:#000;font-weight:bold">).</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">parent</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Janna&#34;</span><span style="color:#000;font-weight:bold">,</span><span style="color:#4e9a06">&#34;Jake&#34;</span><span style="color:#000;font-weight:bold">).</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">parent</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Tom&#34;</span><span style="color:#000;font-weight:bold">,</span><span style="color:#4e9a06">&#34;Tim&#34;</span><span style="color:#000;font-weight:bold">).</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">male</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Tom&#34;</span><span style="color:#000;font-weight:bold">).</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">male</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Tim&#34;</span><span style="color:#000;font-weight:bold">).</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">male</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Jake&#34;</span><span style="color:#000;font-weight:bold">).</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">female</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Janna&#34;</span><span style="color:#000;font-weight:bold">).</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#000">brother</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">X</span><span style="color:#000;font-weight:bold">,</span><span style="color:#000">Y</span><span style="color:#000;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">:-</span><span style="color:#000">parent</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">Z</span><span style="color:#000;font-weight:bold">,</span><span style="color:#000">X</span><span style="color:#000;font-weight:bold">),</span><span style="color:#000">parent</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">Z</span><span style="color:#000;font-weight:bold">,</span><span style="color:#000">Y</span><span style="color:#000;font-weight:bold">),</span><span style="color:#000">male</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">X</span><span style="color:#000;font-weight:bold">),</span><span style="color:#000">male</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">Y</span><span style="color:#000;font-weight:bold">),</span><span style="color:#000">X</span><span style="color:#a40000">\</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#000">Y</span><span style="color:#000;font-weight:bold">.</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">?</span> <span style="color:#000">brother</span> -</span></span></code></pre></div><p>Получилась вот такая функционально - эквивалентная программа на С++, которая максимально приближена по стилю к декларативному прототипу:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">enum</span> <span style="color:#000">sex_</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">male</span><span style="color:#000;font-weight:bold">,</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">female</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">struct</span> <span style="color:#000">human</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">typedef</span> <span style="color:#000">std</span><span style="color:#ce5c00;font-weight:bold">::</span><span style="color:#000">vector</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">human</span> <span style="color:#ce5c00;font-weight:bold">*&gt;</span> <span style="color:#000">parent_</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">struct</span> <span style="color:#000">human</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">const</span> <span style="color:#204a87;font-weight:bold">char</span> <span style="color:#ce5c00;font-weight:bold">*</span><span style="color:#000">name</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">sex_</span> <span style="color:#000">sex</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">parent_</span> <span style="color:#000">parent</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#000">human</span> <span style="color:#000">Tom</span><span style="color:#000;font-weight:bold">{</span><span style="color:#4e9a06">&#34;Tom&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">male</span><span style="color:#000;font-weight:bold">,{}};</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">human</span> <span style="color:#000">Janna</span><span style="color:#000;font-weight:bold">{</span><span style="color:#4e9a06">&#34;Janna&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">female</span><span style="color:#000;font-weight:bold">,{}};</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">human</span> <span style="color:#000">Jake</span><span style="color:#000;font-weight:bold">{</span><span style="color:#4e9a06">&#34;Jake&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">male</span><span style="color:#000;font-weight:bold">,{</span><span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">Tom</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">Janna</span><span style="color:#000;font-weight:bold">}};</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">human</span> <span style="color:#000">Tim</span><span style="color:#000;font-weight:bold">{</span><span style="color:#4e9a06">&#34;Tim&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">male</span><span style="color:#000;font-weight:bold">,{</span><span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">Tom</span><span style="color:#000;font-weight:bold">}};</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#000">std</span><span style="color:#ce5c00;font-weight:bold">::</span><span style="color:#000">vector</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#000">human</span> <span style="color:#ce5c00;font-weight:bold">*&gt;</span> <span style="color:#000">humans</span><span style="color:#000;font-weight:bold">{</span><span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">Tom</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">Janna</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">Jake</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">Tim</span><span style="color:#000;font-weight:bold">};</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">auto</span> <span style="color:#000">brothers</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000;font-weight:bold">[](</span><span style="color:#000">human</span> <span style="color:#ce5c00;font-weight:bold">*</span> <span style="color:#000">a</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">human</span> <span style="color:#ce5c00;font-weight:bold">*</span> <span style="color:#000">b</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">auto</span> <span style="color:#000">intersec</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000;font-weight:bold">[](</span><span style="color:#000">parent_</span> <span style="color:#ce5c00;font-weight:bold">&amp;</span><span style="color:#000">a</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">parent_</span> <span style="color:#ce5c00;font-weight:bold">&amp;</span> <span style="color:#000">b</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">for</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">auto</span> <span style="color:#f57900">elem_a</span> <span style="color:#000;font-weight:bold">:</span> <span style="color:#000">a</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">for</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">auto</span> <span style="color:#f57900">elem_b</span> <span style="color:#000;font-weight:bold">:</span> <span style="color:#000">b</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">if</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">elem_a</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#000">elem_b</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#000">elem_a</span> <span style="color:#ce5c00;font-weight:bold">==</span> <span style="color:#000">elem_b</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#204a87">true</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#204a87">false</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">return</span> <span style="color:#000">a</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#000">b</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#000">a</span> <span style="color:#ce5c00;font-weight:bold">!=</span> <span style="color:#000">b</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#000">a</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">sex</span> <span style="color:#ce5c00;font-weight:bold">==</span> <span style="color:#000">male</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#000">b</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">sex</span> <span style="color:#ce5c00;font-weight:bold">==</span> <span style="color:#000">male</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#000">intersec</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">a</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">parent</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">b</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">parent</span><span style="color:#000;font-weight:bold">));</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">for</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">auto</span> <span style="color:#f57900">a</span> <span style="color:#000;font-weight:bold">:</span> <span style="color:#000">humans</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">for</span> <span style="color:#000;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">auto</span> <span style="color:#f57900">b</span> <span style="color:#000;font-weight:bold">:</span> <span style="color:#000">humans</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">if</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">brothers</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">a</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">b</span><span style="color:#000;font-weight:bold">))</span> <span style="color:#000;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#000">std</span><span style="color:#ce5c00;font-weight:bold">::</span><span style="color:#000">cout</span> <span style="color:#ce5c00;font-weight:bold">&lt;&lt;</span> <span style="color:#000">a</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">name</span> <span style="color:#ce5c00;font-weight:bold">&lt;&lt;</span> <span style="color:#4e9a06">&#34; and &#34;</span> <span style="color:#ce5c00;font-weight:bold">&lt;&lt;</span> <span style="color:#000">b</span><span style="color:#ce5c00;font-weight:bold">-&gt;</span><span style="color:#000">name</span> <span style="color:#ce5c00;font-weight:bold">&lt;&lt;</span> <span style="color:#4e9a06">&#34;</span><span style="color:#4e9a06">\n</span><span style="color:#4e9a06">&#34;</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> -</span></span></code></pre></div><p>Конечно, текст на С++ получается значительно многословней, чем вариант на Прологе, но по сути, это почти дословное повторение декларативного стиля написания кода. -Тем более, не стоит забывать про рассуждения в начале статьи об изначальном выборе концепции при создании языка -и &ldquo;принуждении&rdquo; программистов пользоваться только одной, изначально выбранной парадигмой разработки.</p> -<p><strong>Таким образом, можно с высокой долей уверенности утверждать, что теоретически можно писать код одновременно в разных стилях.</strong></p> -<p>Но что тогда мешает в рамках одного языка программирования писать с использованием императивного и декларативного стиля? -Неужели только убежденность создателей языков в том, что императивный и декларативный стили программирования являются взаимоисключающими? -И только из-за этого получаются языки программирования, синтаксис которых подходит для использования одной единственной парадигмы?</p> -<p><em>Но если это так, то что мешает попробовать разработать синтаксис языка программирования, в котором можно было бы использовать сразу императивный и декларативный стили программирования одновременно?</em></p> -<h2 id="что-мешает-совместить-императивный-и-декларативный-стили-написания-в-рамках-одной-программы">Что мешает совместить императивный и декларативный стили написания в рамках одной программы?<a class="td-heading-self-link" href="#%d1%87%d1%82%d0%be-%d0%bc%d0%b5%d1%88%d0%b0%d0%b5%d1%82-%d1%81%d0%be%d0%b2%d0%bc%d0%b5%d1%81%d1%82%d0%b8%d1%82%d1%8c-%d0%b8%d0%bc%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b9-%d0%b8-%d0%b4%d0%b5%d0%ba%d0%bb%d0%b0%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b9-%d1%81%d1%82%d0%b8%d0%bb%d0%b8-%d0%bd%d0%b0%d0%bf%d0%b8%d1%81%d0%b0%d0%bd%d0%b8%d1%8f-%d0%b2-%d1%80%d0%b0%d0%bc%d0%ba%d0%b0%d1%85-%d0%be%d0%b4%d0%bd%d0%be%d0%b9-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d1%8b" aria-label="Heading self-link"></a></h2> -<p>В любой компьютерной программе всегда существует разделение кода на описание данных и на языковые конструкции для их обработки, т.е. фактически это разделение <strong>на данные</strong> и <strong>на функции</strong>. -Мне кажется, что основная сложность, которая не дает использовать разные стили программирования в рамках одного языка, это необходимость разделять описываемые сущности на «данные» и «управляющие конструкции». -Ведь это свойство (необходимость разделения сущностей на &ldquo;данные&rdquo; и &ldquo;функции&rdquo;), является неотъемлемой частью любого языка программирования.</p> -<p>Это не удивительно, ведь на заре становления ИТ индустрии, создатели первых языков программирования ориентировались исключительно на императивный стиль, потому что назначением любого компилятора было - преобразовать исходный текст программы в машинные инструкции. И на примерах модульного, структурного и объекто-ориентированного подходах показана и доказана необходимость оформления исполняемого кода в выделенные процедуры с последующей их группировкой в модули и классы.</p> -<p>А декларативный стиль написания программ стал появляться только после создания высокоуровневых языков программирования. -И основная цель создания данных языков сместилась на поиск решения конечного пользователя, а не на упрощение генерации бинарных файлов с машинными инструкциями. -Если внимательно посмотреть на приведенные выше примеры кода, то можно заметить, что в них определения данных и операторы для их обработки идут вперемешку, (для примера на С++ это определение лямбд функции), что кардинально отличается от императивного подхода.</p> -<p>Так может быть, основная особенность декларативного стиля как раз и заключается в том, что в нем не разделяются «данные» и «действия над данными»? -Или как вариант, можно не указывать выполняемые действия над данными вовсе (как в некоторых SQL конструкциях)?</p> -<p>Может быть как раз именно эта особенность (возможность последовательной записи программного кода в соответствии с собственными логическими рассуждениями, -в которых могут перемежаться «данные» и «функции», как это происходит при человеческом мыслительном процессе), -не дает в полной мере реализовать возможность совмещения императивных и декларативных стилей программирования?</p> -<p><em>И если это так, тогда можно попробовать разработать такой синтаксис, который будет поддерживать определение как данных, так и декларацию функций в рамках единого потока языковых конструкций!</em></p> -<h2 id="проверка-гипотезы-в-новом-языке-программирования">Проверка гипотезы в новом языке программирования<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b0-%d0%b3%d0%b8%d0%bf%d0%be%d1%82%d0%b5%d0%b7%d1%8b-%d0%b2-%d0%bd%d0%be%d0%b2%d0%be%d0%bc-%d1%8f%d0%b7%d1%8b%d0%ba%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h2> -<p>Для поверки данного предположения, я решил добавить в свой <a href="/blog/2021/05/24/%D0%BD%D0%B5%D0%BE%D0%B1%D1%8B%D1%87%D0%BD%D0%B0%D1%8F-%D0%BA%D0%BE%D0%BD%D1%86%D0%B5%D0%BF%D1%86%D0%B8%D1%8F-%D1%81%D0%B8%D0%BD%D1%82%D0%B0%D0%BA%D1%81%D0%B8%D1%81%D0%B0-%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0-%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F/">новый язык программирования</a> -(синтаксис которого допускает определение функций в одном потоке с описанием обрабатываемых данных), недостающие алгоритмические конструкции, которые позволяли бы реализовать императивный стиль программирования, -несмотря на изначальную ориентацию только на декларативную парадигму.</p> -<p>Правда с учетом изначальных ограничений синтаксиса нового языка (запрет на применение операторов в виде зарезервированных ключевых слов), -в качестве оператора проверки условия была выбрана синтаксическая конструкция, соответствующая по смыслу термину «следует», -т.е. тире и угловая скобка «<strong>-&gt;</strong>».</p> -<p>В результате, условный оператор получился практически математический, который легко объединяется в последовательности для реализации проверки множественных условий вида «else if». -А для объединения сразу нескольких логического операторов между собой и для отделения их от последующего действия, операторы проверки условия можно заключать в круглые скобки.</p> -<p>В общем случае условный оператор в новом языке программирования имеет вид:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span> <span style="color:#a40000">условие</span> <span style="color:#ce5c00;font-weight:bold">-&gt;</span> <span style="color:#a40000">действие</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#a40000">или</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">условие</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">-&gt;</span> <span style="color:#000;font-weight:bold">{</span><span style="color:#a40000">действие</span><span style="color:#000;font-weight:bold">};</span> -</span></span><span style="display:flex;"><span> <span style="color:#a40000">или</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">условие</span><span style="color:#0000cf;font-weight:bold">1</span> <span style="color:#ce5c00;font-weight:bold">||</span> <span style="color:#a40000">условие</span><span style="color:#0000cf;font-weight:bold">2</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">-&gt;</span> <span style="color:#000;font-weight:bold">{</span><span style="color:#a40000">действие</span><span style="color:#000;font-weight:bold">}</span> <span style="color:#ce5c00;font-weight:bold">-&gt;</span> <span style="color:#000;font-weight:bold">{</span><span style="color:#a40000">действие</span> <span style="color:#a40000">иначе</span><span style="color:#000;font-weight:bold">};</span> -</span></span></code></pre></div><p>Или расширенный вариант, для наглядности записанный с отступами:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">условие</span><span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">-&gt;</span> <span style="color:#000;font-weight:bold">{</span><span style="color:#a40000">действие</span><span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">условие</span><span style="color:#0000cf;font-weight:bold">2</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">-&gt;</span> <span style="color:#000;font-weight:bold">{</span><span style="color:#a40000">действие</span><span style="color:#0000cf;font-weight:bold">2</span><span style="color:#000;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">условие</span><span style="color:#0000cf;font-weight:bold">3</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">-&gt;</span> <span style="color:#000;font-weight:bold">{</span><span style="color:#a40000">действие</span><span style="color:#0000cf;font-weight:bold">3</span><span style="color:#000;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">-&gt;</span> <span style="color:#000;font-weight:bold">{</span><span style="color:#a40000">действие</span><span style="color:#000">_иначе</span><span style="color:#000;font-weight:bold">};</span> -</span></span></code></pre></div><p>Тогда и операторы циклов можно будет записать практически аналогично, только выбрав в качестве оператора, не оператор следования, -а следование с возвратом (раз уж нужно указывать циклическое действие).</p> -<p>Цикл пока:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">условие</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">&lt;-&gt;</span> <span style="color:#000;font-weight:bold">{</span><span style="color:#a40000">тело</span> <span style="color:#a40000">цикла</span><span style="color:#000;font-weight:bold">};</span> -</span></span></code></pre></div><p>счетный цикл для работы с итератором:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">счетчик</span><span style="color:#000">_или_данные</span><span style="color:#ce5c00;font-weight:bold">!</span><span style="color:#000;font-weight:bold">)</span><span style="color:#ce5c00;font-weight:bold">?</span> <span style="color:#ce5c00;font-weight:bold">&lt;-&gt;</span> <span style="color:#000;font-weight:bold">{</span><span style="color:#a40000">тело</span> <span style="color:#a40000">цикла</span><span style="color:#000;font-weight:bold">};</span> -</span></span></code></pre></div><p>В этом случае, решение тестового примера декларативной программы на Прологе можно будет легко оформить, как в императивном, так и в декларативном стилях одновременно!</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> м :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#4e9a06">&#34;муж.&#34;</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> ж :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#4e9a06">&#34;жен.&#34;</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> human @<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">пол</span><span style="color:#ce5c00;font-weight:bold">=</span>, <span style="color:#000">parent</span><span style="color:#ce5c00;font-weight:bold">=[</span>,<span style="color:#ce5c00;font-weight:bold">])</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Tom @<span style="color:#ce5c00;font-weight:bold">=</span> human<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">пол</span><span style="color:#ce5c00;font-weight:bold">=</span>м<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Janna @<span style="color:#ce5c00;font-weight:bold">=</span> human<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">пол</span><span style="color:#ce5c00;font-weight:bold">=</span>ж<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Jake @<span style="color:#ce5c00;font-weight:bold">=</span> human<span style="color:#ce5c00;font-weight:bold">(</span>м, <span style="color:#ce5c00;font-weight:bold">[</span><span style="color:#000;font-weight:bold">&amp;</span>Tom, <span style="color:#000;font-weight:bold">&amp;</span>Janna,<span style="color:#ce5c00;font-weight:bold">])</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Tim @<span style="color:#ce5c00;font-weight:bold">=</span> human<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">пол</span><span style="color:#ce5c00;font-weight:bold">=</span>м, <span style="color:#000">parent</span><span style="color:#ce5c00;font-weight:bold">=[</span><span style="color:#000;font-weight:bold">&amp;</span>Tom,<span style="color:#ce5c00;font-weight:bold">])</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> brother<span style="color:#ce5c00;font-weight:bold">(</span>h1, h2<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;=</span> <span style="color:#000">$h1</span>!<span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#000">$h2</span>, <span style="color:#000">$h1</span>.пол<span style="color:#ce5c00;font-weight:bold">==</span>м, <span style="color:#000">$h2</span>.пол<span style="color:#ce5c00;font-weight:bold">==</span>м, <span style="color:#000">$h1</span>.parent <span style="color:#000;font-weight:bold">&amp;</span> <span style="color:#000">$h2</span>.parent<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> // Оператор «<span style="color:#000;font-weight:bold">&amp;</span>» побитовое «И» для чисел или операция пересечения для множеств -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> // Запись алгоритма поиска решения в императивном стиле -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">h1</span><span style="color:#ce5c00;font-weight:bold">=</span>human!, <span style="color:#000">h2</span><span style="color:#ce5c00;font-weight:bold">=</span>human!<span style="color:#ce5c00;font-weight:bold">)</span>? &lt;-&gt; <span style="color:#ce5c00;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span>brother<span style="color:#ce5c00;font-weight:bold">(</span>h1, h2<span style="color:#ce5c00;font-weight:bold">))</span> -&gt; <span style="color:#ce5c00;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> @print<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">$h1</span>, <span style="color:#000">$h2</span>, «<span style="color:#4e9a06">\n</span>»<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span> -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> // Краткая запись алгоритма поиска решения в императивном стиле -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">h1</span><span style="color:#ce5c00;font-weight:bold">=</span>human!, <span style="color:#000">h2</span><span style="color:#ce5c00;font-weight:bold">=</span>human!<span style="color:#ce5c00;font-weight:bold">)</span>? &lt;-&gt; -</span></span><span style="display:flex;"><span> brother<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">$h1</span>, <span style="color:#000">$h2</span><span style="color:#ce5c00;font-weight:bold">)</span> -&gt; @print<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">$h1</span>, <span style="color:#000">$h2</span>, «<span style="color:#4e9a06">\n</span>»<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> // Запись поиска решения в декларативном стиле -</span></span><span style="display:flex;"><span> brother<span style="color:#ce5c00;font-weight:bold">(</span>human!, human!<span style="color:#ce5c00;font-weight:bold">)</span>?<span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>Примерно это и требовалось показать!</p> -<h3 id="зы">З.Ы.<a class="td-heading-self-link" href="#%d0%b7%d1%8b" aria-label="Heading self-link"></a></h3> -<p>Я почти закончил эксперименты с синтаксисом языка. -И теперь, после добавления в него недостающих алгоритмический конструкций (ветвления и циклов), планирую, -что следующая статья о новом языке программирования будет посвящена описанию его полного синтаксиса и публикации исходников прототипа компилятора для возможности поиграться на реальных примерах.</p> -<h3 id="ззы">З.З.Ы<a class="td-heading-self-link" href="#%d0%b7%d0%b7%d1%8b" aria-label="Heading self-link"></a></h3> -<p>В <a href="https://habr.com/company/timeweb/blog/569422/comments/#comment_23301086">комментариях @gbg</a> привел очень простой ответ на один из поднятых вопросов. -Причем в более элегантном виде и без написания кода!</p> -<blockquote> -<p>Ну и пять копеечек про ООП. Как ни странно:</p> -<ol> -<li>В нем таки есть декларативная часть, все эти pubic, private, virtual, etc</li> -<li>Эта декларативная часть, внезапно, элегантно позволяет реализовывать декомпозицию и управление сложностью.</li> -<li>При наличии перегрузок, можно поиграть в алгебраическое мышление, рассматривая взаимодействие двух объектов как бинарную операцию.</li> -</ol> -<p>Ух ты, ООП - это обкатанная практикой технология, которая совмещает декларатив с императивом и вроде позволяет освоившим ее вкусно кушать и мягко спать!</p> -</blockquote> -<p><a href="https://habr.com/companies/timeweb/articles/569422/">Ссылка на первую публикаци</a></p> - - <ul class="list-unstyled d-flex justify-content-between align-items-center mb-0 pt-5"> - <li> - <a href="/blog/unusual-prog/" aria-label="Previous - Необычная концепция синтаксиса языка программирования" class="btn btn-primary"><span class="me-1">←</span>Previous</a> - </li> - <li> - <a href="/blog/newlang/" aria-label="Next - Новый язык программирования" class="btn btn-primary">Next<span class="ms-1">→</span></a> - </li> -</ul> - - </div> - - - </main> - </div> - </div> - <footer class="td-footer row d-print-none"> - <div class="container-fluid"> - <div class="row mx-md-2"> - <div class="td-footer__left col-6 col-sm-4 order-sm-1"> - <ul class="td-footer__links-list"> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="User mailing list" aria-label="User mailing list"> - <a target="_blank" rel="noopener" href="mailto:mail@newlang.net" aria-label="User mailing list"> - <i class="fa fa-envelope"></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - -</ul> - - </div><div class="td-footer__right col-6 col-sm-4 order-sm-3"> - <ul class="td-footer__links-list"> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="GitHub" aria-label="GitHub"> - <a target="_blank" rel="noopener" href="https://github.com/rsashka/newlang" aria-label="GitHub"> - <i class="fab fa-github"></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - -</ul> - - </div><div class="td-footer__center col-12 col-sm-4 py-2 order-sm-2"> - <span class="td-footer__copyright">&copy; - 2024 - <span class="td-footer__authors">The NewLang Authors</span></span><span class="td-footer__all_rights_reserved">All Rights Reserved</span> - </div> - </div> - </div> -</footer> - - </div> - <script src="/js/main.js"></script> -<script defer src="/js/click-to-copy.js" crossorigin="anonymous"></script> -<script src='/js/tabpane-persist.js'></script> - - </body> -</html> \ No newline at end of file diff --git a/docs/blog/release-v0.1/index.html b/docs/blog/release-v0.1/index.html deleted file mode 100644 index b73d943d..00000000 --- a/docs/blog/release-v0.1/index.html +++ /dev/null @@ -1,727 +0,0 @@ -<!doctype html> -<html itemscope itemtype="http://schema.org/WebPage" lang="en" class="no-js"> - <head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script> - <meta charset="utf-8"> -<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> -<meta name="robots" content="noindex, nofollow"> - - -<link rel="shortcut icon" href="/favicons/favicon.ico" > -<link rel="apple-touch-icon" href="/favicons/apple-touch-icon-180x180.png" sizes="180x180"> -<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16"> -<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32"> -<link rel="icon" type="image/png" href="/favicons/android-36x36.png" sizes="36x36"> -<link rel="icon" type="image/png" href="/favicons/android-48x48.png" sizes="48x48"> -<link rel="icon" type="image/png" href="/favicons/android-72x72.png" sizes="72x72"> -<link rel="icon" type="image/png" href="/favicons/android-96x96.png" sizes="96x96"> -<link rel="icon" type="image/png" href="/favicons/android-144x144.png" sizes="144x144"> -<link rel="icon" type="image/png" href="/favicons/android-192x192.png" sizes="192x192"> - -<title>Релиз языка программрования NewLang | NewLang</title> -<meta name="description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -NewLang - это язык программирования высокого уровня, в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения. -Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка)."> -<meta property="og:title" content="Релиз языка программрования NewLang" /> -<meta property="og:description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -NewLang - это язык программирования высокого уровня, в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения. -Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка)." /> -<meta property="og:type" content="article" /> -<meta property="og:url" content="http://localhost:1313/blog/release-v0.1/" /><meta property="article:section" content="blog" /> -<meta property="article:published_time" content="2022-06-24T00:00:00+00:00" /> -<meta property="article:modified_time" content="2024-03-22T23:57:08+03:00" /><meta property="og:site_name" content="NewLang" /> -<meta itemprop="name" content="Релиз языка программрования NewLang"> -<meta itemprop="description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -NewLang - это язык программирования высокого уровня, в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения. -Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка)."><meta itemprop="datePublished" content="2022-06-24T00:00:00+00:00" /> -<meta itemprop="dateModified" content="2024-03-22T23:57:08+03:00" /> -<meta itemprop="wordCount" content="4962"> -<meta itemprop="keywords" content="" /><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Релиз языка программрования NewLang"/> -<meta name="twitter:description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -NewLang - это язык программирования высокого уровня, в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения. -Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка)."/> - - - - - -<link href="/scss/main.css" rel="stylesheet"> - -<script - src="https://code.jquery.com/jquery-3.6.3.min.js" - integrity="sha512-STof4xm1wgkfm7heWqFJVn58Hm3EtS31XFaagaa8VMReCXAkQnJZ+jEy8PCC/iT18dFy95WcExNHFTqLyp72eQ==" - crossorigin="anonymous"></script> -<script defer - src="https://unpkg.com/lunr@2.3.9/lunr.min.js" - integrity="sha384-203J0SNzyqHby3iU6hzvzltrWi/M41wOP5Gu+BiJMz5nwKykbkUx8Kp7iti0Lpli" - crossorigin="anonymous"></script> - - </head> - <body class="td-page td-blog"> - <header> - <nav class="td-navbar navbar-dark js-navbar-scroll"> -<div class="container-fluid flex-column flex-md-row"> - <a class="navbar-brand" href="/"><span class="navbar-brand__logo navbar-logo"><svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500" style="enable-background:new 0 0 500 500"><g><path style="fill:#fff" d="M116.8525 421.9722c-5.7041.0-10.3442-4.3127-10.3442-9.6129V88.183c0-5.3002 4.6401-9.6117 10.3442-9.6117H320.858c3.0347.0 9.3959.5498 11.7506 2.6302l.3545.3442 58.905 63.2912c2.3101 2.491 2.9202 8.4928 2.9202 11.3184v256.2039c0 5.3002-4.6407 9.6129-10.3436 9.6129H116.8525z"/><g><g><g><path style="fill:#767676" d="M384.4445 423.2066H116.852c-6.3839.0-11.5786-4.8658-11.5786-10.8474V88.1831c0-5.9804 5.1947-10.8461 11.5786-10.8461h204.0062c.377.0 9.2786.0329 12.568 2.9389l.3947.3833 58.9508 63.337c3.2135 3.4652 3.2514 11.7924 3.2514 12.1593v256.2036C396.0231 418.3408 390.8284 423.2066 384.4445 423.2066zM116.5079 411.9189c.0848.0278.1999.0531.3441.0531h267.5925c.1442.0.2581-.0253.3441-.0531V156.1556c-.0076-.9033-.3593-3.7347-.7034-5.0037l-57.6527-61.9416c-1.4651-.3176-4.4533-.6389-5.5742-.6389H116.852c-.143.0-.2594.024-.3441.0531V411.9189zm267.4533-261.149zM327.0321 89.371v.0013V89.371z"/></g></g></g><g><g><path style="fill:#5b7fc0" d="M189.0874 210.1754l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.025 2.454-11.4897 6.4116-15.4473C177.5953 212.627 183.0601 210.1742 189.0874 210.1754zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403S197.0816 234.1722 197.0804 232.033z"/><path style="opacity:.3;fill:#fff" d="M189.0898 210.176c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 212.6276 183.0612 210.176 189.0898 210.176zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 236.239 197.0839 234.2399 197.0839 232.0372z"/><g><defs><path id="SVGID_1_" d="M194.7376 237.6875c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.999 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 234.2399 196.1861 236.239 194.7376 237.6875z"/></defs><clipPath id="SVGID_2_"><use xlink:href="#SVGID_1_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_2_);fill:#fff" d="M190.0704 225.0237c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 225.7247 191.9774 225.0237 190.0704 225.0237z"/><path style="opacity:.13;clip-path:url(#SVGID_2_);fill:#020202" d="M190.0704 225.0237c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 225.7247 191.9774 225.0237 190.0704 225.0237z"/></g><g><defs><path id="SVGID_3_" d="M189.0898 210.176c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 212.6276 183.0612 210.176 189.0898 210.176zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 236.239 197.0839 234.2399 197.0839 232.0372z"/></defs><clipPath id="SVGID_4_"><use xlink:href="#SVGID_3_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_4_);fill:#5b7fc0" d="M172.6595 215.6045c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8612 12.0547.0024 21.8636-9.797 21.8613-21.8612.0024-3.8475-1.0151-7.6326-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 209.1953 176.6171 211.647 172.6595 215.6045z"/></g></g><rect x="198.8952" y="225.1043" style="fill:#5b7fc0" width="122.6266" height="13.8671"/></g><g><path style="fill:#d95140" d="M189.0874 155.7611l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.0249 2.454-11.4897 6.4116-15.4473C177.5953 158.2128 183.0601 155.7599 189.0874 155.7611zm7.993 21.8577c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403C196.2508 181.7667 197.0816 179.758 197.0804 177.6188z"/><path style="opacity:.3;fill:#fff" d="M189.0898 155.7617c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 158.2134 183.0612 155.7617 189.0898 155.7617zm7.9941 21.8613c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 181.8248 197.0839 179.8256 197.0839 177.623z"/><g><defs><path id="SVGID_5_" d="M194.7376 183.2733c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.9989 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 179.8256 196.1861 181.8248 194.7376 183.2733z"/></defs><clipPath id="SVGID_6_"><use xlink:href="#SVGID_5_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_6_);fill:#fff" d="M190.0704 170.6095c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 171.3104 191.9774 170.6095 190.0704 170.6095z"/><path style="opacity:.13;clip-path:url(#SVGID_6_);fill:#020202" d="M190.0704 170.6095c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 171.3104 191.9774 170.6095 190.0704 170.6095z"/></g><g><defs><path id="SVGID_7_" d="M189.0898 155.7617c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 158.2134 183.0612 155.7617 189.0898 155.7617zm7.9941 21.8613c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 181.8248 197.0839 179.8256 197.0839 177.623z"/></defs><clipPath id="SVGID_8_"><use xlink:href="#SVGID_7_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_8_);fill:#d95140" d="M172.6595 161.1903c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8613 12.0547.0024 21.8636-9.797 21.8613-21.8613.0024-3.8474-1.0151-7.6326-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 154.7811 176.6171 157.2327 172.6595 161.1903z"/></g><rect x="198.8952" y="170.69" style="fill:#d95140" width="122.6266" height="13.8671"/></g><g><g><path style="fill:#56a55c" d="M189.5379 264.6147l.0012-.0012c7.7751.0012 15.0294 4.1862 18.932 10.9235 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032-5.8394.0-11.3281-2.2733-15.458-6.4032-4.13-4.13-6.4032-9.6186-6.4056-15.4628.0012-6.0249 2.454-11.4897 6.4116-15.4472C178.0458 267.0663 183.5105 264.6135 189.5379 264.6147zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6538 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403C196.7013 290.6202 197.5321 288.6115 197.5309 286.4723z"/><path style="opacity:.3;fill:#fff" d="M189.5403 264.6153c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8065-21.8612-21.8613.0-6.0285 2.4516-11.492 6.4116-15.452C178.0482 267.0669 183.5117 264.6153 189.5403 264.6153zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.6366 290.6783 197.5344 288.6792 197.5344 286.4765z"/><g><defs><path id="SVGID_9_" d="M195.1881 292.1268c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.9989 7.9942-7.9941 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.5344 288.6792 196.6366 290.6783 195.1881 292.1268z"/></defs><clipPath id="SVGID_10_"><use xlink:href="#SVGID_9_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_10_);fill:#fff" d="M190.5209 279.463c-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7446-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9941 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C194.239 280.164 192.4279 279.463 190.5209 279.463z"/><path style="opacity:.13;clip-path:url(#SVGID_10_);fill:#020202" d="M190.5209 279.463c-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7446-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9941 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C194.239 280.164 192.4279 279.463 190.5209 279.463z"/></g><g><defs><path id="SVGID_11_" d="M189.5403 264.6153c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8065-21.8612-21.8613.0-6.0285 2.4516-11.492 6.4116-15.452C178.0482 267.0669 183.5117 264.6153 189.5403 264.6153zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.6366 290.6783 197.5344 288.6792 197.5344 286.4765z"/></defs><clipPath id="SVGID_12_"><use xlink:href="#SVGID_11_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_12_);fill:#56a55c" d="M173.11 270.0439c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8613 12.0547.0024 21.8636-9.797 21.8613-21.8613.0024-3.8474-1.0151-7.6326-2.9353-10.9462-3.8977-6.7325-11.1497-10.9151-18.926-10.9151C182.5311 263.6346 177.0676 266.0863 173.11 270.0439z"/></g></g><rect x="199.3456" y="279.5436" style="fill:#56a55c" width="122.6266" height="13.8671"/></g><g><g><path style="fill:#f1bc42" d="M189.0874 318.7208l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3305-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.025 2.454-11.4897 6.4116-15.4472C177.5953 321.1724 183.0601 318.7196 189.0874 318.7208zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403S197.0816 342.7176 197.0804 340.5784z"/><path style="opacity:.3;fill:#fff" d="M189.0898 318.7214c7.7763.0 15.0283 4.1826 18.926 10.915 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8612-12.0547.0024-21.8636-9.8065-21.8612-21.8612.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 321.173 183.0612 318.7214 189.0898 318.7214zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 344.7844 197.0839 342.7853 197.0839 340.5826z"/><g><defs><path id="SVGID_13_" d="M194.7376 346.2329c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.999 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 342.7853 196.1861 344.7844 194.7376 346.2329z"/></defs><clipPath id="SVGID_14_"><use xlink:href="#SVGID_13_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_14_);fill:#fff" d="M190.0704 333.5691c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0834 6.1218 2.8788C193.7885 334.2701 191.9774 333.5691 190.0704 333.5691z"/><path style="opacity:.13;clip-path:url(#SVGID_14_);fill:#020202" d="M190.0704 333.5691c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0834 6.1218 2.8788C193.7885 334.2701 191.9774 333.5691 190.0704 333.5691z"/></g><g><defs><path id="SVGID_15_" d="M189.0898 318.7214c7.7763.0 15.0283 4.1826 18.926 10.915 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8612-12.0547.0024-21.8636-9.8065-21.8612-21.8612.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 321.173 183.0612 318.7214 189.0898 318.7214zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 344.7844 197.0839 342.7853 197.0839 340.5826z"/></defs><clipPath id="SVGID_16_"><use xlink:href="#SVGID_15_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_16_);fill:#f1bc42" d="M172.6595 324.15c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8612 12.0547.0024 21.8636-9.797 21.8613-21.8612.0024-3.8474-1.0151-7.6327-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 317.7407 176.6171 320.1924 172.6595 324.15z"/></g></g><rect x="198.8952" y="333.6497" style="fill:#f1bc42" width="122.6266" height="13.8671"/></g></g></svg></span><span class="navbar-brand__name">NewLang</span></a> - <div class="td-navbar-nav-scroll ms-md-auto" id="main_navbar"> - <ul class="navbar-nav"> - <li class="nav-item"> - <a class="nav-link" href="/docs/"><span>Documentation</span></a> - </li> - <li class="nav-item"> - <a class="nav-link" href="/playground/"><span>Playground</span></a> - </li> - <li class="nav-item"> - <a class="nav-link active" href="/blog/"><span>Articles</span></a> - </li> - <li class="nav-item dropdown d-none d-lg-block"> - <div class="dropdown"> - <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">English</a> - <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/ru/blog/release-v0.1/">Русский</a></li> - </ul> -</div></li> - </ul> - </div> - <div class="d-none d-lg-block"> - <div class="td-search td-search--offline"> - <div class="td-search__icon"></div> - <input - type="search" - class="td-search__input form-control" - placeholder="Search this site…" - aria-label="Search this site…" - autocomplete="off" - - data-offline-search-index-json-src="/offline-search-index.json" - data-offline-search-base-href="/" - data-offline-search-max-results="10" - > -</div> - </div> -</div> -</nav> - </header> - <div class="container-fluid td-outer"> - <div class="td-main"> - <div class="row flex-xl-nowrap"> - <aside class="col-12 col-md-3 col-xl-2 td-sidebar d-print-none"> - <div id="td-sidebar-menu" class="td-sidebar__inner"> - <form class="td-sidebar__search d-flex align-items-center"> - <div class="td-search td-search--offline"> - <div class="td-search__icon"></div> - <input - type="search" - class="td-search__input form-control" - placeholder="Search this site…" - aria-label="Search this site…" - autocomplete="off" - - data-offline-search-index-json-src="/offline-search-index.json" - data-offline-search-base-href="/" - data-offline-search-max-results="10" - > -</div> - <button class="btn btn-link td-sidebar__toggle d-md-none p-0 ms-3 fas fa-bars" type="button" data-bs-toggle="collapse" data-bs-target="#td-section-nav" aria-controls="td-section-nav" aria-expanded="false" aria-label="Toggle section navigation"> - </button> - </form> - <nav class="td-sidebar-nav collapse" id="td-section-nav"> - <div class="td-sidebar-nav__section nav-item dropdown d-block d-lg-none"> - <div class="dropdown"> - <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">English</a> - <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/ru/blog/release-v0.1/">Русский</a></li> - </ul> -</div> - </div> - <ul class="td-sidebar-nav__section pe-md-3 ul-0"> - <li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child active-path" id="m-blog-li"> - <a href="/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-blog"><span class="">Articles</span></a> - <ul class="ul-1"> - <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v04-li"> - <a href="/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogparser-nuances-li"> - <a href="/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogdsl-domain-specific-language-implementation-with-macros-li"> - <a href="/blog/dsl-domain-specific-language-implementation-with-macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogdsl-domain-specific-language-implementation-with-macros"><span class="">DSL (domain-specific language) implementation with macros</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v03-li"> - <a href="/blog/release-v0.3/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v03"><span class="">Релиз языка программрования NewLang 0.3</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v02-li"> - <a href="/blog/release-v0.2/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v02"><span class="">Релиз языка программрования NewLang 0.2</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child active-path" id="m-blogrelease-v01-li"> - <a href="/blog/release-v0.1/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v01"><span class="td-sidebar-nav-active-item">Релиз языка программрования NewLang</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blognewlang-li"> - <a href="/blog/newlang/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blognewlang"><span class="">Новый язык программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogprog-styles-same-time-li"> - <a href="/blog/prog-styles-same-time/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogprog-styles-same-time"><span class="">Можно ли использовать декларативный и императивный стили написания программ одновременно?</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogunusual-prog-li"> - <a href="/blog/unusual-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogunusual-prog"><span class="">Необычная концепция синтаксиса языка программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogcomplex-prog-li"> - <a href="/blog/complex-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogcomplex-prog"><span class="">Простое сложное программирование</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloglang-final-li"> - <a href="/blog/lang-final/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloglang-final"><span class="">Какая «идеальная» цель развития у языков программирования?</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloglogic-prog-li"> - <a href="/blog/logic-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloglogic-prog"><span class="">Проблема логических языков программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloginter-prog-li"> - <a href="/blog/inter-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloginter-prog"><span class="">Интернациональное программирование на естественных языках</span></a> -</li> - </ul> -</li> - </ul> - </nav> -</div> - - </aside> - <aside class="d-none d-xl-block col-xl-2 td-sidebar-toc d-print-none"> - <div class="td-page-meta ms-2 pb-1 pt-2 mb-0"> -<a id="print" href="/blog/_print/"><i class="fa-solid fa-print fa-fw"></i> Print entire section</a> - -</div> - - <div class="td-toc"> - <nav id="TableOfContents"> - <ul> - <li> - <ul> - <li><a href="#использование-модификаторов-является-обязательным-только-в-двух-случаях">Использование модификаторов является обязательным только в двух случаях:</a></li> - </ul> - </li> - </ul> - - <ul> - <li><a href="#простые-типы">Простые типы</a> - <ul> - <li><a href="#арифметические-значения">Арифметические значения</a></li> - </ul> - </li> - <li><a href="#строки">Строки</a></li> - <li><a href="#системные">Системные</a> - <ul> - <li><a href="#pointer---указатель-на-системную-область-памяти">:Pointer - указатель на системную область памяти</a></li> - <li><a href="#plain---указатель-на-представление-данных-в-бинарном-виде">:Plain - указатель на представление данных в бинарном виде</a></li> - </ul> - </li> - <li><a href="#составные-типы-данных">Составные типы данных:</a> - <ul> - <li><a href="#словарь">Словарь</a></li> - <li><a href="#перечисление-структура-и-объединение">Перечисление, структура и объединение</a></li> - <li><a href="#классы">Классы</a></li> - </ul> - </li> - <li><a href="#функции">Функции</a> - <ul> - <li><a href="#обычная-функция">Обычная функция</a></li> - <li><a href="#чистые-функции">Чистые функции</a></li> - <li><a href="#простые-чистые-функции">Простые чистые функции</a></li> - </ul> - </li> - <li><a href="#специальные-типы-данных">Специальные типы данных:</a> - <ul> - <li><a href="#пусто-none">Пусто (:None)</a></li> - <li><a href="#диапазон-range">Диапазон (:Range)</a></li> - </ul> - </li> - <li><a href="#преобразование-типов">Преобразование типов</a> - <ul> - <li><a href="#явное-приведение-типов">Явное приведение типов</a></li> - </ul> - </li> - </ul> - - <ul> - <li><a href="#операторы">Операторы:</a></li> - <li><a href="#операторы-сравнения">Операторы сравнения:</a></li> - <li><a href="#проверки-типа-имени-класса-объекта">Проверки типа (имени класса объекта):</a></li> - <li><a href="#утиная-типизация">Утиная типизация</a></li> - </ul> - - <ul> - <li><a href="#условный-оператор">Условный оператор</a></li> - <li><a href="#оценка-выражения">Оценка выражения</a></li> - <li><a href="#операторы-циклов">Операторы циклов</a></li> - <li><a href="#операторы-прерывания-возврата">Операторы прерывания (возврата)</a></li> - <li><a href="#следование-блок-кодалямбда-функция">Следование (блок кода/лямбда функция)</a></li> - <li><a href="#стратегия-обработки-ошибок">Стратегия обработки ошибок</a> - <ul> - <li><a href="#подход-к-обработке-исключений-следующий">Подход к обработке исключений следующий:</a></li> - </ul> - </li> - <li><a href="#сборка-repl-из-исходников-пока-только-под-linux">Сборка REPL из исходников (пока только под Linux)</a> - <ul> - <li><a href="#подготовка-репозитория">Подготовка репозитория</a></li> - <li><a href="#собрать">Собрать</a></li> - </ul> - </li> - </ul> -</nav> - </div> - - <div class="taxonomy taxonomy-terms-cloud taxo-tags"> - <h5 class="taxonomy-title">Tag Cloud</h5> - <ul class="taxonomy-terms"> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B/" data-taxonomy-term="%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B"><span class="taxonomy-label">Итераторы</span><span class="taxonomy-count">1</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8/" data-taxonomy-term="%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8"><span class="taxonomy-label">Коллекции</span><span class="taxonomy-count">4</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%BE%D0%BE%D0%BF/" data-taxonomy-term="%D0%BE%D0%BE%D0%BF"><span class="taxonomy-label">ООП</span><span class="taxonomy-count">3</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B/" data-taxonomy-term="%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B"><span class="taxonomy-label">Системые Типы</span><span class="taxonomy-count">1</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85/" data-taxonomy-term="%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85"><span class="taxonomy-label">Типы Данных</span><span class="taxonomy-count">8</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8/" data-taxonomy-term="%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8"><span class="taxonomy-label">Функции</span><span class="taxonomy-count">1</span></a></li> - </ul> - </div> - - - </aside> - <main class="col-12 col-md-9 col-xl-8 ps-md-5 pe-md-4" role="main"> - <a class="td-rss-button" title="RSS" href="/blog/index.xml" target="_blank" rel="noopener"> - <i class="fa-solid fa-rss" aria-hidden="true"></i> - </a> - -<div class="td-content"> - <h1>Релиз языка программрования NewLang</h1> - - <div class="td-byline mb-4"> - - <time datetime="2022-06-24" class="text-muted">Friday, June 24, 2022</time> - </div> - <header class="article-meta"> - - </header> - <p><img alt="КДПВ" src="/blog/langs.jpeg"></p> - - -<div class="pageinfo pageinfo-primary"> -<p>Внимание!!!</p> -<p>Данная статья содержит описание синтаксиса NewLnag предыдущей версии.</p> -<p>Актуальную версию синтаксиса языка можно посмотреть <a href="/docs/">тут</a>.</p> - -</div> - -<p><strong>NewLang</strong> - это язык программирования высокого уровня, в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения.</p> -<p>Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка).</p> -<p>Новое по сравнению с <a href="https://habr.com/company/timeweb/blog/651999/">прошлым выпуском</a>:</p> -<ul> -<li>Реализованы все основные алгоритмические конструкции: проверка условий, различные варианты циклов, сравнение по образцу, прерывание последовательности команд и возврат данных, обработка ошибок и т.д.</li> -<li>Переработан основной синтаксис для отдельных языковых конструкций.</li> -<li>Реализованы большинство операций с переменными, включая операторы раскрытие списков и тензоров.</li> -<li>Серьезно переработана система встроенных типов, реализованы функции для их преобразования и для определения данных (последнее можно назвать data comprehensions).</li> -<li>Добавлены новые тесты и пр.</li> -</ul> -<cut /> -<h1 id="зачем-нужен-newlang">Зачем нужен <em>NewLang</em>?<a class="td-heading-self-link" href="#%d0%b7%d0%b0%d1%87%d0%b5%d0%bc-%d0%bd%d1%83%d0%b6%d0%b5%d0%bd-newlang" aria-label="Heading self-link"></a></h1> -<p>У всех современных языков программирования происходит постоянное развитие (читай усложнение) синтаксиса по мере выхода новых версий. Это является своего рода, платой за появление новых возможностей и воспринимается пользователями как естественное явление.</p> -<p>Но одновременно является и серьезной проблемой, т.к. с выходом новых версий добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки и трудоемкости поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.</p> -<p>У <em>NewLang</em> сложность языковых конструкций естественно ограничена за счет разделения синтаксиса языка на две части, что упрощает его изучение и использование.</p> -<p><em>Основной синтаксис</em> — для написания программ в объектно-ориентированном (императивном) и декларативном стилях, который основан не на зарезервированных ключевых словах, а на строгих грамматических правилах и <em>Расширенный синтаксис</em> — когда основного синтаксиса становится недостаточно, или требуется использовать языковую конструкцию языка реализации.</p> -<p>Еще одно неудобство современных мейнстримовых языков, большинство из них были созданы до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек, а не встроены в основной синтаксис языка и систему базовых типов.</p> -<p>У <em>NewLang</em> тензорные вычисления доступны «из коробки» (используется библиотека <a href="https://pytorch.org/">libtorch</a>), а обычные числа являются скалярами (тензорами нулевой размерности).</p> -<h1 id="синтаксис-newlang">Синтаксис NewLang<a class="td-heading-self-link" href="#%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81-newlang" aria-label="Heading self-link"></a></h1> -<p>При разработке синтаксиса я старался придерживаться уже сложившихся в IT индустрии правил, чтобы не генерировать множественных смыслов, которые будут зависеть от контекста.</p> -<p><strong>Основы</strong></p> -<ul> -<li>Операторы разделяются точкой с запятой «;».</li> -<li>Отступы и переводы строк игнорируются (очень хотелось иметь возможность автоматического форматирование кода).</li> -<li>Многострочные комментарии в исходном коде соответствуют стилю С/С++ и должны располагаться между символами /* и */. Вложенность многострочных комментариев не поддерживается.</li> -<li>Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash.</li> -<li>Последовательность команд, которая должна выполняться как единое целое, заключается в фигурные скобки «{}».</li> -<li>Программные вставки расширенного синтаксиса на языке реализации заключается в фигурные скобки со знаком процента %{ /* тут может быть любой код на C/C++*/ %}, как в лексерах lex и flex.</li> -</ul> -<h1 id="создания-объектов-и-присвоения-новых-значений">Создания объектов и присвоения новых значений<a class="td-heading-self-link" href="#%d1%81%d0%be%d0%b7%d0%b4%d0%b0%d0%bd%d0%b8%d1%8f-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%be%d0%b2-%d0%b8-%d0%bf%d1%80%d0%b8%d1%81%d0%b2%d0%be%d0%b5%d0%bd%d0%b8%d1%8f-%d0%bd%d0%be%d0%b2%d1%8b%d1%85-%d0%b7%d0%bd%d0%b0%d1%87%d0%b5%d0%bd%d0%b8%d0%b9" aria-label="Heading self-link"></a></h1> -<p>Для создания объектов и присвоения им новых значений в NewLang используется сразу три разных оператора:</p> -<ul> -<li><strong>::=</strong> используется только для создания новых объектов, а если объект с таким именем уже существует, то генерируется ошибка.</li> -<li><strong>:=</strong> используется для тех же целей, но если объект с таким именем уже существует, то ошибки не происходит, а новое значение присваивается уже существующему объекту.</li> -<li><strong>=</strong> применяется только для присвоения значения уже существующим объектам, и если объект с указанным именем отсутствует, то тоже происходит ошибка выполнения.</li> -</ul> -<p>Использование трех разных операторов для создания/изменения объектов позволяет более гибко контролировать подобные операции и выявлять логические ошибки в коде на более раннем этапе.</p> -<pre tabindex="0"><code>var ::= 1.0; # Создать новую переменную var без указания типа -var = 100; # Присвоить новое значение уже существующей переменной -printf := @import(&#39;printf(format:Format, ...):Int&#39;); /* Создать новый или переопределить объект printf, который будет результатом выполнения глобальной функции @import */ -</code></pre><h1 id="идентификаторы-объектов-и-модификаторы">Идентификаторы объектов и модификаторы<a class="td-heading-self-link" href="#%d0%b8%d0%b4%d0%b5%d0%bd%d1%82%d0%b8%d1%84%d0%b8%d0%ba%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%be%d0%b2-%d0%b8-%d0%bc%d0%be%d0%b4%d0%b8%d1%84%d0%b8%d0%ba%d0%b0%d1%82%d0%be%d1%80%d1%8b" aria-label="Heading self-link"></a></h1> -<p>В качестве идентификаторов можно использовать буквы, цифры и знаки подчеркивания в любых комбинациях, при условии, что первый символ идентификатора не является цифрой.</p> -<p>В NewLang существует возможность указания области видимости и времени жизни объекта с помощью модификатора — специального символа перед именем переменной. Это может показаться немного похожим на венгерскую нотацию, но в отличие от нее, модификатор не имеет отношения к типу объекта и не является частью имени идентификатора. К тому же в качестве модификаторов используется строго определённые символы, назначение которых определено заранее.</p> -<ul> -<li><strong>$</strong> - в начале имени обозначает локальную переменную, время жизни которой ограничено текущей областью видимости и при её завершении локальная переменная уничтожается.</li> -<li><strong>@</strong> - обозначает глобальную переменную, а сам объект сохраняет свое состояние даже после выхода из текущей области видимости.</li> -<li><strong>:</strong> - двоеточие вначале имени используется в качестве модификатора для указания типа.</li> -</ul> -<p>Семантика обращения к аргументам функций очень похоже на работу с аргументами в bash скриптах, где $1 или $arg — порядковый номер или имя аргумента (происходит обращение к локальным переменным в текущей области видимости).</p> -<h3 id="использование-модификаторов-является-обязательным-только-в-двух-случаях">Использование модификаторов является обязательным только в двух случаях:<a class="td-heading-self-link" href="#%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%bc%d0%be%d0%b4%d0%b8%d1%84%d0%b8%d0%ba%d0%b0%d1%82%d0%be%d1%80%d0%be%d0%b2-%d1%8f%d0%b2%d0%bb%d1%8f%d0%b5%d1%82%d1%81%d1%8f-%d0%be%d0%b1%d1%8f%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d1%8b%d0%bc-%d1%82%d0%be%d0%bb%d1%8c%d0%ba%d0%be-%d0%b2-%d0%b4%d0%b2%d1%83%d1%85-%d1%81%d0%bb%d1%83%d1%87%d0%b0%d1%8f%d1%85" aria-label="Heading self-link"></a></h3> -<ul> -<li>При создании нового типа данных, так как типы всегда создаются в глобальной области видимости, а их символьные имена должны быть уникальными.</li> -<li>При обращении к объектам NewLang внутри программных вставок кода на языке реализации, так как они используется как маркеры при поиске идентификаторов NewLang в коде С/С++.</li> -</ul> -<p>В остальных случаях, для обращения к переменным указывать их модификаторы необязательно. И если при обращении к объекту модификатор не указан, то сперва ищется локальная переменная, а потом глобальная с таким же именем. Причем, локальная переменная будет перекрывать глобальную.</p> -<p>Так же следует иметь в виду, что компилятор может генерировать код для прямого обращения к локальным объектам уже на этапе компиляции, тогда как для обращения к глобальным объектам, или если модификатор области видимости отсутствует, компилятор вынужден каждый раз встраивать runtime вызов функции поиска объекта в глобальной таблице символов.</p> -<h1 id="система-типов">Система типов<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0-%d1%82%d0%b8%d0%bf%d0%be%d0%b2" aria-label="Heading self-link"></a></h1> -<p>Так как система типов языка динамическая, то явное указание типа не влияет на размер переменной и является только своего рода логическим ограничением на возможность присвоения переменной значения другого типа.</p> -<p>Информация о типах используется при проверке их совместимости, когда существующему объекту присваивается значение другого типа. Такая операция возможна только когда типы совместимы между собой и допускают автоматическое приведение. Это справедливо как во время парсинга/компиляции исходного теста, так и во время выполнения в режимах интерпретатора и/или скомпилированного файла.</p> -<h2 id="простые-типы">Простые типы<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%be%d1%81%d1%82%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b" aria-label="Heading self-link"></a></h2> -<h3 id="арифметические-значения">Арифметические значения<a class="td-heading-self-link" href="#%d0%b0%d1%80%d0%b8%d1%84%d0%bc%d0%b5%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5-%d0%b7%d0%bd%d0%b0%d1%87%d0%b5%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h3> -<p>Арифметические типы данных являются тензорами — массивами чисел одного типа с произвольным количеством измерений и одинаковым размером столбцов в каждом. Единичное число тоже тензор нулевого размера.</p> -<p>Поддерживаются только знаковые целые числа, т.к. в беззнаковых числах особая нужда отсутствует, а проблем с ними можно найти очень много на ровном месте.</p> -<p>Проблемы беззнаковых чисел (из интернета):</p> -<blockquote> -<p>Во-первых, вычитание двух беззнаковых чисел, например 3 и 5. 3 минус 5 равно 4294967294, т.к. -2 не может быть представлено как беззнаковое число. Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных значений со знаком и без знака. С++ может свободно преобразовывать числа со знаком и без знака, но не проверяет диапазон, чтобы убедиться, что вы не переполняете свой тип данных. -В C++ всё же есть несколько случаев, когда можно (или необходимо) использовать беззнаковые числа. Во-первых, числа без знака предпочтительнее при работе с битами. Во-вторых, использование беззнаковых чисел связанных с индексацией массивов.</p> -</blockquote> -<p>Но это не мой случай, так как индекс может быть отрицательным и даже не числом, а диапазоном или многоточием.</p> -<p>З.Ы. И даже зная об этом, все равно умудрился недавно словить баг с отрицательными индексами у словарей!</p> -<p>Имена встроенных арифметических типов говорят сами за себя: Char, Short, Int, Long, Float, Double, ComplexFloat, ComplexDouble. Отдельным типом идет логический тип Bool, который может принимать значения только 0 или 1 (false/true соответственно), и в зависимости от выполняемой операции может быть отнесен к целочисленным типам, так и не входить в их состав (данный подход интерпретации логического типа данных был взят из библиотеки Torch).</p> -<pre tabindex="0"><code>// Treat bool as a distinct &#34;category,&#34; to be consistent with type promotion -// rules (e.g. `bool_tensor + 5 -&gt; int64_tensor`). If `5` was in the same -// category as `bool_tensor`, we would not promote. Differing categories -// implies `bool_tensor += 5` is disallowed. -// -// NB: numpy distinguishes &#34;unsigned&#34; as a category to get the desired -// `bool_tensor + 5 -&gt; int64_tensor` behavior. We don&#39;t, because: -// * We don&#39;t want the performance hit of checking the runtime sign of Scalars. -// * `uint8_tensor + 5 -&gt; int64_tensor` would be undesirable. -</code></pre><p>В будущем планируется добавить классы чисел для длинной арифметики и дробей, для чего зарезервированы названия типов BigNum, Currency и Fraction.</p> -<p>Доступ к элементам тензора происходит по целочисленному индексу, который начинается с 0. Для многомерного тензора, индексы элемента перечисляются в квадратных скобках через запятую. Поддерживается доступ к элементам через отрицательный индекс, который обрабатывается точно так же, как в Python (-1 последний элемент, -2 предпоследний и т.д.).</p> -<p>Литерал тензор в тексте программы записывается в квадратных скобках с обязательной завершающей запятой, т.е. [1, 2,] — это литерал одномерный тензор из двух чисел. После закрывающей скобки тип тензора может быть указан в явном виде. Если тип не указан, то он выводится автоматически на основании указанных данных и выбирается минимально возможный байтовый размер, который позволяет сохранить все значения без потери точности.</p> -<p><em>Примеры:</em></p> -<pre tabindex="0"><code>$var_char := 123; # Тип Char выводится автоматически -$var_short := 1000; # Тип Short выводится автоматически -$var_bool := [0, 1, 0, 1,]; # Тензор из 4 элементов. Тип Bool выводится автоматически -$tensor[10,10]:Int := 1; # Тензор Int размером 2x2 инициализированный 1 -$scalar := $tensor[5,5]; # Присвоить скаляру значение указанного элемента тензора -</code></pre><h2 id="строки">Строки<a class="td-heading-self-link" href="#%d1%81%d1%82%d1%80%d0%be%d0%ba%d0%b8" aria-label="Heading self-link"></a></h2> -<p>Поддерживаются два типа строк, StrWide — символьные (широкие) и StrChar — байтовые. Различия между ними заключается в типе единичного элемента. У символьных строк единичным элементом является широкий символ <em>wchar_t</em>, а у байтовой строки единичным элементом является один байт (точнее <em>char</em>, т.е. байт со знаком). Символьные строки литералы в исходном тексте записывается в «двойных кавычках», а байтовые строки в &lsquo;одинарных кавычках&rsquo;.</p> -<p>Количество элементов символьной строки возвращается в широких символах, а размер байтовой строки в байтах, поэтому и обращение к элементу строки по индексу происходит соответственно либо к символу, либо к байту.</p> -<p>Важный момент. К любой переменной можно обратиться так же, как к функции (записав после её имени круглые скобки). Результатом этой операции будет создание копии/клона объекта. Причем некоторые типы (словари, классы и символьные строки) можно использовать в качестве шаблона при создании копии объекта с модифицированными свойствами, если новые и/или изменяемые значения указать в скобках, как аргументы при вызовах функций. Так, если при создании копии в скобках указать набор новых данных, то результирующая копия будет содержать уже измененные данные.</p> -<p><em>Например:</em></p> -<pre tabindex="0"><code>$template := &#34;${name} $1&#34;; # Обычная строка -$result := $template(&#34;шаблон&#34;, name = &#34;Строка&#34;); # result = &#34;Строка шаблон&#34; -</code></pre><h2 id="системные">Системные<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%8b%d0%b5" aria-label="Heading self-link"></a></h2> -<h3 id="pointer---указатель-на-системную-область-памяти">:Pointer - указатель на системную область памяти<a class="td-heading-self-link" href="#pointer---%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%83%d1%8e-%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8" aria-label="Heading self-link"></a></h3> -<p>Так как любой программе приходится взаимодействовать с внешним миром, то по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип <em>Pointer</em>. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. Но можно вывести его значение, например для отладки.</p> -<h3 id="plain---указатель-на-представление-данных-в-бинарном-виде">:Plain - указатель на представление данных в бинарном виде<a class="td-heading-self-link" href="#plain---%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d0%bf%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%be%d0%bc-%d0%b2%d0%b8%d0%b4%d0%b5" aria-label="Heading self-link"></a></h3> -<p>Для взаимодействия с внешними библиотеками требуется еще и обмен данными. И для этих целей служит тип данных <em>Plain</em> - который также является указателем, но на двоичное представление данных в единой области памяти. Конечно, если их можно представить в виде единого фрагмента.</p> -<h2 id="составные-типы-данных">Составные типы данных:<a class="td-heading-self-link" href="#%d1%81%d0%be%d1%81%d1%82%d0%b0%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85" aria-label="Heading self-link"></a></h2> -<h3 id="словарь">Словарь<a class="td-heading-self-link" href="#%d1%81%d0%bb%d0%be%d0%b2%d0%b0%d1%80%d1%8c" aria-label="Heading self-link"></a></h3> -<p>Словарь (:Dictionary) — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии (он похож и на tuple и на структуру одновременно). Словари от тензоров отличаются тем, что являются только одномерными массивами, но каждый элемент может содержать произвольное количество элементов любого типа, в том числе и другие словари.</p> -<p>Доступ к элементам словарей происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. Индекс также начинается с 0 и как у тензоров и тоже может быть отрицательным.</p> -<p>Литерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, т. е. (,) — пустой словарь, (1, 2= «2», name=3,).</p> -<h3 id="перечисление-структура-и-объединение">Перечисление, структура и объединение<a class="td-heading-self-link" href="#%d0%bf%d0%b5%d1%80%d0%b5%d1%87%d0%b8%d1%81%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d0%b8-%d0%be%d0%b1%d1%8a%d0%b5%d0%b4%d0%b8%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> -<p><em>:Enum</em>, <em>:Struct</em> и <em>:Union</em> — это такие же словари, только на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера.</p> -<h3 id="классы">Классы<a class="td-heading-self-link" href="#%d0%ba%d0%bb%d0%b0%d1%81%d1%81%d1%8b" aria-label="Heading self-link"></a></h3> -<p>Класс (реализован частично) — тип данных, с помощью которого реализуется один из принципов ООП — наследование. При создании экземпляра класса создается новая переменная, у которой сохраняется информацию о своем родителе и которая наследует от него свойства и методы. Тип данных <em>:Class</em> аналогичен словарю, но все свойства обязаны иметь имена (хотя доступ к свойствам класса по индексу так же возможен).</p> -<h2 id="функции">Функции<a class="td-heading-self-link" href="#%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h2> -<p>Синтаксис NewLang поддерживать несколько типов функций (а в будущем и методов классов): обычные функции, чистые функции и простые чистые функции.</p> -<p>Для всех типов функций поддерживаются аргументы по умолчанию. При создании функции, её аргументы указываются как в Python, т.е. вначале идут обязательные аргументы, потом аргументы со значениями по умолчанию, где имя аргумента отделяется от его значения по умолчанию знаком равно <strong>=</strong>. Если функция допускает обработку произвольного количества аргументов, то последним в списке параметров указывается многоточие <strong>&hellip;</strong> (три точки подряд) .</p> -<h3 id="обычная-функция">Обычная функция<a class="td-heading-self-link" href="#%d0%be%d0%b1%d1%8b%d1%87%d0%bd%d0%b0%d1%8f-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8f" aria-label="Heading self-link"></a></h3> -<p>Обычная функция — такие функции являются именно обычными функциями в понимании С/С++. Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д.</p> -<p>Внутри обычной функции можно обращаться к локальным и глобальным объектам, и они могут содержаться вставки на языке реализации*, например, для вызова функций из внешних библиотек.</p> -<p>Вставки на языке реализации оформляются в виде %{ %} и могут содержать любой текст на С/С++, а прямо из него можно обращаться к локальным и глобальным объектам NewLang так же, как и в обычном синтаксисе, указывая первым символом имени соответствующий модификатор (<em>$</em> для локальных объектов и <em>@</em> для глобальных).</p> -<p>Технически, такая программная вставка просто переносится трансплайтером непосредственно в исходный текст генерируемого файла, а все идентификаторы NewLang специальным образом декорируются (добавляются специальные маркеры для их идентификации), после этого исходный текст подается на вход обычному компилятору С++. Для локальных объектов трансплайтер может генерировать код для прямого доступа к объекту на этапе компиляции, а для работы с глобальными объектами вынужден использовать runtime вызовы функции поиска в таблице символов.</p> -<hr> -<p>*) - Программные вставки на языке реализации обрабатываются только во время компиляции</p> -<p><em>Например:</em></p> -<pre tabindex="0"><code>print(str) := { - %{ - printf(&#34;%s&#34;, static_cast&lt;const char *&gt;($str)); /* Прямой вызов С функции */ - %} -}; -</code></pre><h3 id="чистые-функции">Чистые функции<a class="td-heading-self-link" href="#%d1%87%d0%b8%d1%81%d1%82%d1%8b%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h3> -<p>Чистая функция — это тоже обычная функция, только в том смысле, какой в него вкладывает функциональное программирование. Создания чистой функции происходит с помощью оператора <strong>:-</strong>, а сам оператор заимствован из языка Пролог. У чистой функции отсутствует доступ к контексту и глобальным переменным, поэтому она может обрабатывать только те данные, которые были ей переданы в качестве аргументов.</p> -<p>Программные вставки на языке реализации внутри чистых функций не запрещены и могут использоваться, например, для отладки. Но делается это на страх и риск разработчика. Именно он отвечает за их «чистоту», например при вызове функций из внешних библиотек.</p> -<pre tabindex="0"><code>Sum(arg1, arg2) :- {$arg1+$arg2;}; # Вернуть сумму аргументов -</code></pre><h3 id="простые-чистые-функции">Простые чистые функции<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%be%d1%81%d1%82%d1%8b%d0%b5-%d1%87%d0%b8%d1%81%d1%82%d1%8b%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h3> -<p>Простые чистые функции — отдельный класс чистых функций, которые предназначены только для вычисления логического результата (т.е. они являются предикатами) и их отличает упрощенная формой записи. Тело простой чистой функции состоит из последовательности операторов, которые разделяются запятыми и заканчиваются, как и любое выражение, точкой с запятой. Все операторы простой чистой функции всегда приводятся к булевому значению, а итоговый результат функции вычисляется по одной из возможных логических операций: И, ИЛИ и исключающее ИЛИ.</p> -<p><em>Например:</em></p> -<pre tabindex="0"><code>func_and(arg1, arg2) :&amp;&amp;= arg1==3, arg2 &gt; 0; # Простая чистая функция Логическое И -func_or(arg1, arg2) :||= arg1==3, arg2 &gt; 0; # Простая чистая функция Логическое ИЛИ -func_xor(arg1, arg2) :^^= arg1==3, arg2 &gt; 0; # Простая чистая функция Исключающее ИЛИ -</code></pre><h2 id="специальные-типы-данных">Специальные типы данных:<a class="td-heading-self-link" href="#%d1%81%d0%bf%d0%b5%d1%86%d0%b8%d0%b0%d0%bb%d1%8c%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85" aria-label="Heading self-link"></a></h2> -<h3 id="пусто-none">Пусто (:None)<a class="td-heading-self-link" href="#%d0%bf%d1%83%d1%81%d1%82%d0%be-none" aria-label="Heading self-link"></a></h3> -<p><strong>:None</strong> (пусто) — не содержит значения (точнее имеет одно значение None) и совместим с любым другим типом данных. Указывается в тексте программы как один подчерк «_». None имеют не инициализированные переменные и при попытке чтения из такой переменной возникает ошибка.</p> -<p>Тип переменной может быть явно указан или выведен автоматически из присваиваемого значения. Присвоить новое значение уже инициализированной переменной можно только для совместимого типа, так как неявное преобразование типов не допускаются.</p> -<pre tabindex="0"><code>$var := _; # Создать не инициализированную переменную -$var2 := var; # Ошибка!!! Нельзя прочитать неинициализированную переменную var -$var = 1000; # У переменной будет тип Short (минимальный размер для хранения значения) -$var = 0,5; # Ошибка!!! Short ← Float не совместимы -$var = _; # Очистить значение переменной -$var = 0,5; # Теперь можно, т. к. None совместим с любым типом -</code></pre><h3 id="диапазон-range">Диапазон (:Range)<a class="td-heading-self-link" href="#%d0%b4%d0%b8%d0%b0%d0%bf%d0%b0%d0%b7%d0%be%d0%bd-range" aria-label="Heading self-link"></a></h3> -<p>Диапазон — специальный тип данных, являющейся приблизительным аналогом типа «генератор» в Python. К диапазону можно обращаться как к итератору и он будет поочередно выдавать элементы в указанном интервале с заданным шагом. Диапазон в тексте программы указывается как два или три элемента через две точки, например 1..5 — диапазон от единицы до пяти с шагом по умолчанию 1. В качестве параметров диапазона можно указывать не только литералы, но и имена переменных. Например, <em>0,1..$stop..0,1</em> — диапазон от 0,1 до значения, указанного в переменной $stop с шагом 0,1.</p> -<p>Диапазон для целых чисел можно использовать в качестве индекса у тензоров (точнее, у любых объектов, которые допускают доступ к своим элементам по индексу, т.е. тензоры, словари и текстовые строки). Фактический, это поведение аналогично <em>slice</em> в языке Python и <em>array[1:5]</em> в Python означает тоже самое, что и <em>array[1..5]</em> в NewLang.</p> -<p>В качестве индекса у тензоров еще можно указать произвольное количество измерений с помощью многоточия, т.е.</p> -<pre tabindex="0"><code>$tensor[…, 0] = 0; # Обнулить все первые элементы в каждом измерении. -</code></pre><h2 id="преобразование-типов">Преобразование типов<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b5%d0%be%d0%b1%d1%80%d0%b0%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d1%82%d0%b8%d0%bf%d0%be%d0%b2" aria-label="Heading self-link"></a></h2> -<h3 id="явное-приведение-типов">Явное приведение типов<a class="td-heading-self-link" href="#%d1%8f%d0%b2%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%b8%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5-%d1%82%d0%b8%d0%bf%d0%be%d0%b2" aria-label="Heading self-link"></a></h3> -<p>Несмотря на динамическую типизацию языка, если тип переменной указан явно, то автоматическое приведение типов не выполняется, и чтобы присвоить переменой значение не совместимого типа, требуется явное преобразование.</p> -<p>Так как символьные названия типов относятся к деталям реализации, то явное преобразование в конкретный тип данных производится с помощью вызова функции с именем типа, т.е. :Bool(), :StrWide(), :Long() и т.д.</p> -<p>Для преобразования любого типа данных в строку ещё можно использовать оператор конкатенации строк, которой преобразует любой тип данных в строковое представление. Но, так как строковых типов два (байтовые и широкие строки), то тип строки определяется первым аргументом в операторе конкатенации/сцепления <strong>++</strong>. Также преобразовать любое значение в строковое можно с помощью строки-шаблона.</p> -<pre tabindex="0"><code>&#34;&#34; ++ 123; # &#34;123&#34; - Строка широких символов -&#39;&#39; ++ 123; # &#39;123&#39; - Байтовая строка - -val := 12345; # Число -&#34;$1&#34;(val); # Будет строка &#34;12345&#34; -</code></pre><p>Так как тензоры могут иметь больше одного значения, то и в качестве аргументов могут принимать их произвольное количество, а итоговым результатом будет тензор, в котором все переданные данные преобразованы к требуемому типу автоматически.</p> -<p><em>Примеры:</em></p> -<pre tabindex="0"><code>&gt; tstr := :Tensor(&#34;Тест&#34;); # Создать тензор из строки широких символов -[1058, 1077, 1089, 1090,]:Int - -&gt; t2 := :Tensor[2,2](&#34;Тест&#34;); # Тоже самое, но тензор указанной размерности -[ - [1058, 1077,], [1089, 1090,], -]:Int - -&gt; :StrWide(tstr) # Создать символьную строку из тензора -Тест - -&gt; :Double(t2) # Изменить тип данных тезора без изменения размерности -[ - [1058, 1077,], [1089, 1090,], -]:Double - -&gt; t3 := :Char[4]( t2 ) # Изменить размерность тензора и его тип (в данном случае с частичной потерей данных) -[34, 53, 65, 66,]:Char - - -&gt;:Tensor( (1,2,3,) ); # Тензор из словаря -[1, 2, 3,]:Char - -&gt;:Tensor( &#39;first second&#39; ) # Байтовая строка в тензор -[102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char - -&gt;:Tensor( (first=&#39;first&#39;, space=32, second=&#39;second&#39;,) ) # Получаем тензор из словаря с такими же данными -[102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char - -&gt;:Double[10,2]( 0, ...) # Тензор заданного формата с нулями, где многоточие повторяет последние указанные данные до получения тензора требуемого размера -[ - [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], -]:Double - -&gt;:Int[3,2]( ... rand() ...) # Тензор со случайными данными, где между многоточиями указана функция, которую следует вызывать каждый раз при получении нового элемента тензора -# Пришлось придумывать новую конструкцию, т.к. многоточие перед именем, это оператор раскрытия словаря, а многоточие после имени, это повторение последнего значения до конца заданной размерности. -[ - [1804289383, 846930886,], [1681692777, 1714636915,], [1957747793, 424238335,], -]:Int - -&gt;:Int[5,2]( 0..10 ); # Создание тензора из диапазона -[ - [0, 1,], [2, 3,], [4, 5,], [6, 7,], [8, 9,], -]:Int - -&gt;:Tensor( 0..0.99..0.1 ); # Или даже так -[0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,]:Double -</code></pre><h1 id="операторы-и-управляющие-конструкции">Операторы и управляющие конструкции<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d0%b8-%d1%83%d0%bf%d1%80%d0%b0%d0%b2%d0%bb%d1%8f%d1%8e%d1%89%d0%b8%d0%b5-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h1> -<h2 id="операторы">Операторы:<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b" aria-label="Heading self-link"></a></h2> -<p>Все операторы имеют парный аналог с присвоением значения:</p> -<ul> -<li><strong>+</strong> и <strong>+=</strong> - сложение арифметических типов данных;</li> -<li><strong>-</strong> и <strong>-=</strong> - вычитание арифметических типов данных;</li> -<li><strong>/</strong> и <strong>/=</strong> - деление (результат число с плавающей точкой);</li> -<li><strong>//</strong> и <strong>//=</strong> - целочисленное деление с округлением к меньшему числу (как в Python);</li> -<li><em>*</em> и <em>*=</em> - умножение;</li> -<li><em>**</em> и <strong>**=</strong> - возведение в степень (он же используется и для повторения текстовых строк);</li> -<li><strong>++</strong> и <strong>++=</strong> - конкатенация строк с автоматическим приведением аргументов к стоковому типу (символ инкремента специально используется вместо одиночного плюса для того, чтобы в явном виде разделить конкатенацию строк и операторы арифметического сложения).</li> -</ul> -<h2 id="операторы-сравнения">Операторы сравнения:<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d1%81%d1%80%d0%b0%d0%b2%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h2> -<ul> -<li><strong>&lt;</strong>, <strong>&gt;</strong>, <strong>&lt;=</strong>, <strong>&gt;=</strong> - классические для сравнения скаляров</li> -<li><strong>==</strong> и <strong>!=</strong> - операторы сравнения с автоматическим приведением совместимых типов для любых объектов</li> -<li><strong>===</strong> и <strong>!==</strong> - оператор точного сравнения для любых объектов (автоматического приведения типов не выполняется)</li> -</ul> -<h2 id="проверки-типа-имени-класса-объекта">Проверки типа (имени класса объекта):<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b8-%d1%82%d0%b8%d0%bf%d0%b0-%d0%b8%d0%bc%d0%b5%d0%bd%d0%b8-%d0%ba%d0%bb%d0%b0%d1%81%d1%81%d0%b0-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%b0" aria-label="Heading self-link"></a></h2> -<p>Для оператора проверки имени класса объекта используется символ тильда <strong>~</strong>. Он немного похож на оператор <em>instanceof</em> в Java. Левым операндом должен быть проверяемый объект, а правым — проверяемый тип, который можно указать строкой литералом, переменной строкового типа или именем проверяемого класса непосредственно. Результатом операции будет истина, если правый операнд содержит название класса проверяемого объекта или он присутствует в иерархии наследования.</p> -<pre tabindex="0"><code>name := &#34;class&#34;; # Строковая переменная с именем класса -var ~ name; -var ~ :class; # Имя типа -var ~ &#34;class&#34;; # Строка литерал с именем типа -</code></pre><h2 id="утиная-типизация">Утиная типизация<a class="td-heading-self-link" href="#%d1%83%d1%82%d0%b8%d0%bd%d0%b0%d1%8f-%d1%82%d0%b8%d0%bf%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f" aria-label="Heading self-link"></a></h2> -<p>Оператор утиной типизации, два символа тильны <strong>~~</strong> — приблизительный аналог функции isinstance() в Python, который для простых типов сравнивает непосредственную совместимость типа левого операнда по отношению к правому. А для словарей и классов в левом операнде проверяется наличие всех имен полей, присутствующих у правого операнда, т.е.:</p> -<pre tabindex="0"><code>(field1=«value», field2=2,) ~~ (); # Истина (т. е. левый операнд словарь) -(field1=«value», field2=2,) ~~ (field1=_); # Тоже истина (т. к. поле field1 присутствует у левого операнда) -(field1=«value», field2=2,) ~~ (not_found=_); # Ложь, т.к. поле not_found у левого операнда отсутствует -</code></pre><p>Строгая утиная типизация <strong>~~~</strong> — для простых типов сравнивается идентичности типов без учета совместимости, а для составных типов происходит сравнение всех свойств с помощью оператора строгого равенства. Для данной операции, пустой тип совместим только с другим пустим типом.</p> -<h1 id="управляющие-конструкции">Управляющие конструкции<a class="td-heading-self-link" href="#%d1%83%d0%bf%d1%80%d0%b0%d0%b2%d0%bb%d1%8f%d1%8e%d1%89%d0%b8%d0%b5-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h1> -<p>К управляющим конструкциям языка NewLang относятся условный оператор, два вида циклов, оператор оценки выражения, оператор прерывания последовательности выполнения команд и перехват прерывания. Операторы проверки условий всегда указываются в квадратных скобках, а последовательность команд для выполнения - в фигурных.</p> -<h2 id="условный-оператор">Условный оператор<a class="td-heading-self-link" href="#%d1%83%d1%81%d0%bb%d0%be%d0%b2%d0%bd%d1%8b%d0%b9-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80" aria-label="Heading self-link"></a></h2> -<p>В качестве оператора проверки условия используется синтаксическая конструкция, соответствующая по смыслу термину «следует», т.е. тире и угловая скобка <strong>-&gt;</strong> или с двумя тире для большей наглядности <strong>&ndash;&gt;</strong>. Такая запись условного оператора очень похожа на математическую и легко объединяется в последовательности для проверки множественных условий вида «else if».</p> -<p>В общем случае условный оператор имеет вид: <code>[ условие ] -&gt; действие;</code> или <code>[ условие ] -&gt; {действие};</code> или <code>[ условие1 || условие2 ] --&gt; {действие}, [_] --&gt; {действие иначе};</code></p> -<p>Для наглядности записанный с отступами:</p> -<pre tabindex="0"><code>[ условие1 ] -&gt; { действие1 }, - [ условие2 ] -&gt; действие2, - [ условие3 ] -&gt; действие3, - [_] -&gt; {действие_иначе}; -</code></pre><h2 id="оценка-выражения">Оценка выражения<a class="td-heading-self-link" href="#%d0%be%d1%86%d0%b5%d0%bd%d0%ba%d0%b0-%d0%b2%d1%8b%d1%80%d0%b0%d0%b6%d0%b5%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h2> -<p>Синтаксическая конструкция с помощью которой реализуется аналог оператора switch выглядит следующим образом:</p> -<pre tabindex="0"><code>[ $var ] ==&gt; { - [1] -&gt; { code }; # Выполнится проверка условия $var == 1 - [1, 2] -&gt; { code }; # Выполнится проверка условия ($var == 1 || $var == 2) - [_] -&gt; { code default }; # Ветка условия иначе -}; -</code></pre><p>Причем в качестве оператора для оценки могут быть использован любые имеющиеся операторы сравнения на равенство:</p> -<ul> -<li><strong>==&gt;</strong> - проверка на равенство с приведением типов;</li> -<li><strong>===&gt;</strong> - проверка на точное равенство;</li> -<li><strong>~&gt;</strong> - проверка типа (имени класса);</li> -<li><strong>~~&gt;</strong> - утиная типизация;</li> -<li><strong>~~~&gt;</strong> - строгая утиная типизация.</li> -</ul> -<p>И если в качестве оператора сравнения использовать оператор утиной типизации, то оценка выражения превращается в классический Pattern Matching:</p> -<pre tabindex="0"><code>$value := (f1=1, f2=&#34;2&#34;,); -[ $value ] ~~~&gt; { - [ (f1=_, ), (f1=_, f2=0, ) ] -&gt; { code }; # Поле f2 отсутствует или число - [(f1=_, f2=&#34;&#34;,), (f1=_, f2=&#39;&#39;,)] -&gt; { code }; # Поле f2 строка - [_] -&gt; { code default }; # Код по умолчанию -}; -</code></pre><h2 id="операторы-циклов">Операторы циклов<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d1%86%d0%b8%d0%ba%d0%bb%d0%be%d0%b2" aria-label="Heading self-link"></a></h2> -<p>Для указания операторов циклов используются управляющие <strong>-&raquo;</strong> или <strong>&ndash;&raquo;</strong> (с двумя стрелками по направлению от проверки условия к телу цикла). И в зависимости от расположения условия и тела цикла, он может быть с предусловием (<em>while</em>) или постусловием (<em>do while</em>). Хотя пока эти синтаксические конструкции не &ldquo;отлежались&rdquo; и их можно считать временными из-за того, что их легко перепутать с условным оператором, и, возможно, имеет смысл заменить разные операторы цикла одной единственной конструкцией вида: <strong>&lt;&ndash;&gt;</strong> или <strong>&laquo;-&raquo;</strong>, которая сильнее отличается от оператора следования.</p> -<p>Но в настоящий момент циклы реализованы вот так:</p> -<pre tabindex="0"><code>[условие while] -&gt;&gt; { - тело цикла while -}; - -{ - тело цикла do while -} &lt;&lt;-- [условие do while]; -</code></pre><p>Реализация цикла foreach на примере суммирования всех элементов словаря (или одномерного тензора):</p> -<pre tabindex="0"><code>summa := 0; -dict := (1,2,3,4,5,); -[ dict ] --&gt;&gt; { # Условие цикла, пока есть данные - item, dict := ... dict; # Результат оператора раскрытия словаря - первый его элемент перемещается в item - summa += item; # Вычисление суммы всех элементов словаря -}; -</code></pre><h2 id="операторы-прерывания-возврата">Операторы прерывания (возврата)<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d0%bf%d1%80%d0%b5%d1%80%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%b2%d0%be%d0%b7%d0%b2%d1%80%d0%b0%d1%82%d0%b0" aria-label="Heading self-link"></a></h2> -<p>В качестве оператора прерывания/возврата используется два символа минус <strong>&ndash;</strong>. Оператор позволяет прервать выполнение последовательности команд и/или вернуть данные из текущей функции/блока кода и является самым близким аналогом оператора <strong>return</strong> и <strong>throw</strong> одновременно. Для того чтобы вернуть данные, их необходимо указать между двумя операторами прерывания, т.е. <code>--100--; # Вернуть указанное значение</code>. Если возвращаемое значение не указано явно, то будет возвращено значение <em>None</em>.</p> -<h2 id="следование-блок-кодалямбда-функция">Следование (блок кода/лямбда функция)<a class="td-heading-self-link" href="#%d1%81%d0%bb%d0%b5%d0%b4%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%b1%d0%bb%d0%be%d0%ba-%d0%ba%d0%be%d0%b4%d0%b0%d0%bb%d1%8f%d0%bc%d0%b1%d0%b4%d0%b0-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8f" aria-label="Heading self-link"></a></h2> -<p>Алгоритмическая конструкция, которая отвечает последовательное выполнение нескольких команд/операторов и возвращающая результат выполнения последнего из них. Также, результатом выполнения может быть значение, которое возвращается с помощью оператора прерывания (возврата). Это очень похоже на классическую лямбда функцию, только она выполняется сразу во время определения, а в переменную сохраняется уже результат её выполнения.</p> -<p>Следование без перехвата прерывания оформляется в виде последовательности обычных и фигурных скобок, т.е. <code>(){ run code };</code> или тоже самое, но сохраняет результата выполнения в переменной: <code>$result := (){ run(); code() };</code>. Но если внутри такой функции будет выполнен оператор прерывания, то она никогда вернет управления и не сохранит возвращаемое значение в переменой <em>$result</em>!</p> -<p>Чтобы перехватывать прерывания, в том числе и возвращаемые значения, необходимо использовать конструкция следования с перехватом прерываний, которая оформляется в виде последовательности обычных и <strong>двойных</strong> фигурных скобок, т.е. <code>$error := (){{ run(); error();code() }};</code>. Такая конструкция перехватывает все возвраты и прерывания, если они возникают во время выполнения последовательности команд. В этом случае любой результат будет сохранен в переменной <em>$error</em> как при нормальном завершении, так и в случае возникновения ошибки.</p> -<p>Для более тонкой настройки перехвата прерываний следует использовать типизированную конструкцию, когда в явном виде указывается, какие типы прерываний следует перехватывать. <code>$runtime := (){{ run(); error(); code() }}:ErrorRuntime;</code>. Такая конструкция вернет результат только в случае успешного завершения (когда с помощью оператора прерывания возвращается не типизированное значение, например, <code>--&quot;Строка&quot;--;</code>), или при создании прерывания с указанием конкретного типа <strong>&ndash;:ErrorRuntime(&ldquo;Описание ошибки&rdquo;)&ndash;;</strong>. А вот при возникновении любого другого типизированного прерывания, значение перехвачено не будет и все отработает как самый первый вариант, т.е. без перехвата прерывания и без сохранения возвращаемого значения в переменную.</p> -<h2 id="стратегия-обработки-ошибок">Стратегия обработки ошибок<a class="td-heading-self-link" href="#%d1%81%d1%82%d1%80%d0%b0%d1%82%d0%b5%d0%b3%d0%b8%d1%8f-%d0%be%d0%b1%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b8-%d0%be%d1%88%d0%b8%d0%b1%d0%be%d0%ba" aria-label="Heading self-link"></a></h2> -<p>Обработка ошибок состоит из комбинации двух элементов: оператора прерывания выполнения с указанием типа возвращаемого значения и алгоритмической конструкции следование с возможностью перехвата прерывания заданного типа.</p> -<p>Это немного отличается от классического варианта обработки исключений, который в обычных языках программирования обычно оформляется ключевыми словами try… catch… finally с различными вариациями. Ведь основная цель подобных синтаксических конструкций — выделить участок кода, где возможно возникновение ошибки, перехватить и обработать правильный тип данных (исключений), т.к. <strong>NewLang</strong> не делает различий между операторами возврата и генерации исключения.</p> -<h3 id="подход-к-обработке-исключений-следующий">Подход к обработке исключений следующий:<a class="td-heading-self-link" href="#%d0%bf%d0%be%d0%b4%d1%85%d0%be%d0%b4-%d0%ba-%d0%be%d0%b1%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b5-%d0%b8%d1%81%d0%ba%d0%bb%d1%8e%d1%87%d0%b5%d0%bd%d0%b8%d0%b9-%d1%81%d0%bb%d0%b5%d0%b4%d1%83%d1%8e%d1%89%d0%b8%d0%b9" aria-label="Heading self-link"></a></h3> -<p>Программный код, который может привести к ошибке, заключается в двойные фигурные скобки, а результат выполнения такого блока кода присваивается переменной. После этого анализируется возвращенное значение, например, оператором сравнения по образцу:</p> -<pre tabindex="0"><code>$result := (){{ # начало аналога блока try - $value := call_or_exception1(); - [условие1] -&gt; { -- :Error -- }; - [условие2] -&gt; { -- $value -- }; - $value := call_or_exception2(); -}}; # конец аналога блока try - -[$result] ~&gt; { # Для сравнения по образцу использовать оператор проверки типа (имени класса) - [:ErrorParser] -&gt; {Код обработки ошибок парсера}; - [:ErrorRunTime] -&gt; {Код обработки ошибок времени выполнения}; - [:Error] -&gt; { Код обработки остальных ошибок }; - [_] -&gt; { Обработка нормальных данных $value без ошибок }; -}; -</code></pre><h2 id="сборка-repl-из-исходников-пока-только-под-linux">Сборка REPL из исходников (пока только под Linux)<a class="td-heading-self-link" href="#%d1%81%d0%b1%d0%be%d1%80%d0%ba%d0%b0-repl-%d0%b8%d0%b7-%d0%b8%d1%81%d1%85%d0%be%d0%b4%d0%bd%d0%b8%d0%ba%d0%be%d0%b2-%d0%bf%d0%be%d0%ba%d0%b0-%d1%82%d0%be%d0%bb%d1%8c%d0%ba%d0%be-%d0%bf%d0%be%d0%b4-linux" aria-label="Heading self-link"></a></h2> -<h3 id="подготовка-репозитория">Подготовка репозитория<a class="td-heading-self-link" href="#%d0%bf%d0%be%d0%b4%d0%b3%d0%be%d1%82%d0%be%d0%b2%d0%ba%d0%b0-%d1%80%d0%b5%d0%bf%d0%be%d0%b7%d0%b8%d1%82%d0%be%d1%80%d0%b8%d1%8f" aria-label="Heading self-link"></a></h3> -<ul> -<li><a href="https://github.com/rsashka/newlang"><u>Скачать исходники</u></a></li> -<li>Скачать и развернуть архив <a href="https://pytorch.org/">libtorch</a> в каталоге <em>contrib</em> (PyTorch Build: Stable (1.10.*) -&gt; Your OS: Linux -&gt; Package: LibTorch -&gt; Language: C++ / Java -&gt; Compute Platform: CPU -&gt; Download here (cxx11 ABI): -<a href="https://download.pytorch.org/libtorch/cpu/libtorch-cxx11-abi-shared-with-deps-1.10.2%2Bcpu.zip">libtorch-cxx11-abi-shared-with-deps-1.10.2+cpu.zip</a>)</li> -<li>Активировать и скачать исходники субмодулей (<code>git submodule init &amp;&amp; git submodule update</code>)</li> -<li>В каталоге <em>contrib</em> запустить файл <code>build.sh</code> для сборки библиотеки libffi</li> -<li>В каталоге <em>core</em> запустить файл <code>compile_syntax.sh</code> для генерации файлов парсера и лексического анализатора. Также может потребоваться установка утилит <em>flex</em> и <em>bison</em>. Если что, у меня установлены flex 2.6.4 и bison (GNU Bison) 3.7.4</li> -</ul> -<h3 id="собрать">Собрать<a class="td-heading-self-link" href="#%d1%81%d0%be%d0%b1%d1%80%d0%b0%d1%82%d1%8c" aria-label="Heading self-link"></a></h3> -<ul> -<li>Юнит-тесты (newlang_test): в каталоге <em>core</em> выполнить команду <code>make CONF=UnitTest</code>*</li> -<li>Интерпретатор (nlc): в каталоге <em>core</em> выполнить команду <code>make CONF=Debug</code>*</li> -</ul> -<hr> -<p>*) - Сборка проекта выполняется обычной утилитой make, но сборочные файлы генерируются автоматически в давно устаревшей версии NetBeans 8.2, т.к. это единственная универсальная среда разработки с поддержкой Makefile &ldquo;из коробки&rdquo;, тогда как в текущей версии Apache NetBeans полноценная поддержка разработки на С/С++ вообще отсутствует. Начал постепенный переход на использование редактора VSCodium (аналога VSCode, в котором вычищена телеметрия от Microsoft) и генерацию скриптов сборки с помощью сmake, но этот процесс пока не завершен.</p> -<h1 id="планы-на-будущее">Планы на будущее<a class="td-heading-self-link" href="#%d0%bf%d0%bb%d0%b0%d0%bd%d1%8b-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5" aria-label="Heading self-link"></a></h1> -<p>Текущая версия языка значительно обогатилась возможностями, но все еще является тестовой платформой для проверки декларируемых концепций и основного синтаксиса. Если говорить о планах, то в настоящий момент роадмап развития NewLang следующий:</p> -<ul> -<li>Реализовать макросы для более привычного использования языка (за счет использования DSL);</li> -<li>Добавить в арифметические типы длинные числа и дроби;</li> -<li>Сделать какую-нибудь логическую игру (крестики нолики, судоку или что-то похожее) с алгоритмическим выбором следующего хода и его вычислением с помощью машинного обучения;</li> -<li>Написать еще больше разных примеров для оценки синтаксиса;</li> -<li>Зафиксировать синтаксис с учетом полученного опыта и обратной связи;</li> -<li>Восстановить работоспособность компилятора для генерации исполняемых файлов;</li> -<li>Сделать очередную большую чистку кода;</li> -<li>Переработать и задокументировать получившуюся семантику языка с учетом всех возможностей и выпустить первую полнофункциональную версию NewLang.</li> -</ul> - - <ul class="list-unstyled d-flex justify-content-between align-items-center mb-0 pt-5"> - <li> - <a href="/blog/newlang/" aria-label="Previous - Новый язык программирования" class="btn btn-primary"><span class="me-1">←</span>Previous</a> - </li> - <li> - <a href="/blog/release-v0.2/" aria-label="Next - Релиз языка программрования NewLang 0.2" class="btn btn-primary">Next<span class="ms-1">→</span></a> - </li> -</ul> - - </div> - - - </main> - </div> - </div> - <footer class="td-footer row d-print-none"> - <div class="container-fluid"> - <div class="row mx-md-2"> - <div class="td-footer__left col-6 col-sm-4 order-sm-1"> - <ul class="td-footer__links-list"> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="User mailing list" aria-label="User mailing list"> - <a target="_blank" rel="noopener" href="mailto:mail@newlang.net" aria-label="User mailing list"> - <i class="fa fa-envelope"></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - -</ul> - - </div><div class="td-footer__right col-6 col-sm-4 order-sm-3"> - <ul class="td-footer__links-list"> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="GitHub" aria-label="GitHub"> - <a target="_blank" rel="noopener" href="https://github.com/rsashka/newlang" aria-label="GitHub"> - <i class="fab fa-github"></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - -</ul> - - </div><div class="td-footer__center col-12 col-sm-4 py-2 order-sm-2"> - <span class="td-footer__copyright">&copy; - 2024 - <span class="td-footer__authors">The NewLang Authors</span></span><span class="td-footer__all_rights_reserved">All Rights Reserved</span> - </div> - </div> - </div> -</footer> - - </div> - <script src="/js/main.js"></script> -<script defer src="/js/click-to-copy.js" crossorigin="anonymous"></script> -<script src='/js/tabpane-persist.js'></script> - - </body> -</html> \ No newline at end of file diff --git a/docs/blog/release-v0.2/index.html b/docs/blog/release-v0.2/index.html deleted file mode 100644 index fc5df6ce..00000000 --- a/docs/blog/release-v0.2/index.html +++ /dev/null @@ -1,437 +0,0 @@ -<!doctype html> -<html itemscope itemtype="http://schema.org/WebPage" lang="en" class="no-js"> - <head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script> - <meta charset="utf-8"> -<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> -<meta name="robots" content="noindex, nofollow"> - - -<link rel="shortcut icon" href="/favicons/favicon.ico" > -<link rel="apple-touch-icon" href="/favicons/apple-touch-icon-180x180.png" sizes="180x180"> -<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16"> -<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32"> -<link rel="icon" type="image/png" href="/favicons/android-36x36.png" sizes="36x36"> -<link rel="icon" type="image/png" href="/favicons/android-48x48.png" sizes="48x48"> -<link rel="icon" type="image/png" href="/favicons/android-72x72.png" sizes="72x72"> -<link rel="icon" type="image/png" href="/favicons/android-96x96.png" sizes="96x96"> -<link rel="icon" type="image/png" href="/favicons/android-144x144.png" sizes="144x144"> -<link rel="icon" type="image/png" href="/favicons/android-192x192.png" sizes="192x192"> - -<title>Релиз языка программрования NewLang 0.2 | NewLang</title> -<meta name="description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -NewLang - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения. -Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка)."> -<meta property="og:title" content="Релиз языка программрования NewLang 0.2" /> -<meta property="og:description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -NewLang - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения. -Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка)." /> -<meta property="og:type" content="article" /> -<meta property="og:url" content="http://localhost:1313/blog/release-v0.2/" /><meta property="article:section" content="blog" /> -<meta property="article:published_time" content="2022-08-12T00:00:00+00:00" /> -<meta property="article:modified_time" content="2024-03-22T23:57:08+03:00" /><meta property="og:site_name" content="NewLang" /> -<meta itemprop="name" content="Релиз языка программрования NewLang 0.2"> -<meta itemprop="description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -NewLang - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения. -Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка)."><meta itemprop="datePublished" content="2022-08-12T00:00:00+00:00" /> -<meta itemprop="dateModified" content="2024-03-22T23:57:08+03:00" /> -<meta itemprop="wordCount" content="704"> -<meta itemprop="keywords" content="" /><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Релиз языка программрования NewLang 0.2"/> -<meta name="twitter:description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -NewLang - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения. -Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка)."/> - - - - - -<link href="/scss/main.css" rel="stylesheet"> - -<script - src="https://code.jquery.com/jquery-3.6.3.min.js" - integrity="sha512-STof4xm1wgkfm7heWqFJVn58Hm3EtS31XFaagaa8VMReCXAkQnJZ+jEy8PCC/iT18dFy95WcExNHFTqLyp72eQ==" - crossorigin="anonymous"></script> -<script defer - src="https://unpkg.com/lunr@2.3.9/lunr.min.js" - integrity="sha384-203J0SNzyqHby3iU6hzvzltrWi/M41wOP5Gu+BiJMz5nwKykbkUx8Kp7iti0Lpli" - crossorigin="anonymous"></script> - - </head> - <body class="td-page td-blog"> - <header> - <nav class="td-navbar navbar-dark js-navbar-scroll"> -<div class="container-fluid flex-column flex-md-row"> - <a class="navbar-brand" href="/"><span class="navbar-brand__logo navbar-logo"><svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500" style="enable-background:new 0 0 500 500"><g><path style="fill:#fff" d="M116.8525 421.9722c-5.7041.0-10.3442-4.3127-10.3442-9.6129V88.183c0-5.3002 4.6401-9.6117 10.3442-9.6117H320.858c3.0347.0 9.3959.5498 11.7506 2.6302l.3545.3442 58.905 63.2912c2.3101 2.491 2.9202 8.4928 2.9202 11.3184v256.2039c0 5.3002-4.6407 9.6129-10.3436 9.6129H116.8525z"/><g><g><g><path style="fill:#767676" d="M384.4445 423.2066H116.852c-6.3839.0-11.5786-4.8658-11.5786-10.8474V88.1831c0-5.9804 5.1947-10.8461 11.5786-10.8461h204.0062c.377.0 9.2786.0329 12.568 2.9389l.3947.3833 58.9508 63.337c3.2135 3.4652 3.2514 11.7924 3.2514 12.1593v256.2036C396.0231 418.3408 390.8284 423.2066 384.4445 423.2066zM116.5079 411.9189c.0848.0278.1999.0531.3441.0531h267.5925c.1442.0.2581-.0253.3441-.0531V156.1556c-.0076-.9033-.3593-3.7347-.7034-5.0037l-57.6527-61.9416c-1.4651-.3176-4.4533-.6389-5.5742-.6389H116.852c-.143.0-.2594.024-.3441.0531V411.9189zm267.4533-261.149zM327.0321 89.371v.0013V89.371z"/></g></g></g><g><g><path style="fill:#5b7fc0" d="M189.0874 210.1754l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.025 2.454-11.4897 6.4116-15.4473C177.5953 212.627 183.0601 210.1742 189.0874 210.1754zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403S197.0816 234.1722 197.0804 232.033z"/><path style="opacity:.3;fill:#fff" d="M189.0898 210.176c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 212.6276 183.0612 210.176 189.0898 210.176zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 236.239 197.0839 234.2399 197.0839 232.0372z"/><g><defs><path id="SVGID_1_" d="M194.7376 237.6875c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.999 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 234.2399 196.1861 236.239 194.7376 237.6875z"/></defs><clipPath id="SVGID_2_"><use xlink:href="#SVGID_1_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_2_);fill:#fff" d="M190.0704 225.0237c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 225.7247 191.9774 225.0237 190.0704 225.0237z"/><path style="opacity:.13;clip-path:url(#SVGID_2_);fill:#020202" d="M190.0704 225.0237c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 225.7247 191.9774 225.0237 190.0704 225.0237z"/></g><g><defs><path id="SVGID_3_" d="M189.0898 210.176c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 212.6276 183.0612 210.176 189.0898 210.176zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 236.239 197.0839 234.2399 197.0839 232.0372z"/></defs><clipPath id="SVGID_4_"><use xlink:href="#SVGID_3_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_4_);fill:#5b7fc0" d="M172.6595 215.6045c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8612 12.0547.0024 21.8636-9.797 21.8613-21.8612.0024-3.8475-1.0151-7.6326-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 209.1953 176.6171 211.647 172.6595 215.6045z"/></g></g><rect x="198.8952" y="225.1043" style="fill:#5b7fc0" width="122.6266" height="13.8671"/></g><g><path style="fill:#d95140" d="M189.0874 155.7611l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.0249 2.454-11.4897 6.4116-15.4473C177.5953 158.2128 183.0601 155.7599 189.0874 155.7611zm7.993 21.8577c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403C196.2508 181.7667 197.0816 179.758 197.0804 177.6188z"/><path style="opacity:.3;fill:#fff" d="M189.0898 155.7617c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 158.2134 183.0612 155.7617 189.0898 155.7617zm7.9941 21.8613c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 181.8248 197.0839 179.8256 197.0839 177.623z"/><g><defs><path id="SVGID_5_" d="M194.7376 183.2733c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.9989 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 179.8256 196.1861 181.8248 194.7376 183.2733z"/></defs><clipPath id="SVGID_6_"><use xlink:href="#SVGID_5_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_6_);fill:#fff" d="M190.0704 170.6095c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 171.3104 191.9774 170.6095 190.0704 170.6095z"/><path style="opacity:.13;clip-path:url(#SVGID_6_);fill:#020202" d="M190.0704 170.6095c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 171.3104 191.9774 170.6095 190.0704 170.6095z"/></g><g><defs><path id="SVGID_7_" d="M189.0898 155.7617c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 158.2134 183.0612 155.7617 189.0898 155.7617zm7.9941 21.8613c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 181.8248 197.0839 179.8256 197.0839 177.623z"/></defs><clipPath id="SVGID_8_"><use xlink:href="#SVGID_7_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_8_);fill:#d95140" d="M172.6595 161.1903c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8613 12.0547.0024 21.8636-9.797 21.8613-21.8613.0024-3.8474-1.0151-7.6326-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 154.7811 176.6171 157.2327 172.6595 161.1903z"/></g><rect x="198.8952" y="170.69" style="fill:#d95140" width="122.6266" height="13.8671"/></g><g><g><path style="fill:#56a55c" d="M189.5379 264.6147l.0012-.0012c7.7751.0012 15.0294 4.1862 18.932 10.9235 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032-5.8394.0-11.3281-2.2733-15.458-6.4032-4.13-4.13-6.4032-9.6186-6.4056-15.4628.0012-6.0249 2.454-11.4897 6.4116-15.4472C178.0458 267.0663 183.5105 264.6135 189.5379 264.6147zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6538 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403C196.7013 290.6202 197.5321 288.6115 197.5309 286.4723z"/><path style="opacity:.3;fill:#fff" d="M189.5403 264.6153c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8065-21.8612-21.8613.0-6.0285 2.4516-11.492 6.4116-15.452C178.0482 267.0669 183.5117 264.6153 189.5403 264.6153zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.6366 290.6783 197.5344 288.6792 197.5344 286.4765z"/><g><defs><path id="SVGID_9_" d="M195.1881 292.1268c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.9989 7.9942-7.9941 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.5344 288.6792 196.6366 290.6783 195.1881 292.1268z"/></defs><clipPath id="SVGID_10_"><use xlink:href="#SVGID_9_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_10_);fill:#fff" d="M190.5209 279.463c-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7446-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9941 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C194.239 280.164 192.4279 279.463 190.5209 279.463z"/><path style="opacity:.13;clip-path:url(#SVGID_10_);fill:#020202" d="M190.5209 279.463c-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7446-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9941 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C194.239 280.164 192.4279 279.463 190.5209 279.463z"/></g><g><defs><path id="SVGID_11_" d="M189.5403 264.6153c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8065-21.8612-21.8613.0-6.0285 2.4516-11.492 6.4116-15.452C178.0482 267.0669 183.5117 264.6153 189.5403 264.6153zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.6366 290.6783 197.5344 288.6792 197.5344 286.4765z"/></defs><clipPath id="SVGID_12_"><use xlink:href="#SVGID_11_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_12_);fill:#56a55c" d="M173.11 270.0439c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8613 12.0547.0024 21.8636-9.797 21.8613-21.8613.0024-3.8474-1.0151-7.6326-2.9353-10.9462-3.8977-6.7325-11.1497-10.9151-18.926-10.9151C182.5311 263.6346 177.0676 266.0863 173.11 270.0439z"/></g></g><rect x="199.3456" y="279.5436" style="fill:#56a55c" width="122.6266" height="13.8671"/></g><g><g><path style="fill:#f1bc42" d="M189.0874 318.7208l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3305-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.025 2.454-11.4897 6.4116-15.4472C177.5953 321.1724 183.0601 318.7196 189.0874 318.7208zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403S197.0816 342.7176 197.0804 340.5784z"/><path style="opacity:.3;fill:#fff" d="M189.0898 318.7214c7.7763.0 15.0283 4.1826 18.926 10.915 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8612-12.0547.0024-21.8636-9.8065-21.8612-21.8612.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 321.173 183.0612 318.7214 189.0898 318.7214zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 344.7844 197.0839 342.7853 197.0839 340.5826z"/><g><defs><path id="SVGID_13_" d="M194.7376 346.2329c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.999 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 342.7853 196.1861 344.7844 194.7376 346.2329z"/></defs><clipPath id="SVGID_14_"><use xlink:href="#SVGID_13_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_14_);fill:#fff" d="M190.0704 333.5691c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0834 6.1218 2.8788C193.7885 334.2701 191.9774 333.5691 190.0704 333.5691z"/><path style="opacity:.13;clip-path:url(#SVGID_14_);fill:#020202" d="M190.0704 333.5691c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0834 6.1218 2.8788C193.7885 334.2701 191.9774 333.5691 190.0704 333.5691z"/></g><g><defs><path id="SVGID_15_" d="M189.0898 318.7214c7.7763.0 15.0283 4.1826 18.926 10.915 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8612-12.0547.0024-21.8636-9.8065-21.8612-21.8612.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 321.173 183.0612 318.7214 189.0898 318.7214zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 344.7844 197.0839 342.7853 197.0839 340.5826z"/></defs><clipPath id="SVGID_16_"><use xlink:href="#SVGID_15_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_16_);fill:#f1bc42" d="M172.6595 324.15c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8612 12.0547.0024 21.8636-9.797 21.8613-21.8612.0024-3.8474-1.0151-7.6327-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 317.7407 176.6171 320.1924 172.6595 324.15z"/></g></g><rect x="198.8952" y="333.6497" style="fill:#f1bc42" width="122.6266" height="13.8671"/></g></g></svg></span><span class="navbar-brand__name">NewLang</span></a> - <div class="td-navbar-nav-scroll ms-md-auto" id="main_navbar"> - <ul class="navbar-nav"> - <li class="nav-item"> - <a class="nav-link" href="/docs/"><span>Documentation</span></a> - </li> - <li class="nav-item"> - <a class="nav-link" href="/playground/"><span>Playground</span></a> - </li> - <li class="nav-item"> - <a class="nav-link active" href="/blog/"><span>Articles</span></a> - </li> - <li class="nav-item dropdown d-none d-lg-block"> - <div class="dropdown"> - <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">English</a> - <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/ru/blog/release-v0.2/">Русский</a></li> - </ul> -</div></li> - </ul> - </div> - <div class="d-none d-lg-block"> - <div class="td-search td-search--offline"> - <div class="td-search__icon"></div> - <input - type="search" - class="td-search__input form-control" - placeholder="Search this site…" - aria-label="Search this site…" - autocomplete="off" - - data-offline-search-index-json-src="/offline-search-index.json" - data-offline-search-base-href="/" - data-offline-search-max-results="10" - > -</div> - </div> -</div> -</nav> - </header> - <div class="container-fluid td-outer"> - <div class="td-main"> - <div class="row flex-xl-nowrap"> - <aside class="col-12 col-md-3 col-xl-2 td-sidebar d-print-none"> - <div id="td-sidebar-menu" class="td-sidebar__inner"> - <form class="td-sidebar__search d-flex align-items-center"> - <div class="td-search td-search--offline"> - <div class="td-search__icon"></div> - <input - type="search" - class="td-search__input form-control" - placeholder="Search this site…" - aria-label="Search this site…" - autocomplete="off" - - data-offline-search-index-json-src="/offline-search-index.json" - data-offline-search-base-href="/" - data-offline-search-max-results="10" - > -</div> - <button class="btn btn-link td-sidebar__toggle d-md-none p-0 ms-3 fas fa-bars" type="button" data-bs-toggle="collapse" data-bs-target="#td-section-nav" aria-controls="td-section-nav" aria-expanded="false" aria-label="Toggle section navigation"> - </button> - </form> - <nav class="td-sidebar-nav collapse" id="td-section-nav"> - <div class="td-sidebar-nav__section nav-item dropdown d-block d-lg-none"> - <div class="dropdown"> - <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">English</a> - <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/ru/blog/release-v0.2/">Русский</a></li> - </ul> -</div> - </div> - <ul class="td-sidebar-nav__section pe-md-3 ul-0"> - <li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child active-path" id="m-blog-li"> - <a href="/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-blog"><span class="">Articles</span></a> - <ul class="ul-1"> - <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v04-li"> - <a href="/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogparser-nuances-li"> - <a href="/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogdsl-domain-specific-language-implementation-with-macros-li"> - <a href="/blog/dsl-domain-specific-language-implementation-with-macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogdsl-domain-specific-language-implementation-with-macros"><span class="">DSL (domain-specific language) implementation with macros</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v03-li"> - <a href="/blog/release-v0.3/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v03"><span class="">Релиз языка программрования NewLang 0.3</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child active-path" id="m-blogrelease-v02-li"> - <a href="/blog/release-v0.2/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v02"><span class="td-sidebar-nav-active-item">Релиз языка программрования NewLang 0.2</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v01-li"> - <a href="/blog/release-v0.1/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v01"><span class="">Релиз языка программрования NewLang</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blognewlang-li"> - <a href="/blog/newlang/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blognewlang"><span class="">Новый язык программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogprog-styles-same-time-li"> - <a href="/blog/prog-styles-same-time/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogprog-styles-same-time"><span class="">Можно ли использовать декларативный и императивный стили написания программ одновременно?</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogunusual-prog-li"> - <a href="/blog/unusual-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogunusual-prog"><span class="">Необычная концепция синтаксиса языка программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogcomplex-prog-li"> - <a href="/blog/complex-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogcomplex-prog"><span class="">Простое сложное программирование</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloglang-final-li"> - <a href="/blog/lang-final/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloglang-final"><span class="">Какая «идеальная» цель развития у языков программирования?</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloglogic-prog-li"> - <a href="/blog/logic-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloglogic-prog"><span class="">Проблема логических языков программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloginter-prog-li"> - <a href="/blog/inter-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloginter-prog"><span class="">Интернациональное программирование на естественных языках</span></a> -</li> - </ul> -</li> - </ul> - </nav> -</div> - - </aside> - <aside class="d-none d-xl-block col-xl-2 td-sidebar-toc d-print-none"> - <div class="td-page-meta ms-2 pb-1 pt-2 mb-0"> -<a id="print" href="/blog/_print/"><i class="fa-solid fa-print fa-fw"></i> Print entire section</a> - -</div> - - <div class="td-toc"> - <nav id="TableOfContents"> - <ul> - <li><a href="#особенности-языка">Особенности языка:</a></li> - <li><a href="#новые-глобальные-фичи">Новые глобальные фичи:</a></li> - <li><a href="#изменения-в-синтаксисе">Изменения в синтаксисе:</a></li> - <li><a href="#подробная-информация-о-языке">Подробная информация о языке:</a></li> - <li><a href="#примеры-кода">Примеры кода</a></li> - </ul> -</nav> - </div> - - <div class="taxonomy taxonomy-terms-cloud taxo-tags"> - <h5 class="taxonomy-title">Tag Cloud</h5> - <ul class="taxonomy-terms"> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B/" data-taxonomy-term="%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B"><span class="taxonomy-label">Итераторы</span><span class="taxonomy-count">1</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8/" data-taxonomy-term="%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8"><span class="taxonomy-label">Коллекции</span><span class="taxonomy-count">4</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%BE%D0%BE%D0%BF/" data-taxonomy-term="%D0%BE%D0%BE%D0%BF"><span class="taxonomy-label">ООП</span><span class="taxonomy-count">3</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B/" data-taxonomy-term="%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B"><span class="taxonomy-label">Системые Типы</span><span class="taxonomy-count">1</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85/" data-taxonomy-term="%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85"><span class="taxonomy-label">Типы Данных</span><span class="taxonomy-count">8</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8/" data-taxonomy-term="%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8"><span class="taxonomy-label">Функции</span><span class="taxonomy-count">1</span></a></li> - </ul> - </div> - - - </aside> - <main class="col-12 col-md-9 col-xl-8 ps-md-5 pe-md-4" role="main"> - <a class="td-rss-button" title="RSS" href="/blog/index.xml" target="_blank" rel="noopener"> - <i class="fa-solid fa-rss" aria-hidden="true"></i> - </a> - -<div class="td-content"> - <h1>Релиз языка программрования NewLang 0.2</h1> - - <div class="td-byline mb-4"> - - <time datetime="2022-08-12" class="text-muted">Friday, August 12, 2022</time> - </div> - <header class="article-meta"> - - </header> - <p><img alt="КДПВ" src="/blog/langs.jpeg"></p> - - -<div class="pageinfo pageinfo-primary"> -<p>Внимание!!!</p> -<p>Данная статья содержит описание синтаксиса NewLnag предыдущей версии.</p> -<p>Актуальную версию синтаксиса языка можно посмотреть <a href="/docs/">тут</a>.</p> - -</div> - -<p><em>NewLang</em> - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения.</p> -<p>Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка).</p> -<p><em>NewLang</em> находится в процессе активного развития и это второй публичный релиз в котором добавлены существенные новые возможности и произошли некоторые изменения по сравнению с <a href="https://habr.com/company/timeweb/blog/673176/">предыдущей версией</a>.</p> -<h2 id="особенности-языка">Особенности языка:<a class="td-heading-self-link" href="#%d0%be%d1%81%d0%be%d0%b1%d0%b5%d0%bd%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d1%8f%d0%b7%d1%8b%d0%ba%d0%b0" aria-label="Heading self-link"></a></h2> -<ul> -<li>Возможность работы как в режиме интерпретатора, так и компилятора*.</li> -<li>Динамическая и статическая типизация с возможностью указания типов в явном виде.</li> -<li>Статическая типизация является условно строгой (автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных, например, целое число может быть автоматически преобразовано в вещественное или рациональное, но не наоборот).</li> -<li>Автоматическое управление памятью.</li> -<li>ООП в виде явного наследования классов и «утиная» типизация.</li> -<li>На уровне синтаксиса поддержка нескольких типов функций (обычные и чистые функции без побочных эффектов).</li> -<li>Необязательные и именованные параметры функций.</li> -<li>Возможны вставки кода на языке реализации (С/С++)*.</li> -<li>Простая интеграция с уже существующими программными библиотеками (в том числе импорт нативных переменных и функций из С/С++).</li> -<li>Имеется REPL read-eval-print loop — «цикл: чтение — вычисление — вывод».</li> -</ul> -<h2 id="новые-глобальные-фичи">Новые глобальные фичи:<a class="td-heading-self-link" href="#%d0%bd%d0%be%d0%b2%d1%8b%d0%b5-%d0%b3%d0%bb%d0%be%d0%b1%d0%b0%d0%bb%d1%8c%d0%bd%d1%8b%d0%b5-%d1%84%d0%b8%d1%87%d0%b8" aria-label="Heading self-link"></a></h2> -<ul> -<li>Добавлены макросы. Теперь можно делать собственные языковые диалекты и использовать более привычную запись алгоритмических конструкций с использование ключевых слов. -Например, цикл</li> -</ul> -<pre tabindex="0"><code>[ cond ] &lt;-&gt; { - тело цикла -}; -</code></pre><p>можно записать в более привычный нотации</p> -<pre tabindex="0"><code>\while (cond) { - тело цикла -}; -</code></pre><ul> -<li>Добавлены итераторы для перебора элементов словарей или для запросов к другим контейнерам (например, к базам данных). На уровне базового синтаксиса поддерживается фильтрация данный, включая функциональный аналог LINQ за счет применения функций обратного вызова в качестве условия фильтра.</li> -<li>Добавлен новый тип данных — рациональные числа с неограниченной точностью. Они записываются в виде обыкновенной дроби, у которой разделитель бекслеш, например единицу можно записать <code>1\1</code>, а число 0.5 как <code>1\2</code>.</li> -<li>Реализован оператор распаковки словаря <strong>…</strong> (многоточие), который можно использовать чтобы передать несколько аргументов при вызове функции или для присвоения значения сразу нескольким переменным.</li> -<li>Теперь оператор присвоения поддерживает установку значений сразу нескольким переменным. С правой стороны от оператора присвоения может находится одно или несколько значений или оператор распаковки словаря. Причем словарь может быть указан и с левой стороны от оператора присвоения и таким образом можно записать самый простой способ перебора всех его элементов, когда в цикле первый элемент словаря сохраняется в переменную <em>item</em>, а из самого словаря удаляется:</li> -</ul> -<pre tabindex="0"><code>[ dict ] &lt;-&gt; { - item, dict := ... dict; -}; -</code></pre><h2 id="изменения-в-синтаксисе">Изменения в синтаксисе:<a class="td-heading-self-link" href="#%d0%b8%d0%b7%d0%bc%d0%b5%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b2-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81%d0%b5" aria-label="Heading self-link"></a></h2> -<ul> -<li>Изменена запись циклов. Вместо двух разных типов с предусловием и постусловие, теперь используется единая форма записи, а тип цикла определяется взаимным расположением условия и его тела.</li> -<li>Изменены названия арифметических и некоторых других типов данных на более логичные. В именах арифметических типов теперь указан их размер (Int8, Int16 … Float32, Float64 и т.д.).</li> -<li>Многострочные комментарии стали вложенными</li> -</ul> -<h2 id="подробная-информация-о-языке">Подробная информация о языке:<a class="td-heading-self-link" href="#%d0%bf%d0%be%d0%b4%d1%80%d0%be%d0%b1%d0%bd%d0%b0%d1%8f-%d0%b8%d0%bd%d1%84%d0%be%d1%80%d0%bc%d0%b0%d1%86%d0%b8%d1%8f-%d0%be-%d1%8f%d0%b7%d1%8b%d0%ba%d0%b5" aria-label="Heading self-link"></a></h2> -<ul> -<li><a href="/docs/syntax/">Основные правила синтаксиса:</a></li> -<li><a href="/docs/types/">Встроенные типы данных:</a></li> -<li><a href="/docs/ops/">Операторы и управляющие конструкции:</a></li> -</ul> -<h2 id="примеры-кода">Примеры кода<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80%d1%8b-%d0%ba%d0%be%d0%b4%d0%b0" aria-label="Heading self-link"></a></h2> -<spoiler title="Привет, мир!"> -``` -#!../output/nlc --eval -<h1 id="определение-функции-hello">Определение функции hello<a class="td-heading-self-link" href="#%d0%be%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-hello" aria-label="Heading self-link"></a></h1> -<p>hello(str) := {</p> -<pre><code># Импорт стандартной C функции -printf := :Pointer('printf(format:FmtChar, ...):Int32'); - -# Вызов C функции с проверкой типов аргументов по строке формата -printf('%s', $str); - -# Возврат значения из функции hello - $str; -</code></pre> -<p>};</p> -<p>hello(&lsquo;Привет, мир!&rsquo;); # Вызвать функцию</p> -<pre tabindex="0"><code>Вывод (первая строка выводится с помощью printf, а вторая - возвращаемое значение функции hello): -</code></pre><pre><code>Привет, мир! -Привет, мир! -</code></pre> -<pre tabindex="0"><code class="language-</spoiler>" data-lang="</spoiler>"> -&lt;spoiler title=&#34;Пример скрипта для вычисления факториала 1000&#34;&gt; -</code></pre><p>#!../output/nlc &ndash;eval</p> -<p>@fact := 1\1; # Рациональное число без ограничения точности -@mult := 1000..1..-1?; # Сделать из диапазона итератор для множителей от 1000 до 2 -[mult ?!] &lt;-&gt; { # Цикл, пока не закончатся данные итератора -# Получить текущий множитель и перейти на следующий элемент итератора -fact *= mult !; -}; -fact # Вывести итоговый результат</p> -<pre tabindex="0"><code>Вывод: -</code></pre><p>402387260077093773543702433923003985719374864210714632543799910429938512398629 -020592044208486969404800479988610197196058631666872994808558901323829669944590 -997424504087073759918823627727188732519779505950995276120874975462497043601418 -278094646496291056393887437886487337119181045825783647849977012476632889835955 -735432513185323958463075557409114262417474349347553428646576611667797396668820 -291207379143853719588249808126867838374559731746136085379534524221586593201928 -090878297308431392844403281231558611036976801357304216168747609675871348312025 -478589320767169132448426236131412508780208000261683151027341827977704784635868 -170164365024153691398281264810213092761244896359928705114964975419909342221566 -832572080821333186116811553615836546984046708975602900950537616475847728421889 -679646244945160765353408198901385442487984959953319101723355556602139450399736 -280750137837615307127761926849034352625200015888535147331611702103968175921510 -907788019393178114194545257223865541461062892187960223838971476088506276862967 -146674697562911234082439208160153780889893964518263243671616762179168909779911 -903754031274622289988005195444414282012187361745992642956581746628302955570299 -024324153181617210465832036786906117260158783520751516284225540265170483304226 -143974286933061690897968482590125458327168226458066526769958652682272807075781 -391858178889652208164348344825993266043367660176999612831860788386150279465955 -131156552036093988180612138558600301435694527224206344631797460594682573103790 -084024432438465657245014402821885252470935190620929023136493273497565513958720 -559654228749774011413346962715422845862377387538230483865688976461927383814900 -140767310446640259899490222221765904339901886018566526485061799702356193897017 -860040811889729918311021171229845901641921068884387121855646124960798722908519 -296819372388642614839657382291123125024186649353143970137428531926649875337218 -940694281434118520158014123344828015051399694290153483077644569099073152433278 -288269864602789864321139083506217095002597389863554277196742822248757586765752 -344220207573630569498825087968928162753848863396909959826280956121450994871701 -244516461260379029309120889086942028510640182154399457156805941872748998094254 -742173582401063677404595741785160829230135358081840096996372524230560855903700 -624271243416909004153690105933983835777939410970027753472000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000\1</p> -<pre tabindex="0"><code class="language-</spoiler>" data-lang="</spoiler>"> -## Как посмотреть? -- [Загрузить собранный REPL и тесты (пока только под Ubuntu)](https://github.com/rsashka/newlang/releases/download/v0.2.0/nlc_bin.tar.xz) -- Для запуска бинарных файлов потребуются разделяемые библиотеки libLLVM-13 и libtorch: [архив только с нужными библиотеками](https://github.com/rsashka/newlang/releases/download/v0.2.0/nlc_so.tar.xz). -- Так же все можно собрать напрямую из исходников по инструкции в [репозитории](https://github.com/rsashka/newlang) -</code></pre> - <ul class="list-unstyled d-flex justify-content-between align-items-center mb-0 pt-5"> - <li> - <a href="/blog/release-v0.1/" aria-label="Previous - Релиз языка программрования NewLang" class="btn btn-primary"><span class="me-1">←</span>Previous</a> - </li> - <li> - <a href="/blog/release-v0.3/" aria-label="Next - Релиз языка программрования NewLang 0.3" class="btn btn-primary">Next<span class="ms-1">→</span></a> - </li> -</ul> - - </div> - - - </main> - </div> - </div> - <footer class="td-footer row d-print-none"> - <div class="container-fluid"> - <div class="row mx-md-2"> - <div class="td-footer__left col-6 col-sm-4 order-sm-1"> - <ul class="td-footer__links-list"> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="User mailing list" aria-label="User mailing list"> - <a target="_blank" rel="noopener" href="mailto:mail@newlang.net" aria-label="User mailing list"> - <i class="fa fa-envelope"></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - -</ul> - - </div><div class="td-footer__right col-6 col-sm-4 order-sm-3"> - <ul class="td-footer__links-list"> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="GitHub" aria-label="GitHub"> - <a target="_blank" rel="noopener" href="https://github.com/rsashka/newlang" aria-label="GitHub"> - <i class="fab fa-github"></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - -</ul> - - </div><div class="td-footer__center col-12 col-sm-4 py-2 order-sm-2"> - <span class="td-footer__copyright">&copy; - 2024 - <span class="td-footer__authors">The NewLang Authors</span></span><span class="td-footer__all_rights_reserved">All Rights Reserved</span> - </div> - </div> - </div> -</footer> - - </div> - <script src="/js/main.js"></script> -<script defer src="/js/click-to-copy.js" crossorigin="anonymous"></script> -<script src='/js/tabpane-persist.js'></script> - - </body> -</html> \ No newline at end of file diff --git a/docs/blog/release-v0.3/index.html b/docs/blog/release-v0.3/index.html deleted file mode 100644 index 53433cdb..00000000 --- a/docs/blog/release-v0.3/index.html +++ /dev/null @@ -1,506 +0,0 @@ -<!doctype html> -<html itemscope itemtype="http://schema.org/WebPage" lang="en" class="no-js"> - <head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script> - <meta charset="utf-8"> -<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> -<meta name="robots" content="noindex, nofollow"> - - -<link rel="shortcut icon" href="/favicons/favicon.ico" > -<link rel="apple-touch-icon" href="/favicons/apple-touch-icon-180x180.png" sizes="180x180"> -<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16"> -<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32"> -<link rel="icon" type="image/png" href="/favicons/android-36x36.png" sizes="36x36"> -<link rel="icon" type="image/png" href="/favicons/android-48x48.png" sizes="48x48"> -<link rel="icon" type="image/png" href="/favicons/android-72x72.png" sizes="72x72"> -<link rel="icon" type="image/png" href="/favicons/android-96x96.png" sizes="96x96"> -<link rel="icon" type="image/png" href="/favicons/android-144x144.png" sizes="144x144"> -<link rel="icon" type="image/png" href="/favicons/android-192x192.png" sizes="192x192"> - -<title>Релиз языка программрования NewLang 0.3 | NewLang</title> -<meta name="description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -NewLang — это язык программирования высокого уровня общего назначения. Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан на строгой системе грамматических правил. За счет использования макросов, синтаксис языка легко расширяется до более привычного вида на основе ключевых слов. -NewLang находится в процессе активного развития. Это третий публичный релиз в который добавлены новые существенные возможности по сравнению с предыдущей версией."> -<meta property="og:title" content="Релиз языка программрования NewLang 0.3" /> -<meta property="og:description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -NewLang — это язык программирования высокого уровня общего назначения. Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан на строгой системе грамматических правил. За счет использования макросов, синтаксис языка легко расширяется до более привычного вида на основе ключевых слов. -NewLang находится в процессе активного развития. Это третий публичный релиз в который добавлены новые существенные возможности по сравнению с предыдущей версией." /> -<meta property="og:type" content="article" /> -<meta property="og:url" content="http://localhost:1313/blog/release-v0.3/" /><meta property="article:section" content="blog" /> -<meta property="article:published_time" content="2022-11-07T00:00:00+00:00" /> -<meta property="article:modified_time" content="2024-03-22T23:57:08+03:00" /><meta property="og:site_name" content="NewLang" /> -<meta itemprop="name" content="Релиз языка программрования NewLang 0.3"> -<meta itemprop="description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -NewLang — это язык программирования высокого уровня общего назначения. Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан на строгой системе грамматических правил. За счет использования макросов, синтаксис языка легко расширяется до более привычного вида на основе ключевых слов. -NewLang находится в процессе активного развития. Это третий публичный релиз в который добавлены новые существенные возможности по сравнению с предыдущей версией."><meta itemprop="datePublished" content="2022-11-07T00:00:00+00:00" /> -<meta itemprop="dateModified" content="2024-03-22T23:57:08+03:00" /> -<meta itemprop="wordCount" content="1535"> -<meta itemprop="keywords" content="" /><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Релиз языка программрования NewLang 0.3"/> -<meta name="twitter:description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -NewLang — это язык программирования высокого уровня общего назначения. Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан на строгой системе грамматических правил. За счет использования макросов, синтаксис языка легко расширяется до более привычного вида на основе ключевых слов. -NewLang находится в процессе активного развития. Это третий публичный релиз в который добавлены новые существенные возможности по сравнению с предыдущей версией."/> - - - - - -<link href="/scss/main.css" rel="stylesheet"> - -<script - src="https://code.jquery.com/jquery-3.6.3.min.js" - integrity="sha512-STof4xm1wgkfm7heWqFJVn58Hm3EtS31XFaagaa8VMReCXAkQnJZ+jEy8PCC/iT18dFy95WcExNHFTqLyp72eQ==" - crossorigin="anonymous"></script> -<script defer - src="https://unpkg.com/lunr@2.3.9/lunr.min.js" - integrity="sha384-203J0SNzyqHby3iU6hzvzltrWi/M41wOP5Gu+BiJMz5nwKykbkUx8Kp7iti0Lpli" - crossorigin="anonymous"></script> - - </head> - <body class="td-page td-blog"> - <header> - <nav class="td-navbar navbar-dark js-navbar-scroll"> -<div class="container-fluid flex-column flex-md-row"> - <a class="navbar-brand" href="/"><span class="navbar-brand__logo navbar-logo"><svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500" style="enable-background:new 0 0 500 500"><g><path style="fill:#fff" d="M116.8525 421.9722c-5.7041.0-10.3442-4.3127-10.3442-9.6129V88.183c0-5.3002 4.6401-9.6117 10.3442-9.6117H320.858c3.0347.0 9.3959.5498 11.7506 2.6302l.3545.3442 58.905 63.2912c2.3101 2.491 2.9202 8.4928 2.9202 11.3184v256.2039c0 5.3002-4.6407 9.6129-10.3436 9.6129H116.8525z"/><g><g><g><path style="fill:#767676" d="M384.4445 423.2066H116.852c-6.3839.0-11.5786-4.8658-11.5786-10.8474V88.1831c0-5.9804 5.1947-10.8461 11.5786-10.8461h204.0062c.377.0 9.2786.0329 12.568 2.9389l.3947.3833 58.9508 63.337c3.2135 3.4652 3.2514 11.7924 3.2514 12.1593v256.2036C396.0231 418.3408 390.8284 423.2066 384.4445 423.2066zM116.5079 411.9189c.0848.0278.1999.0531.3441.0531h267.5925c.1442.0.2581-.0253.3441-.0531V156.1556c-.0076-.9033-.3593-3.7347-.7034-5.0037l-57.6527-61.9416c-1.4651-.3176-4.4533-.6389-5.5742-.6389H116.852c-.143.0-.2594.024-.3441.0531V411.9189zm267.4533-261.149zM327.0321 89.371v.0013V89.371z"/></g></g></g><g><g><path style="fill:#5b7fc0" d="M189.0874 210.1754l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.025 2.454-11.4897 6.4116-15.4473C177.5953 212.627 183.0601 210.1742 189.0874 210.1754zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403S197.0816 234.1722 197.0804 232.033z"/><path style="opacity:.3;fill:#fff" d="M189.0898 210.176c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 212.6276 183.0612 210.176 189.0898 210.176zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 236.239 197.0839 234.2399 197.0839 232.0372z"/><g><defs><path id="SVGID_1_" d="M194.7376 237.6875c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.999 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 234.2399 196.1861 236.239 194.7376 237.6875z"/></defs><clipPath id="SVGID_2_"><use xlink:href="#SVGID_1_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_2_);fill:#fff" d="M190.0704 225.0237c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 225.7247 191.9774 225.0237 190.0704 225.0237z"/><path style="opacity:.13;clip-path:url(#SVGID_2_);fill:#020202" d="M190.0704 225.0237c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 225.7247 191.9774 225.0237 190.0704 225.0237z"/></g><g><defs><path id="SVGID_3_" d="M189.0898 210.176c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 212.6276 183.0612 210.176 189.0898 210.176zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 236.239 197.0839 234.2399 197.0839 232.0372z"/></defs><clipPath id="SVGID_4_"><use xlink:href="#SVGID_3_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_4_);fill:#5b7fc0" d="M172.6595 215.6045c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8612 12.0547.0024 21.8636-9.797 21.8613-21.8612.0024-3.8475-1.0151-7.6326-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 209.1953 176.6171 211.647 172.6595 215.6045z"/></g></g><rect x="198.8952" y="225.1043" style="fill:#5b7fc0" width="122.6266" height="13.8671"/></g><g><path style="fill:#d95140" d="M189.0874 155.7611l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.0249 2.454-11.4897 6.4116-15.4473C177.5953 158.2128 183.0601 155.7599 189.0874 155.7611zm7.993 21.8577c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403C196.2508 181.7667 197.0816 179.758 197.0804 177.6188z"/><path style="opacity:.3;fill:#fff" d="M189.0898 155.7617c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 158.2134 183.0612 155.7617 189.0898 155.7617zm7.9941 21.8613c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 181.8248 197.0839 179.8256 197.0839 177.623z"/><g><defs><path id="SVGID_5_" d="M194.7376 183.2733c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.9989 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 179.8256 196.1861 181.8248 194.7376 183.2733z"/></defs><clipPath id="SVGID_6_"><use xlink:href="#SVGID_5_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_6_);fill:#fff" d="M190.0704 170.6095c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 171.3104 191.9774 170.6095 190.0704 170.6095z"/><path style="opacity:.13;clip-path:url(#SVGID_6_);fill:#020202" d="M190.0704 170.6095c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 171.3104 191.9774 170.6095 190.0704 170.6095z"/></g><g><defs><path id="SVGID_7_" d="M189.0898 155.7617c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 158.2134 183.0612 155.7617 189.0898 155.7617zm7.9941 21.8613c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 181.8248 197.0839 179.8256 197.0839 177.623z"/></defs><clipPath id="SVGID_8_"><use xlink:href="#SVGID_7_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_8_);fill:#d95140" d="M172.6595 161.1903c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8613 12.0547.0024 21.8636-9.797 21.8613-21.8613.0024-3.8474-1.0151-7.6326-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 154.7811 176.6171 157.2327 172.6595 161.1903z"/></g><rect x="198.8952" y="170.69" style="fill:#d95140" width="122.6266" height="13.8671"/></g><g><g><path style="fill:#56a55c" d="M189.5379 264.6147l.0012-.0012c7.7751.0012 15.0294 4.1862 18.932 10.9235 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032-5.8394.0-11.3281-2.2733-15.458-6.4032-4.13-4.13-6.4032-9.6186-6.4056-15.4628.0012-6.0249 2.454-11.4897 6.4116-15.4472C178.0458 267.0663 183.5105 264.6135 189.5379 264.6147zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6538 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403C196.7013 290.6202 197.5321 288.6115 197.5309 286.4723z"/><path style="opacity:.3;fill:#fff" d="M189.5403 264.6153c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8065-21.8612-21.8613.0-6.0285 2.4516-11.492 6.4116-15.452C178.0482 267.0669 183.5117 264.6153 189.5403 264.6153zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.6366 290.6783 197.5344 288.6792 197.5344 286.4765z"/><g><defs><path id="SVGID_9_" d="M195.1881 292.1268c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.9989 7.9942-7.9941 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.5344 288.6792 196.6366 290.6783 195.1881 292.1268z"/></defs><clipPath id="SVGID_10_"><use xlink:href="#SVGID_9_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_10_);fill:#fff" d="M190.5209 279.463c-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7446-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9941 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C194.239 280.164 192.4279 279.463 190.5209 279.463z"/><path style="opacity:.13;clip-path:url(#SVGID_10_);fill:#020202" d="M190.5209 279.463c-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7446-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9941 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C194.239 280.164 192.4279 279.463 190.5209 279.463z"/></g><g><defs><path id="SVGID_11_" d="M189.5403 264.6153c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8065-21.8612-21.8613.0-6.0285 2.4516-11.492 6.4116-15.452C178.0482 267.0669 183.5117 264.6153 189.5403 264.6153zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.6366 290.6783 197.5344 288.6792 197.5344 286.4765z"/></defs><clipPath id="SVGID_12_"><use xlink:href="#SVGID_11_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_12_);fill:#56a55c" d="M173.11 270.0439c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8613 12.0547.0024 21.8636-9.797 21.8613-21.8613.0024-3.8474-1.0151-7.6326-2.9353-10.9462-3.8977-6.7325-11.1497-10.9151-18.926-10.9151C182.5311 263.6346 177.0676 266.0863 173.11 270.0439z"/></g></g><rect x="199.3456" y="279.5436" style="fill:#56a55c" width="122.6266" height="13.8671"/></g><g><g><path style="fill:#f1bc42" d="M189.0874 318.7208l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3305-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.025 2.454-11.4897 6.4116-15.4472C177.5953 321.1724 183.0601 318.7196 189.0874 318.7208zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403S197.0816 342.7176 197.0804 340.5784z"/><path style="opacity:.3;fill:#fff" d="M189.0898 318.7214c7.7763.0 15.0283 4.1826 18.926 10.915 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8612-12.0547.0024-21.8636-9.8065-21.8612-21.8612.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 321.173 183.0612 318.7214 189.0898 318.7214zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 344.7844 197.0839 342.7853 197.0839 340.5826z"/><g><defs><path id="SVGID_13_" d="M194.7376 346.2329c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.999 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 342.7853 196.1861 344.7844 194.7376 346.2329z"/></defs><clipPath id="SVGID_14_"><use xlink:href="#SVGID_13_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_14_);fill:#fff" d="M190.0704 333.5691c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0834 6.1218 2.8788C193.7885 334.2701 191.9774 333.5691 190.0704 333.5691z"/><path style="opacity:.13;clip-path:url(#SVGID_14_);fill:#020202" d="M190.0704 333.5691c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0834 6.1218 2.8788C193.7885 334.2701 191.9774 333.5691 190.0704 333.5691z"/></g><g><defs><path id="SVGID_15_" d="M189.0898 318.7214c7.7763.0 15.0283 4.1826 18.926 10.915 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8612-12.0547.0024-21.8636-9.8065-21.8612-21.8612.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 321.173 183.0612 318.7214 189.0898 318.7214zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 344.7844 197.0839 342.7853 197.0839 340.5826z"/></defs><clipPath id="SVGID_16_"><use xlink:href="#SVGID_15_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_16_);fill:#f1bc42" d="M172.6595 324.15c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8612 12.0547.0024 21.8636-9.797 21.8613-21.8612.0024-3.8474-1.0151-7.6327-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 317.7407 176.6171 320.1924 172.6595 324.15z"/></g></g><rect x="198.8952" y="333.6497" style="fill:#f1bc42" width="122.6266" height="13.8671"/></g></g></svg></span><span class="navbar-brand__name">NewLang</span></a> - <div class="td-navbar-nav-scroll ms-md-auto" id="main_navbar"> - <ul class="navbar-nav"> - <li class="nav-item"> - <a class="nav-link" href="/docs/"><span>Documentation</span></a> - </li> - <li class="nav-item"> - <a class="nav-link" href="/playground/"><span>Playground</span></a> - </li> - <li class="nav-item"> - <a class="nav-link active" href="/blog/"><span>Articles</span></a> - </li> - <li class="nav-item dropdown d-none d-lg-block"> - <div class="dropdown"> - <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">English</a> - <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/ru/blog/release-v0.3/">Русский</a></li> - </ul> -</div></li> - </ul> - </div> - <div class="d-none d-lg-block"> - <div class="td-search td-search--offline"> - <div class="td-search__icon"></div> - <input - type="search" - class="td-search__input form-control" - placeholder="Search this site…" - aria-label="Search this site…" - autocomplete="off" - - data-offline-search-index-json-src="/offline-search-index.json" - data-offline-search-base-href="/" - data-offline-search-max-results="10" - > -</div> - </div> -</div> -</nav> - </header> - <div class="container-fluid td-outer"> - <div class="td-main"> - <div class="row flex-xl-nowrap"> - <aside class="col-12 col-md-3 col-xl-2 td-sidebar d-print-none"> - <div id="td-sidebar-menu" class="td-sidebar__inner"> - <form class="td-sidebar__search d-flex align-items-center"> - <div class="td-search td-search--offline"> - <div class="td-search__icon"></div> - <input - type="search" - class="td-search__input form-control" - placeholder="Search this site…" - aria-label="Search this site…" - autocomplete="off" - - data-offline-search-index-json-src="/offline-search-index.json" - data-offline-search-base-href="/" - data-offline-search-max-results="10" - > -</div> - <button class="btn btn-link td-sidebar__toggle d-md-none p-0 ms-3 fas fa-bars" type="button" data-bs-toggle="collapse" data-bs-target="#td-section-nav" aria-controls="td-section-nav" aria-expanded="false" aria-label="Toggle section navigation"> - </button> - </form> - <nav class="td-sidebar-nav collapse" id="td-section-nav"> - <div class="td-sidebar-nav__section nav-item dropdown d-block d-lg-none"> - <div class="dropdown"> - <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">English</a> - <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/ru/blog/release-v0.3/">Русский</a></li> - </ul> -</div> - </div> - <ul class="td-sidebar-nav__section pe-md-3 ul-0"> - <li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child active-path" id="m-blog-li"> - <a href="/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-blog"><span class="">Articles</span></a> - <ul class="ul-1"> - <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v04-li"> - <a href="/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogparser-nuances-li"> - <a href="/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogdsl-domain-specific-language-implementation-with-macros-li"> - <a href="/blog/dsl-domain-specific-language-implementation-with-macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogdsl-domain-specific-language-implementation-with-macros"><span class="">DSL (domain-specific language) implementation with macros</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child active-path" id="m-blogrelease-v03-li"> - <a href="/blog/release-v0.3/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v03"><span class="td-sidebar-nav-active-item">Релиз языка программрования NewLang 0.3</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v02-li"> - <a href="/blog/release-v0.2/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v02"><span class="">Релиз языка программрования NewLang 0.2</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v01-li"> - <a href="/blog/release-v0.1/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v01"><span class="">Релиз языка программрования NewLang</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blognewlang-li"> - <a href="/blog/newlang/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blognewlang"><span class="">Новый язык программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogprog-styles-same-time-li"> - <a href="/blog/prog-styles-same-time/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogprog-styles-same-time"><span class="">Можно ли использовать декларативный и императивный стили написания программ одновременно?</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogunusual-prog-li"> - <a href="/blog/unusual-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogunusual-prog"><span class="">Необычная концепция синтаксиса языка программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogcomplex-prog-li"> - <a href="/blog/complex-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogcomplex-prog"><span class="">Простое сложное программирование</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloglang-final-li"> - <a href="/blog/lang-final/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloglang-final"><span class="">Какая «идеальная» цель развития у языков программирования?</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloglogic-prog-li"> - <a href="/blog/logic-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloglogic-prog"><span class="">Проблема логических языков программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloginter-prog-li"> - <a href="/blog/inter-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloginter-prog"><span class="">Интернациональное программирование на естественных языках</span></a> -</li> - </ul> -</li> - </ul> - </nav> -</div> - - </aside> - <aside class="d-none d-xl-block col-xl-2 td-sidebar-toc d-print-none"> - <div class="td-page-meta ms-2 pb-1 pt-2 mb-0"> -<a id="print" href="/blog/_print/"><i class="fa-solid fa-print fa-fw"></i> Print entire section</a> - -</div> - - <div class="td-toc"> - <nav id="TableOfContents"> - <ul> - <li><a href="#зачем-нужен-newlang">Зачем нужен <em>NewLang</em>?</a></li> - <li><a href="#новые-глобальные-фичи-и-изменения-в-синтаксисе">Новые глобальные фичи и изменения в синтаксисе:</a> - <ul> - <li><a href="#простые-чистые-функции-удалены">Простые чистые функции удалены</a></li> - <li><a href="#зафиксирован-синтаксис-операторов-проверки-условияdocsopsif-и-цикловdocsopswhile">Зафиксирован синтаксис операторов проверки <a href="/docs/ops/if/">условия</a> и <a href="/docs/ops/while/">циклов</a>.</a></li> - <li><a href="#конструкция-else-у-операторов-цикла">Конструкция else у операторов цикла</a></li> - <li><a href="#пространства-имен">Пространства имен</a></li> - <li><a href="#программные-модули">Программные модули</a></li> - <li><a href="#объектно-ориентированное-программирование">Объектно ориентированное программирование</a></li> - <li><a href="#прерывания-возврат-и-обработка-ошибок">Прерывания, возврат и обработка ошибок</a></li> - </ul> - </li> - <li><a href="#бинарная-сборка-под-windws">Бинарная сборка под Windws:</a></li> - <li><a href="#подробная-информация-о-языке">Подробная информация о языке:</a></li> - <li><a href="#обратная-связь">Обратная связь</a></li> - <li><a href="#примеры-кода">Примеры кода</a></li> - <li><a href="#как-посмотреть">Как посмотреть?</a></li> - </ul> -</nav> - </div> - - <div class="taxonomy taxonomy-terms-cloud taxo-tags"> - <h5 class="taxonomy-title">Tag Cloud</h5> - <ul class="taxonomy-terms"> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B/" data-taxonomy-term="%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B"><span class="taxonomy-label">Итераторы</span><span class="taxonomy-count">1</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8/" data-taxonomy-term="%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8"><span class="taxonomy-label">Коллекции</span><span class="taxonomy-count">4</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%BE%D0%BE%D0%BF/" data-taxonomy-term="%D0%BE%D0%BE%D0%BF"><span class="taxonomy-label">ООП</span><span class="taxonomy-count">3</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B/" data-taxonomy-term="%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B"><span class="taxonomy-label">Системые Типы</span><span class="taxonomy-count">1</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85/" data-taxonomy-term="%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85"><span class="taxonomy-label">Типы Данных</span><span class="taxonomy-count">8</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8/" data-taxonomy-term="%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8"><span class="taxonomy-label">Функции</span><span class="taxonomy-count">1</span></a></li> - </ul> - </div> - - - </aside> - <main class="col-12 col-md-9 col-xl-8 ps-md-5 pe-md-4" role="main"> - <a class="td-rss-button" title="RSS" href="/blog/index.xml" target="_blank" rel="noopener"> - <i class="fa-solid fa-rss" aria-hidden="true"></i> - </a> - -<div class="td-content"> - <h1>Релиз языка программрования NewLang 0.3</h1> - - <div class="td-byline mb-4"> - - <time datetime="2022-11-07" class="text-muted">Monday, November 07, 2022</time> - </div> - <header class="article-meta"> - - </header> - <p><img alt="КДПВ" src="/blog/langs.jpeg"></p> - - -<div class="pageinfo pageinfo-primary"> -<p>Внимание!!!</p> -<p>Данная статья содержит описание синтаксиса NewLnag предыдущей версии.</p> -<p>Актуальную версию синтаксиса языка можно посмотреть <a href="/docs/">тут</a>.</p> - -</div> - -<p>NewLang — это язык программирования высокого уровня общего назначения. Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан на строгой системе грамматических правил. За счет использования макросов, синтаксис языка легко расширяется до более привычного вида на основе ключевых слов.</p> -<p>NewLang находится в процессе активного развития. Это третий публичный <a href="https://github.com/rsashka/newlang/releases/tag/v0.3.0">релиз</a> в который добавлены новые существенные возможности по сравнению с предыдущей версией.</p> -<h2 id="зачем-нужен-newlang">Зачем нужен <em>NewLang</em>?<a class="td-heading-self-link" href="#%d0%b7%d0%b0%d1%87%d0%b5%d0%bc-%d0%bd%d1%83%d0%b6%d0%b5%d0%bd-newlang" aria-label="Heading self-link"></a></h2> -<p>У всех современных языков программирования происходит постоянное развитие (усложнение) синтаксиса по мере выхода новых версий. Это является своего рода платой за появление новых возможностей и воспринимается пользователями как естественное явление.</p> -<p>Но одновременно является и серьезной проблемой, так как с выходом версий добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки и поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.</p> -<p>У <em>NewLang</em> сложность языковых конструкций ограничена естественным образом за счет разделения синтаксиса языка на две части - это упрощает его изучение и использование.</p> -<p><em>Основной синтаксис</em> — для написания программ в объектно-ориентированном (императивном) и декларативном стилях, который основан не на зарезервированных ключевых словах, а на системе строгих <a href="/docs/syntax/">грамматических правил</a>. Имеется возможность расширения основного синтаксиса за счет использования макросов. <em>Расширенный синтаксис</em> — программные вставки на языке реализации (С/С++), когда основного синтаксиса становится недостаточно.</p> -<p>Еще одно неудобство современных языков в том, что большинство из них были созданы до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек. Это же касается и вычислений с неограниченной точностью, которые так же требуют применения дополнительных библиотечных функций.</p> -<p>У <em>NewLang</em> тензорные вычисления и рациональные числа неограниченной точности доступны «из коробки». Они поддерживаются на уровне синтаксиса для записи литералов соответствующих типов, а простые арифметические типы данных являются скалярами (тензорами нулевой размерности). Реализация тензорных вычислений сделана на базе библиотеки <a href="https://pytorch.org/">libtorch</a>, а рациональные числа с использованием <a href="https://github.com/openssl/openssl/blob/master/crypto/bn/README.pod">OpenSSL</a>.</p> -<h2 id="новые-глобальные-фичи-и-изменения-в-синтаксисе">Новые глобальные фичи и изменения в синтаксисе:<a class="td-heading-self-link" href="#%d0%bd%d0%be%d0%b2%d1%8b%d0%b5-%d0%b3%d0%bb%d0%be%d0%b1%d0%b0%d0%bb%d1%8c%d0%bd%d1%8b%d0%b5-%d1%84%d0%b8%d1%87%d0%b8-%d0%b8-%d0%b8%d0%b7%d0%bc%d0%b5%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b2-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81%d0%b5" aria-label="Heading self-link"></a></h2> -<h3 id="простые-чистые-функции-удалены">Простые чистые функции удалены<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%be%d1%81%d1%82%d1%8b%d0%b5-%d1%87%d0%b8%d1%81%d1%82%d1%8b%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d1%83%d0%b4%d0%b0%d0%bb%d0%b5%d0%bd%d1%8b" aria-label="Heading self-link"></a></h3> -<p>Раньше я пытался использовать синтаксис предикатов из Пролога, в котором проверки условий записываются через запятую. Но эта идея оказалась провальной, а сами операторы просто ужасными (тестировал разные варианты, но каждый раз получал много отрицательных отзывов), поэтому сейчас решил полностью от них отказаться.</p> -<p>Они получались не только сложными для восприятия, но и по факту не нужными, так как легко заменялись обычной функцией с комбинации обычных логических операций.</p> -<h3 id="зафиксирован-синтаксис-операторов-проверки-условияdocsopsif-и-цикловdocsopswhile">Зафиксирован синтаксис операторов проверки <a href="/docs/ops/if/">условия</a> и <a href="/docs/ops/while/">циклов</a>.<a class="td-heading-self-link" href="#%d0%b7%d0%b0%d1%84%d0%b8%d0%ba%d1%81%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d0%be%d0%b2-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b8-%d1%83%d1%81%d0%bb%d0%be%d0%b2%d0%b8%d1%8fdocsopsif-%d0%b8-%d1%86%d0%b8%d0%ba%d0%bb%d0%be%d0%b2docsopswhile" aria-label="Heading self-link"></a></h3> -<p>Изменен и упрощен синтаксис операторов проверки условия (импликации) и цикла, для которых оставлено только по одному варианту. Проверка условия записывается в виде оператора математического следования <strong>&ndash;&gt;</strong>, а цикл с помощью оператора <strong>&lt;-&gt;</strong>.</p> -<p>Но для упрощения записи можно пользоваться макросами, тогда в этом случае операции проверки условий и циклы превращаются в классические</p> -<pre tabindex="0"><code>\if(...){ - ... -} \elif(...) { - ... -} \else { - ... -}; -</code></pre><p>или</p> -<pre tabindex="0"><code> \while( ... ){ - ... -}; -</code></pre><h3 id="конструкция-else-у-операторов-цикла">Конструкция else у операторов цикла<a class="td-heading-self-link" href="#%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%86%d0%b8%d1%8f-else-%d1%83-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d0%be%d0%b2-%d1%86%d0%b8%d0%ba%d0%bb%d0%b0" aria-label="Heading self-link"></a></h3> -<p>Теперь оператор цикла <strong>while</strong> поддерживает конструкцию <a href="/docs/ops/while/"><strong>else</strong></a>, которая выполняется если условие входа в цикл не было выполнено. <em>Это поведение отличается от аналогичных конструкций в языке Python, у которого секция <strong>else</strong> выполняется всегда, кроме прерывания цикла по break.</em></p> -<p>Ветка <strong>else</strong> у оператора цикла записывается так же как и ветка иначе в условном операторе, т. е.</p> -<pre tabindex="0"><code>[ cond ] &lt;-&gt; { - ... -}, [_] --&gt; { - ... -}; -</code></pre><p>Или тоже самое, но с использованием макросов:</p> -<pre tabindex="0"><code>\while(cond) { - ... -} \else { - ... -}; -</code></pre><h3 id="пространства-имен">Пространства имен<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%be%d1%81%d1%82%d1%80%d0%b0%d0%bd%d1%81%d1%82%d0%b2%d0%b0-%d0%b8%d0%bc%d0%b5%d0%bd" aria-label="Heading self-link"></a></h3> -<p>В синтаксис NewLang добавлены <a href="/docs/syntax/namespace/">пространства имен</a>, в стиле очень похожим на С++. Имена разделяются двойным двоеточием, а для определение пространства имен, его нужно указать перед открывающейся фигурной скобкой.</p> -<pre tabindex="0"><code>ns { - name { - var := 0; # Имя переменной будет ns::name::var - ::var := 1; # Переменная из глобального пространства имен - } -} -</code></pre><h3 id="программные-модули">Программные модули<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%bd%d1%8b%d0%b5-%d0%bc%d0%be%d0%b4%d1%83%d0%bb%d0%b8" aria-label="Heading self-link"></a></h3> -<p>Реализована концепция программных модулей - которая повторяет концепцию иерархического расположения файлов в структуре каталогов файловой системы, как в языках Python и Java.</p> -<p>Имя модуля начинается на префикс <strong>@</strong>, а структура каталогов указывается через точку. Причем концепции программных модулей и пространства имен объединены, и полное имя переменой из предыдущего абзаца будет <code>@root.dir.module::ns::name::var</code>, где <strong>root</strong> и <strong>dir</strong> это каталоги в файловой системе, а <strong>module</strong> — имя файла.</p> -<h3 id="объектно-ориентированное-программирование">Объектно ориентированное программирование<a class="td-heading-self-link" href="#%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%bd%d0%be-%d0%be%d1%80%d0%b8%d0%b5%d0%bd%d1%82%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> -<p>Реализована часть концепции ООП и добавлена поддержка <a href="/docs/types/class/">определения классов</a> и их наследование, которая сейчас выглядит следующим образом:</p> -<pre tabindex="0"><code>:NewClass := :Class() { # Новый тип (класс) - field := 1; - method() := {}; -}; -obj := :NewClass(); # Экземпляр класса -</code></pre><p>Неожиданно для самого себя понял, что имея полный набор вариантов проверок при создании объектов (<strong>::=</strong> - создать новый объект, <strong>:=</strong> - создать новый или присвоить значение существующему, <strong>=</strong> - только присвоить значение, а если объект не существует будет ошибка), концепция переопределения наследуемых функций не требует вообще никаких ключевых слов:</p> -<pre tabindex="0"><code>:NewClass2 := :NewClass() { # Новый класс на базе существующего - field ::= 2; # Будет ошибка, т. к. поле field уже есть в базовом классе - method() = {}; # Аналог override, т.к. method должен существовать в базовом классе -}; -</code></pre><h3 id="прерывания-возврат-и-обработка-ошибок">Прерывания, возврат и обработка ошибок<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b5%d1%80%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%b2%d0%be%d0%b7%d0%b2%d1%80%d0%b0%d1%82-%d0%b8-%d0%be%d0%b1%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b0-%d0%be%d1%88%d0%b8%d0%b1%d0%be%d0%ba" aria-label="Heading self-link"></a></h3> -<p>Изменена, а точнее полностью переделана идеология возвратов из функций и обработки ошибок. -Теперь она чем-то похожа на подход, примененный в Ruby. Любая последовательность команд заключенные в фигурные скобки (в том числе тело функции), рассматривается как блок кода у которого нет специального оператора аналога <strong>return</strong>, который возвращает какое либо значение. -Просто любой блок кода всегда возвращает последнее вычисленное значение (это чем то похоже на оператор «запятая» в языках C/C++).</p> -<p>Для того, чтобы прервать выполнение кода используются две разные команды - прерывания, которые условно можно назвать <em>положительным</em> и <em>отрицательным</em> результатом. Что примерно соответствует семантике их записи. -&ldquo;Отрицательное&rdquo; прерывание записывается в виде двух минусов, а &ldquo;положительное&rdquo; прерывание в виде двух плюсов, т.е. <strong>--</strong> или <strong>++</strong>.</p> -<p>По умолчанию данные операции возвращают пустое значение. Чтобы прерывание вернуло результат, возвращаемые данные нужно записывать между парой соответствующих символов, -т.е. <strong>--</strong> 100 <strong>--</strong>, что является близким аналогом оператора <code>return 100;</code> в других языках программирования, а <strong>++</strong>«Строка»<strong>++</strong> - аналогом <code>return «Строка»;</code>.</p> -<p>Хотя более точным аналогом этих операторов будет все таки не <strong>return</strong>, а <strong>throw</strong>, -т.к. эти команды не только прерывают выполнение последовательности команд в блоке, но их еще можно «ловить». -Для этого используется блок кода с соответствующей семантикой, <strong>{+</strong> … <strong>+}</strong> - блок кода, -который перехватывает положительные прерывания и <strong>{-</strong> … <strong>-}</strong> - блок кода, который перехватывает прерывания, созданные операторами <strong>&ndash;</strong>.</p> -<p>Подобная концепция (в явном виде не разделять возвраты из функций и обработку исключений), -хоть и выглядит немного необычной, но позволяет реализовывать несколько очень полезных финтов, -которые сложно реализуемые в обычных языках программирования.</p> -<p>Например, возврат из нескольких вложенных функций без необходимости обрабатывать результат возврата каждой из них. -В этом примере функция <em>Test</em> перехватывает &ldquo;положительные&rdquo; прерывания из вложенных функций:</p> -<pre tabindex="0"><code> Test0(arg) := { \if($arg==0) \return(&#34;DONE - 0&#34;); «FAIL» }; - Test1(arg) := { \if($arg==1) \return(&#34;DONE - 1&#34;); Test0($arg); }; - Test(arg) := {+ \if($arg &gt;= 0) Test1($arg); $arg; +}; - - Test(0); # Вернет «DONE — 0» возврат из вложенной функции Test0 - Test(1); # Вернет «DONE — 1» возврат из вложенной функции Test1 - Test(2); # Вернет «FAIL» возврат из вложенной функции Test0 - Test(-2); # Вернет -2 — возврат из функции Test -</code></pre><p>Есть еще блок <code>{* … *}</code>, который перехватывает оба типа прерываний. Такой блок кода поддерживает типизацию возвращаемого значения, что позволяет в явном виде указывать типы данных, которые нужно перехватывать. -Например, <code>{* ... *} :Type1</code> — будет перехвачено прерывание вида <code>++ :Type1 ++</code> или <code>--:Type1--</code>, что позволяет очень гибко формировать логику работы программы.</p> -<p>Блоки кода с перехватом исключений также поддерживают оператор иначе (<em>\else</em>) который, по аналогии с оператором <em>\else</em> в циклах, выполняется только тогда, если прерывания не произошло.</p> -<p>Можно указать сразу несколько типов, которые нужно перехватывать:</p> -<pre tabindex="0"><code> {* - .... - *} &lt;:Type1, :Type2, :Type3&gt;; -</code></pre><h2 id="бинарная-сборка-под-windws">Бинарная сборка под Windws:<a class="td-heading-self-link" href="#%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%b0%d1%8f-%d1%81%d0%b1%d0%be%d1%80%d0%ba%d0%b0-%d0%bf%d0%be%d0%b4-windws" aria-label="Heading self-link"></a></h2> -<p>В текущем релизе версия clang повышена 15, а вызовы нативных функций опять реализованы с помощью libffi, что в итоге позволило собрать бинарную сборку не только под Linux, но и под Windows. И теперь чтобы поиграться с REPL read-eval-print loop можно скачать уже готовый бинарник.</p> -<h2 id="подробная-информация-о-языке">Подробная информация о языке:<a class="td-heading-self-link" href="#%d0%bf%d0%be%d0%b4%d1%80%d0%be%d0%b1%d0%bd%d0%b0%d1%8f-%d0%b8%d0%bd%d1%84%d0%be%d1%80%d0%bc%d0%b0%d1%86%d0%b8%d1%8f-%d0%be-%d1%8f%d0%b7%d1%8b%d0%ba%d0%b5" aria-label="Heading self-link"></a></h2> -<ul> -<li><a href="/docs/syntax/">Синтаксис <em>NewLang</em></a></li> -<li><a href="/docs/types/">Подробное описание типов данных</a></li> -<li><a href="/docs/ops/">Операторы и управляющие конструкции</a></li> -<li><a href="/docs/_print/">Вся документация по <em>NewLang</em> на одной странице</a></li> -</ul> -<h2 id="обратная-связь">Обратная связь<a class="td-heading-self-link" href="#%d0%be%d0%b1%d1%80%d0%b0%d1%82%d0%bd%d0%b0%d1%8f-%d1%81%d0%b2%d1%8f%d0%b7%d1%8c" aria-label="Heading self-link"></a></h2> -<p>Если у вас появятся предложения по развитию нового или улучшению уже существующего функционала <em>NewLang</em>, <a href="https://github.com/rsashka/newlang/discussions">пишите</a>.</p> -<h2 id="примеры-кода">Примеры кода<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80%d1%8b-%d0%ba%d0%be%d0%b4%d0%b0" aria-label="Heading self-link"></a></h2> -<pre tabindex="0"><code>#!../output/nlc --eval -# Определение функции hello -hello(str) := { - # Импорт стандартной C функции - printf := :Pointer(&#39;printf(format:FmtChar, ...):Int32&#39;); - # Вызов C функции с проверкой типов аргументов по строке формата - printf(&#39;%s&#39;, $str); - # Возврат значения из функции hello - $str; -}; - -hello(&#39;Привет, мир!&#39;); # Вызвать функцию&lt;/code&gt; -</code></pre><p>Вывод (первая строка выводится с помощью printf, а вторая — возвращаемое значение функции hello):</p> -<pre tabindex="0"><code> Привет, мир! - Привет, мир! -</code></pre><p>Пример скрипта для вычисления факториала 1000</p> -<pre tabindex="0"><code>#!../output/nlc --eval - -fact := 1\1; # Рациональное число без ограничения точности -mult := 1000..1..-1?; # Сделать из диапазона итератор для множителей от 1000 до 2 -[mult ?!] &lt;-&gt; { # Цикл, пока не закончатся данные итератора - # Получить текущий множитель и перейти на следующий элемент итератора - fact *= mult !; -}; -fact # Вывести итоговый результат -</code></pre><p>Вывод:</p> -<spoiler title="Много цифр"> -402387260077093773543702433923003985719374864210714632543799910429938512398629 -020592044208486969404800479988610197196058631666872994808558901323829669944590 -997424504087073759918823627727188732519779505950995276120874975462497043601418 -278094646496291056393887437886487337119181045825783647849977012476632889835955 -735432513185323958463075557409114262417474349347553428646576611667797396668820 -291207379143853719588249808126867838374559731746136085379534524221586593201928 -090878297308431392844403281231558611036976801357304216168747609675871348312025 -478589320767169132448426236131412508780208000261683151027341827977704784635868 -170164365024153691398281264810213092761244896359928705114964975419909342221566 -832572080821333186116811553615836546984046708975602900950537616475847728421889 -679646244945160765353408198901385442487984959953319101723355556602139450399736 -280750137837615307127761926849034352625200015888535147331611702103968175921510 -907788019393178114194545257223865541461062892187960223838971476088506276862967 -146674697562911234082439208160153780889893964518263243671616762179168909779911 -903754031274622289988005195444414282012187361745992642956581746628302955570299 -024324153181617210465832036786906117260158783520751516284225540265170483304226 -143974286933061690897968482590125458327168226458066526769958652682272807075781 -391858178889652208164348344825993266043367660176999612831860788386150279465955 -131156552036093988180612138558600301435694527224206344631797460594682573103790 -084024432438465657245014402821885252470935190620929023136493273497565513958720 -559654228749774011413346962715422845862377387538230483865688976461927383814900 -140767310446640259899490222221765904339901886018566526485061799702356193897017 -860040811889729918311021171229845901641921068884387121855646124960798722908519 -296819372388642614839657382291123125024186649353143970137428531926649875337218 -940694281434118520158014123344828015051399694290153483077644569099073152433278 -288269864602789864321139083506217095002597389863554277196742822248757586765752 -344220207573630569498825087968928162753848863396909959826280956121450994871701 -244516461260379029309120889086942028510640182154399457156805941872748998094254 -742173582401063677404595741785160829230135358081840096996372524230560855903700 -624271243416909004153690105933983835777939410970027753472000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000\1 -</spoiler> -<h2 id="как-посмотреть">Как посмотреть?<a class="td-heading-self-link" href="#%d0%ba%d0%b0%d0%ba-%d0%bf%d0%be%d1%81%d0%bc%d0%be%d1%82%d1%80%d0%b5%d1%82%d1%8c" aria-label="Heading self-link"></a></h2> -<ul> -<li><a href="https://github.com/rsashka/newlang/releases/download/v0.3.0/nlc_win_64.zip">Бинарная сборка и тесты под Windows</a></li> -<li><a href="https://github.com/rsashka/newlang/releases/download/v0.3.0/nlc_lin_64.tar.xz">Бинарная сборка и тесты под Ubuntu</a></li> -<li>Для запуска бинарных сборок потребуются разделяемые библиотеки libLLVM-15 и libtorch (<a href="https://github.com/rsashka/newlang/releases/download/v0.3.0/nlc_dll.zip">архив с библиотеками для Windows</a>), (<a href="https://github.com/rsashka/newlang/releases/download/v0.3.0/nlc_so.tar.xz">архив с библиотеками для Ubuntu</a>).</li> -<li>Так же все можно собрать напрямую из исходников по инструкции в <a href="https://github.com/rsashka/newlang">репозитории</a></li> -</ul> - - <ul class="list-unstyled d-flex justify-content-between align-items-center mb-0 pt-5"> - <li> - <a href="/blog/release-v0.2/" aria-label="Previous - Релиз языка программрования NewLang 0.2" class="btn btn-primary"><span class="me-1">←</span>Previous</a> - </li> - <li> - <a href="/blog/dsl-domain-specific-language-implementation-with-macros/" aria-label="Next - DSL (domain-specific language) implementation with macros" class="btn btn-primary">Next<span class="ms-1">→</span></a> - </li> -</ul> - - </div> - - - </main> - </div> - </div> - <footer class="td-footer row d-print-none"> - <div class="container-fluid"> - <div class="row mx-md-2"> - <div class="td-footer__left col-6 col-sm-4 order-sm-1"> - <ul class="td-footer__links-list"> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="User mailing list" aria-label="User mailing list"> - <a target="_blank" rel="noopener" href="mailto:mail@newlang.net" aria-label="User mailing list"> - <i class="fa fa-envelope"></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - -</ul> - - </div><div class="td-footer__right col-6 col-sm-4 order-sm-3"> - <ul class="td-footer__links-list"> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="GitHub" aria-label="GitHub"> - <a target="_blank" rel="noopener" href="https://github.com/rsashka/newlang" aria-label="GitHub"> - <i class="fab fa-github"></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - -</ul> - - </div><div class="td-footer__center col-12 col-sm-4 py-2 order-sm-2"> - <span class="td-footer__copyright">&copy; - 2024 - <span class="td-footer__authors">The NewLang Authors</span></span><span class="td-footer__all_rights_reserved">All Rights Reserved</span> - </div> - </div> - </div> -</footer> - - </div> - <script src="/js/main.js"></script> -<script defer src="/js/click-to-copy.js" crossorigin="anonymous"></script> -<script src='/js/tabpane-persist.js'></script> - - </body> -</html> \ No newline at end of file diff --git a/docs/blog/release-v0.4/index.html b/docs/blog/release-v0.4/index.html index b67e6122..6ffabedb 100644 --- a/docs/blog/release-v0.4/index.html +++ b/docs/blog/release-v0.4/index.html @@ -17,32 +17,20 @@ <link rel="icon" type="image/png" href="/favicons/android-144x144.png" sizes="144x144"> <link rel="icon" type="image/png" href="/favicons/android-192x192.png" sizes="192x192"> -<title>Релиз языка программрования NewLang 0.4 | NewLang</title> -<meta name="description" content="Внимание!!! -&amp;ldquo;nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -ssssssssssssssssssssssssssssssssssssssssssssss"> -<meta property="og:title" content="Релиз языка программрования NewLang 0.4" /> -<meta property="og:description" content="Внимание!!! -&ldquo;nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -ssssssssssssssssssssssssssssssssssssssssssssss" /> +<title>Release of the programming language NewLang 0.4 | NewLang</title> +<meta name="description" content="New features and changes in the syntax of NewLang Reworked the definition of object types using prefix naming (sigils) Interrupting the execution flow and returning can now be done for named code blocks. Simplified the syntax for importing native variables and functions (C/C&#43;&#43;) Stabilized the syntax for initializing tensor, dictionary, and function argument values with initial data. Added built-in macros for writing code using keywords in a DSL style New compiler features (nlc) Completely redesigned the macroprocessor."> +<meta property="og:title" content="Release of the programming language NewLang 0.4" /> +<meta property="og:description" content="New features and changes in the syntax of NewLang Reworked the definition of object types using prefix naming (sigils) Interrupting the execution flow and returning can now be done for named code blocks. Simplified the syntax for importing native variables and functions (C/C&#43;&#43;) Stabilized the syntax for initializing tensor, dictionary, and function argument values with initial data. Added built-in macros for writing code using keywords in a DSL style New compiler features (nlc) Completely redesigned the macroprocessor." /> <meta property="og:type" content="article" /> <meta property="og:url" content="http://localhost:1313/blog/release-v0.4/" /><meta property="article:section" content="blog" /> <meta property="article:published_time" content="2023-06-06T00:00:00+00:00" /> <meta property="article:modified_time" content="2024-03-22T23:57:08+03:00" /><meta property="og:site_name" content="NewLang" /> -<meta itemprop="name" content="Релиз языка программрования NewLang 0.4"> -<meta itemprop="description" content="Внимание!!! -&ldquo;nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -ssssssssssssssssssssssssssssssssssssssssssssss"><meta itemprop="datePublished" content="2023-06-06T00:00:00+00:00" /> +<meta itemprop="name" content="Release of the programming language NewLang 0.4"> +<meta itemprop="description" content="New features and changes in the syntax of NewLang Reworked the definition of object types using prefix naming (sigils) Interrupting the execution flow and returning can now be done for named code blocks. Simplified the syntax for importing native variables and functions (C/C&#43;&#43;) Stabilized the syntax for initializing tensor, dictionary, and function argument values with initial data. Added built-in macros for writing code using keywords in a DSL style New compiler features (nlc) Completely redesigned the macroprocessor."><meta itemprop="datePublished" content="2023-06-06T00:00:00+00:00" /> <meta itemprop="dateModified" content="2024-03-22T23:57:08+03:00" /> -<meta itemprop="wordCount" content="18"> -<meta itemprop="keywords" content="" /><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Релиз языка программрования NewLang 0.4"/> -<meta name="twitter:description" content="Внимание!!! -&ldquo;nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -ssssssssssssssssssssssssssssssssssssssssssssss"/> +<meta itemprop="wordCount" content="159"> +<meta itemprop="keywords" content="" /><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Release of the programming language NewLang 0.4"/> +<meta name="twitter:description" content="New features and changes in the syntax of NewLang Reworked the definition of object types using prefix naming (sigils) Interrupting the execution flow and returning can now be done for named code blocks. Simplified the syntax for importing native variables and functions (C/C&#43;&#43;) Stabilized the syntax for initializing tensor, dictionary, and function argument values with initial data. Added built-in macros for writing code using keywords in a DSL style New compiler features (nlc) Completely redesigned the macroprocessor."/> @@ -141,31 +129,9 @@ <a href="/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-blog"><span class="">Articles</span></a> <ul class="ul-1"> <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child active-path" id="m-blogrelease-v04-li"> - <a href="/blog/release-v0.4/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v04"><span class="td-sidebar-nav-active-item">Релиз языка программрования NewLang 0.4</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogparser-nuances-li"> - <a href="/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> + <a href="/blog/release-v0.4/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v04"><span class="td-sidebar-nav-active-item">Release of the programming language NewLang 0.4</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogdsl-domain-specific-language-implementation-with-macros-li"> <a href="/blog/dsl-domain-specific-language-implementation-with-macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogdsl-domain-specific-language-implementation-with-macros"><span class="">DSL (domain-specific language) implementation with macros</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v03-li"> - <a href="/blog/release-v0.3/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v03"><span class="">Релиз языка программрования NewLang 0.3</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v02-li"> - <a href="/blog/release-v0.2/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v02"><span class="">Релиз языка программрования NewLang 0.2</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v01-li"> - <a href="/blog/release-v0.1/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v01"><span class="">Релиз языка программрования NewLang</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blognewlang-li"> - <a href="/blog/newlang/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blognewlang"><span class="">Новый язык программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogprog-styles-same-time-li"> - <a href="/blog/prog-styles-same-time/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogprog-styles-same-time"><span class="">Можно ли использовать декларативный и императивный стили написания программ одновременно?</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogunusual-prog-li"> - <a href="/blog/unusual-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogunusual-prog"><span class="">Необычная концепция синтаксиса языка программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogcomplex-prog-li"> - <a href="/blog/complex-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogcomplex-prog"><span class="">Простое сложное программирование</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloglang-final-li"> - <a href="/blog/lang-final/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloglang-final"><span class="">Какая «идеальная» цель развития у языков программирования?</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloglogic-prog-li"> - <a href="/blog/logic-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloglogic-prog"><span class="">Проблема логических языков программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloginter-prog-li"> - <a href="/blog/inter-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloginter-prog"><span class="">Интернациональное программирование на естественных языках</span></a> </li> </ul> </li> @@ -180,7 +146,16 @@ </div> - + <div class="td-toc"> + <nav id="TableOfContents"> + <ul> + <li><a href="#new-features-and-changes-in-the-syntax-of-newlang">New features and changes in the syntax of NewLang</a></li> + <li><a href="#new-compiler-features-nlc">New compiler features (nlc)</a></li> + <li><a href="#miscellaneous">Miscellaneous</a></li> + </ul> +</nav> + </div> + <div class="taxonomy taxonomy-terms-cloud taxo-tags"> <h5 class="taxonomy-title">Tag Cloud</h5> <ul class="taxonomy-terms"> @@ -201,7 +176,7 @@ <h5 class="taxonomy-title">Tag Cloud</h5> </a> <div class="td-content"> - <h1>Релиз языка программрования NewLang 0.4</h1> + <h1>Release of the programming language NewLang 0.4</h1> <div class="td-byline mb-4"> @@ -210,21 +185,30 @@ <h1>Релиз языка программрования NewLang 0.4</h1> <header class="article-meta"> </header> - <p><img alt="КДПВ" src="/blog/langs.jpeg"></p> - - -<div class="pageinfo pageinfo-primary"> -<p>Внимание!!!</p> -<p>&ldquo;nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии.</p> -<p>Актуальную версию синтаксиса языка можно посмотреть <a href="/docs/">тут</a>.</p> - -</div> - -<p>ssssssssssssssssssssssssssssssssssssssssssssss</p> + <h2 id="new-features-and-changes-in-the-syntax-of-newlang">New features and changes in the syntax of NewLang<a class="td-heading-self-link" href="#new-features-and-changes-in-the-syntax-of-newlang" aria-label="Heading self-link"></a></h2> +<ul> +<li>Reworked the definition of object types using <a href="https://newlang.net/docs/syntax/naming/">prefix naming (sigils)</a></li> +<li>Interrupting the execution flow and returning can now be done for <a href="https://newlang.net/docs/ops/throw/">named code blocks</a>.</li> +<li>Simplified the syntax for importing <a href="https://newlang.net/docs/types/native/">native variables and functions (C/C++)</a></li> +<li>Stabilized the syntax for <a href="https://newlang.net/docs/ops/create/#comprehensions">initializing tensor, dictionary, and function argument values</a> with initial data.</li> +<li>Added built-in macros for writing code using keywords in a <a href="https://newlang.net/docs/syntax/dsl/">DSL style</a></li> +</ul> +<h2 id="new-compiler-features-nlc">New compiler features (nlc)<a class="td-heading-self-link" href="#new-compiler-features-nlc" aria-label="Heading self-link"></a></h2> +<ul> +<li>Completely redesigned the macroprocessor.</li> +<li>Reworked the compiler architecture with division into parser, macroprocessor, syntax analyzer, interpreter, and code generator.</li> +</ul> +<h2 id="miscellaneous">Miscellaneous<a class="td-heading-self-link" href="#miscellaneous" aria-label="Heading self-link"></a></h2> +<ul> +<li>The documentation <a href="http://newlang.net">website</a> has been translated to <a href="https://gohugo.io/">Hugo</a> and made bilingual.</li> +<li>Instead of binary builds, a section <a href="https://newlang.net/playground/">Playground and example code</a> has been added to the website for small experiments.</li> +<li>Transition to clang-16 has been completed (transition to clang-17 and newer is planned after full implementation of coroutines and support for extended floating-point number formats).</li> +<li>The number of project contributors has increased to more than one!</li> +</ul> <ul class="list-unstyled d-flex justify-content-between align-items-center mb-0 pt-5"> <li> - <a href="/blog/parser-nuances/" aria-label="Previous - Нюансы разработки парсера для своего языка программирования" class="btn btn-primary"><span class="me-1">←</span>Previous</a> + <a href="/blog/dsl-domain-specific-language-implementation-with-macros/" aria-label="Previous - DSL (domain-specific language) implementation with macros" class="btn btn-primary"><span class="me-1">←</span>Previous</a> </li> <li> <a class="btn btn-primary disabled">Next<span class="ms-1">→</span></a> diff --git a/docs/blog/unusual-prog/index.html b/docs/blog/unusual-prog/index.html deleted file mode 100644 index 0b23ab7e..00000000 --- a/docs/blog/unusual-prog/index.html +++ /dev/null @@ -1,453 +0,0 @@ -<!doctype html> -<html itemscope itemtype="http://schema.org/WebPage" lang="en" class="no-js"> - <head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script> - <meta charset="utf-8"> -<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> -<meta name="robots" content="noindex, nofollow"> - - -<link rel="shortcut icon" href="/favicons/favicon.ico" > -<link rel="apple-touch-icon" href="/favicons/apple-touch-icon-180x180.png" sizes="180x180"> -<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16"> -<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32"> -<link rel="icon" type="image/png" href="/favicons/android-36x36.png" sizes="36x36"> -<link rel="icon" type="image/png" href="/favicons/android-48x48.png" sizes="48x48"> -<link rel="icon" type="image/png" href="/favicons/android-72x72.png" sizes="72x72"> -<link rel="icon" type="image/png" href="/favicons/android-96x96.png" sizes="96x96"> -<link rel="icon" type="image/png" href="/favicons/android-144x144.png" sizes="144x144"> -<link rel="icon" type="image/png" href="/favicons/android-192x192.png" sizes="192x192"> - -<title>Необычная концепция синтаксиса языка программирования | NewLang</title> -<meta name="description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -Хочу представить на обсуждение читателей немного необычный концепт языка программирования, в котором отсутствует проблема, присущая практически всем промышленным языкам - постоянное увеличение сложности синтаксиса языка из-за его естественного развития по мере выхода новых версий и добавления новых фич. Эта проблема описана в статье &amp;ldquo;Простое сложное программирование&amp;rdquo; и Какая &amp;ldquo;идеальная&amp;rdquo; цель развития у языков программирования?"> -<meta property="og:title" content="Необычная концепция синтаксиса языка программирования" /> -<meta property="og:description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -Хочу представить на обсуждение читателей немного необычный концепт языка программирования, в котором отсутствует проблема, присущая практически всем промышленным языкам - постоянное увеличение сложности синтаксиса языка из-за его естественного развития по мере выхода новых версий и добавления новых фич. Эта проблема описана в статье &ldquo;Простое сложное программирование&rdquo; и Какая &ldquo;идеальная&rdquo; цель развития у языков программирования?" /> -<meta property="og:type" content="article" /> -<meta property="og:url" content="http://localhost:1313/blog/unusual-prog/" /><meta property="article:section" content="blog" /> -<meta property="article:published_time" content="2021-05-24T00:00:00+00:00" /> -<meta property="article:modified_time" content="2024-03-22T23:57:08+03:00" /><meta property="og:site_name" content="NewLang" /> -<meta itemprop="name" content="Необычная концепция синтаксиса языка программирования"> -<meta itemprop="description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -Хочу представить на обсуждение читателей немного необычный концепт языка программирования, в котором отсутствует проблема, присущая практически всем промышленным языкам - постоянное увеличение сложности синтаксиса языка из-за его естественного развития по мере выхода новых версий и добавления новых фич. Эта проблема описана в статье &ldquo;Простое сложное программирование&rdquo; и Какая &ldquo;идеальная&rdquo; цель развития у языков программирования?"><meta itemprop="datePublished" content="2021-05-24T00:00:00+00:00" /> -<meta itemprop="dateModified" content="2024-03-22T23:57:08+03:00" /> -<meta itemprop="wordCount" content="1594"> -<meta itemprop="keywords" content="" /><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Необычная концепция синтаксиса языка программирования"/> -<meta name="twitter:description" content="Внимание!!! -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -Хочу представить на обсуждение читателей немного необычный концепт языка программирования, в котором отсутствует проблема, присущая практически всем промышленным языкам - постоянное увеличение сложности синтаксиса языка из-за его естественного развития по мере выхода новых версий и добавления новых фич. Эта проблема описана в статье &ldquo;Простое сложное программирование&rdquo; и Какая &ldquo;идеальная&rdquo; цель развития у языков программирования?"/> - - - - - -<link href="/scss/main.css" rel="stylesheet"> - -<script - src="https://code.jquery.com/jquery-3.6.3.min.js" - integrity="sha512-STof4xm1wgkfm7heWqFJVn58Hm3EtS31XFaagaa8VMReCXAkQnJZ+jEy8PCC/iT18dFy95WcExNHFTqLyp72eQ==" - crossorigin="anonymous"></script> -<script defer - src="https://unpkg.com/lunr@2.3.9/lunr.min.js" - integrity="sha384-203J0SNzyqHby3iU6hzvzltrWi/M41wOP5Gu+BiJMz5nwKykbkUx8Kp7iti0Lpli" - crossorigin="anonymous"></script> - - </head> - <body class="td-page td-blog"> - <header> - <nav class="td-navbar navbar-dark js-navbar-scroll"> -<div class="container-fluid flex-column flex-md-row"> - <a class="navbar-brand" href="/"><span class="navbar-brand__logo navbar-logo"><svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500" style="enable-background:new 0 0 500 500"><g><path style="fill:#fff" d="M116.8525 421.9722c-5.7041.0-10.3442-4.3127-10.3442-9.6129V88.183c0-5.3002 4.6401-9.6117 10.3442-9.6117H320.858c3.0347.0 9.3959.5498 11.7506 2.6302l.3545.3442 58.905 63.2912c2.3101 2.491 2.9202 8.4928 2.9202 11.3184v256.2039c0 5.3002-4.6407 9.6129-10.3436 9.6129H116.8525z"/><g><g><g><path style="fill:#767676" d="M384.4445 423.2066H116.852c-6.3839.0-11.5786-4.8658-11.5786-10.8474V88.1831c0-5.9804 5.1947-10.8461 11.5786-10.8461h204.0062c.377.0 9.2786.0329 12.568 2.9389l.3947.3833 58.9508 63.337c3.2135 3.4652 3.2514 11.7924 3.2514 12.1593v256.2036C396.0231 418.3408 390.8284 423.2066 384.4445 423.2066zM116.5079 411.9189c.0848.0278.1999.0531.3441.0531h267.5925c.1442.0.2581-.0253.3441-.0531V156.1556c-.0076-.9033-.3593-3.7347-.7034-5.0037l-57.6527-61.9416c-1.4651-.3176-4.4533-.6389-5.5742-.6389H116.852c-.143.0-.2594.024-.3441.0531V411.9189zm267.4533-261.149zM327.0321 89.371v.0013V89.371z"/></g></g></g><g><g><path style="fill:#5b7fc0" d="M189.0874 210.1754l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.025 2.454-11.4897 6.4116-15.4473C177.5953 212.627 183.0601 210.1742 189.0874 210.1754zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403S197.0816 234.1722 197.0804 232.033z"/><path style="opacity:.3;fill:#fff" d="M189.0898 210.176c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 212.6276 183.0612 210.176 189.0898 210.176zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 236.239 197.0839 234.2399 197.0839 232.0372z"/><g><defs><path id="SVGID_1_" d="M194.7376 237.6875c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.999 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 234.2399 196.1861 236.239 194.7376 237.6875z"/></defs><clipPath id="SVGID_2_"><use xlink:href="#SVGID_1_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_2_);fill:#fff" d="M190.0704 225.0237c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 225.7247 191.9774 225.0237 190.0704 225.0237z"/><path style="opacity:.13;clip-path:url(#SVGID_2_);fill:#020202" d="M190.0704 225.0237c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 225.7247 191.9774 225.0237 190.0704 225.0237z"/></g><g><defs><path id="SVGID_3_" d="M189.0898 210.176c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 212.6276 183.0612 210.176 189.0898 210.176zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 236.239 197.0839 234.2399 197.0839 232.0372z"/></defs><clipPath id="SVGID_4_"><use xlink:href="#SVGID_3_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_4_);fill:#5b7fc0" d="M172.6595 215.6045c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8612 12.0547.0024 21.8636-9.797 21.8613-21.8612.0024-3.8475-1.0151-7.6326-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 209.1953 176.6171 211.647 172.6595 215.6045z"/></g></g><rect x="198.8952" y="225.1043" style="fill:#5b7fc0" width="122.6266" height="13.8671"/></g><g><path style="fill:#d95140" d="M189.0874 155.7611l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.0249 2.454-11.4897 6.4116-15.4473C177.5953 158.2128 183.0601 155.7599 189.0874 155.7611zm7.993 21.8577c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403C196.2508 181.7667 197.0816 179.758 197.0804 177.6188z"/><path style="opacity:.3;fill:#fff" d="M189.0898 155.7617c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 158.2134 183.0612 155.7617 189.0898 155.7617zm7.9941 21.8613c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 181.8248 197.0839 179.8256 197.0839 177.623z"/><g><defs><path id="SVGID_5_" d="M194.7376 183.2733c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.9989 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 179.8256 196.1861 181.8248 194.7376 183.2733z"/></defs><clipPath id="SVGID_6_"><use xlink:href="#SVGID_5_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_6_);fill:#fff" d="M190.0704 170.6095c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 171.3104 191.9774 170.6095 190.0704 170.6095z"/><path style="opacity:.13;clip-path:url(#SVGID_6_);fill:#020202" d="M190.0704 170.6095c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9546.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.663-2.8588-6.116.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C193.7885 171.3104 191.9774 170.6095 190.0704 170.6095z"/></g><g><defs><path id="SVGID_7_" d="M189.0898 155.7617c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8066-21.8612-21.8613.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 158.2134 183.0612 155.7617 189.0898 155.7617zm7.9941 21.8613c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 181.8248 197.0839 179.8256 197.0839 177.623z"/></defs><clipPath id="SVGID_8_"><use xlink:href="#SVGID_7_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_8_);fill:#d95140" d="M172.6595 161.1903c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8613 12.0547.0024 21.8636-9.797 21.8613-21.8613.0024-3.8474-1.0151-7.6326-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 154.7811 176.6171 157.2327 172.6595 161.1903z"/></g><rect x="198.8952" y="170.69" style="fill:#d95140" width="122.6266" height="13.8671"/></g><g><g><path style="fill:#56a55c" d="M189.5379 264.6147l.0012-.0012c7.7751.0012 15.0294 4.1862 18.932 10.9235 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3304-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032-5.8394.0-11.3281-2.2733-15.458-6.4032-4.13-4.13-6.4032-9.6186-6.4056-15.4628.0012-6.0249 2.454-11.4897 6.4116-15.4472C178.0458 267.0663 183.5105 264.6135 189.5379 264.6147zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6538 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403C196.7013 290.6202 197.5321 288.6115 197.5309 286.4723z"/><path style="opacity:.3;fill:#fff" d="M189.5403 264.6153c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8065-21.8612-21.8613.0-6.0285 2.4516-11.492 6.4116-15.452C178.0482 267.0669 183.5117 264.6153 189.5403 264.6153zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.6366 290.6783 197.5344 288.6792 197.5344 286.4765z"/><g><defs><path id="SVGID_9_" d="M195.1881 292.1268c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.9989 7.9942-7.9941 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.5344 288.6792 196.6366 290.6783 195.1881 292.1268z"/></defs><clipPath id="SVGID_10_"><use xlink:href="#SVGID_9_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_10_);fill:#fff" d="M190.5209 279.463c-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7446-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9941 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C194.239 280.164 192.4279 279.463 190.5209 279.463z"/><path style="opacity:.13;clip-path:url(#SVGID_10_);fill:#020202" d="M190.5209 279.463c-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7446-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9941 2.3802-1e-4 4.616 1.0833 6.1218 2.8788C194.239 280.164 192.4279 279.463 190.5209 279.463z"/></g><g><defs><path id="SVGID_11_" d="M189.5403 264.6153c7.7763.0 15.0283 4.1826 18.926 10.9151 1.9201 3.3135 2.9377 7.0987 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8613-12.0547.0024-21.8636-9.8065-21.8612-21.8613.0-6.0285 2.4516-11.492 6.4116-15.452C178.0482 267.0669 183.5117 264.6153 189.5403 264.6153zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9941.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.6366 290.6783 197.5344 288.6792 197.5344 286.4765z"/></defs><clipPath id="SVGID_12_"><use xlink:href="#SVGID_11_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_12_);fill:#56a55c" d="M173.11 270.0439c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8613 12.0547.0024 21.8636-9.797 21.8613-21.8613.0024-3.8474-1.0151-7.6326-2.9353-10.9462-3.8977-6.7325-11.1497-10.9151-18.926-10.9151C182.5311 263.6346 177.0676 266.0863 173.11 270.0439z"/></g></g><rect x="199.3456" y="279.5436" style="fill:#56a55c" width="122.6266" height="13.8671"/></g><g><g><path style="fill:#f1bc42" d="M189.0874 318.7208l.0012-.0012c7.7751.0012 15.0295 4.1862 18.932 10.9234 1.9177 3.3159 2.9305 7.1011 2.9293 10.9378.0 5.8394-2.2733 11.3305-6.4032 15.4604-4.1288 4.1288-9.6186 6.4032-15.458 6.4032s-11.328-2.2733-15.458-6.4032-6.4032-9.6186-6.4056-15.4628c.0012-6.025 2.454-11.4897 6.4116-15.4472C177.5953 321.1724 183.0601 318.7196 189.0874 318.7208zm7.993 21.8576c.0012-1.4042-.3687-2.7868-1.063-3.9887-1.4293-2.4684-4.0833-3.9995-6.9299-4.0019-4.4077.0024-7.993 3.5877-7.993 7.993.0 2.1356.832 4.1431 2.3427 5.6539 1.5083 1.5083 3.5159 2.3403 5.6503 2.3415 2.1356.0 4.1443-.8308 5.6539-2.3403S197.0816 342.7176 197.0804 340.5784z"/><path style="opacity:.3;fill:#fff" d="M189.0898 318.7214c7.7763.0 15.0283 4.1826 18.926 10.915 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8612-12.0547.0024-21.8636-9.8065-21.8612-21.8612.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 321.173 183.0612 318.7214 189.0898 318.7214zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 344.7844 197.0839 342.7853 197.0839 340.5826z"/><g><defs><path id="SVGID_13_" d="M194.7376 346.2329c-1.4461 1.4461-3.4452 2.3439-5.6479 2.3439-4.4077-.0024-7.9918-3.5865-7.9942-7.9942.0024-4.4125 3.5937-7.999 7.9942-7.9942 2.8443.0 5.497 1.5323 6.924 3.9983.6991 1.2067 1.0702 2.5881 1.0702 3.9959C197.0839 342.7853 196.1861 344.7844 194.7376 346.2329z"/></defs><clipPath id="SVGID_14_"><use xlink:href="#SVGID_13_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_14_);fill:#fff" d="M190.0704 333.5691c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0834 6.1218 2.8788C193.7885 334.2701 191.9774 333.5691 190.0704 333.5691z"/><path style="opacity:.13;clip-path:url(#SVGID_14_);fill:#020202" d="M190.0704 333.5691c-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0011 1.9547.7088 3.7452 1.8782 5.1354-1.7447-1.4674-2.8575-3.6631-2.8588-6.1161.0024-4.4125 3.5936-7.999 7.9942-7.9942 2.3802-1e-4 4.616 1.0834 6.1218 2.8788C193.7885 334.2701 191.9774 333.5691 190.0704 333.5691z"/></g><g><defs><path id="SVGID_15_" d="M189.0898 318.7214c7.7763.0 15.0283 4.1826 18.926 10.915 1.9201 3.3136 2.9377 7.0988 2.9353 10.9462.0024 12.0643-9.8065 21.8636-21.8613 21.8612-12.0547.0024-21.8636-9.8065-21.8612-21.8612.0-6.0285 2.4516-11.4921 6.4116-15.452C177.5977 321.173 183.0612 318.7214 189.0898 318.7214zm7.9941 21.8612c0-1.4078-.3711-2.7892-1.0702-3.9959-1.4269-2.466-4.0797-3.9983-6.924-3.9983-4.4005-.0048-7.9918 3.5817-7.9942 7.9942.0024 4.4077 3.5865 7.9918 7.9942 7.9942 2.2027.0 4.2018-.8978 5.6479-2.3439C196.1861 344.7844 197.0839 342.7853 197.0839 340.5826z"/></defs><clipPath id="SVGID_16_"><use xlink:href="#SVGID_15_" style="overflow:visible"/></clipPath><path style="clip-path:url(#SVGID_16_);fill:#f1bc42" d="M172.6595 324.15c-3.96 3.96-6.4116 9.4235-6.4116 15.452-.0024 12.0547 9.8066 21.8636 21.8613 21.8612 12.0547.0024 21.8636-9.797 21.8613-21.8612.0024-3.8474-1.0151-7.6327-2.9353-10.9462-3.8977-6.7324-11.1497-10.9151-18.926-10.9151C182.0806 317.7407 176.6171 320.1924 172.6595 324.15z"/></g></g><rect x="198.8952" y="333.6497" style="fill:#f1bc42" width="122.6266" height="13.8671"/></g></g></svg></span><span class="navbar-brand__name">NewLang</span></a> - <div class="td-navbar-nav-scroll ms-md-auto" id="main_navbar"> - <ul class="navbar-nav"> - <li class="nav-item"> - <a class="nav-link" href="/docs/"><span>Documentation</span></a> - </li> - <li class="nav-item"> - <a class="nav-link" href="/playground/"><span>Playground</span></a> - </li> - <li class="nav-item"> - <a class="nav-link active" href="/blog/"><span>Articles</span></a> - </li> - <li class="nav-item dropdown d-none d-lg-block"> - <div class="dropdown"> - <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">English</a> - <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/ru/blog/unusual-prog/">Русский</a></li> - </ul> -</div></li> - </ul> - </div> - <div class="d-none d-lg-block"> - <div class="td-search td-search--offline"> - <div class="td-search__icon"></div> - <input - type="search" - class="td-search__input form-control" - placeholder="Search this site…" - aria-label="Search this site…" - autocomplete="off" - - data-offline-search-index-json-src="/offline-search-index.json" - data-offline-search-base-href="/" - data-offline-search-max-results="10" - > -</div> - </div> -</div> -</nav> - </header> - <div class="container-fluid td-outer"> - <div class="td-main"> - <div class="row flex-xl-nowrap"> - <aside class="col-12 col-md-3 col-xl-2 td-sidebar d-print-none"> - <div id="td-sidebar-menu" class="td-sidebar__inner"> - <form class="td-sidebar__search d-flex align-items-center"> - <div class="td-search td-search--offline"> - <div class="td-search__icon"></div> - <input - type="search" - class="td-search__input form-control" - placeholder="Search this site…" - aria-label="Search this site…" - autocomplete="off" - - data-offline-search-index-json-src="/offline-search-index.json" - data-offline-search-base-href="/" - data-offline-search-max-results="10" - > -</div> - <button class="btn btn-link td-sidebar__toggle d-md-none p-0 ms-3 fas fa-bars" type="button" data-bs-toggle="collapse" data-bs-target="#td-section-nav" aria-controls="td-section-nav" aria-expanded="false" aria-label="Toggle section navigation"> - </button> - </form> - <nav class="td-sidebar-nav collapse" id="td-section-nav"> - <div class="td-sidebar-nav__section nav-item dropdown d-block d-lg-none"> - <div class="dropdown"> - <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">English</a> - <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/ru/blog/unusual-prog/">Русский</a></li> - </ul> -</div> - </div> - <ul class="td-sidebar-nav__section pe-md-3 ul-0"> - <li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child active-path" id="m-blog-li"> - <a href="/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-blog"><span class="">Articles</span></a> - <ul class="ul-1"> - <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v04-li"> - <a href="/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogparser-nuances-li"> - <a href="/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogdsl-domain-specific-language-implementation-with-macros-li"> - <a href="/blog/dsl-domain-specific-language-implementation-with-macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogdsl-domain-specific-language-implementation-with-macros"><span class="">DSL (domain-specific language) implementation with macros</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v03-li"> - <a href="/blog/release-v0.3/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v03"><span class="">Релиз языка программрования NewLang 0.3</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v02-li"> - <a href="/blog/release-v0.2/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v02"><span class="">Релиз языка программрования NewLang 0.2</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogrelease-v01-li"> - <a href="/blog/release-v0.1/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogrelease-v01"><span class="">Релиз языка программрования NewLang</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blognewlang-li"> - <a href="/blog/newlang/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blognewlang"><span class="">Новый язык программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogprog-styles-same-time-li"> - <a href="/blog/prog-styles-same-time/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogprog-styles-same-time"><span class="">Можно ли использовать декларативный и императивный стили написания программ одновременно?</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child active-path" id="m-blogunusual-prog-li"> - <a href="/blog/unusual-prog/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__page" id="m-blogunusual-prog"><span class="td-sidebar-nav-active-item">Необычная концепция синтаксиса языка программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-blogcomplex-prog-li"> - <a href="/blog/complex-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-blogcomplex-prog"><span class="">Простое сложное программирование</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloglang-final-li"> - <a href="/blog/lang-final/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloglang-final"><span class="">Какая «идеальная» цель развития у языков программирования?</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloglogic-prog-li"> - <a href="/blog/logic-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloglogic-prog"><span class="">Проблема логических языков программирования</span></a> -</li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-bloginter-prog-li"> - <a href="/blog/inter-prog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-bloginter-prog"><span class="">Интернациональное программирование на естественных языках</span></a> -</li> - </ul> -</li> - </ul> - </nav> -</div> - - </aside> - <aside class="d-none d-xl-block col-xl-2 td-sidebar-toc d-print-none"> - <div class="td-page-meta ms-2 pb-1 pt-2 mb-0"> -<a id="print" href="/blog/_print/"><i class="fa-solid fa-print fa-fw"></i> Print entire section</a> - -</div> - - <div class="td-toc"> - <nav id="TableOfContents"> - <ul> - <li><a href="#введение">Введение</a></li> - <li><a href="#привет-мир-в-императивной-парадигме">&ldquo;Привет, мир!&rdquo; в императивной парадигме</a></li> - <li><a href="#логическое-программирование-в-декларативной-парадигме">Логическое программирование в декларативной парадигме</a></li> - <li><a href="#формулировка-проверяемой-концепции">Формулировка проверяемой концепции</a></li> - </ul> -</nav> - </div> - - <div class="taxonomy taxonomy-terms-cloud taxo-tags"> - <h5 class="taxonomy-title">Tag Cloud</h5> - <ul class="taxonomy-terms"> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B/" data-taxonomy-term="%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B"><span class="taxonomy-label">Итераторы</span><span class="taxonomy-count">1</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8/" data-taxonomy-term="%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8"><span class="taxonomy-label">Коллекции</span><span class="taxonomy-count">4</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D0%BE%D0%BE%D0%BF/" data-taxonomy-term="%D0%BE%D0%BE%D0%BF"><span class="taxonomy-label">ООП</span><span class="taxonomy-count">3</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B/" data-taxonomy-term="%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B"><span class="taxonomy-label">Системые Типы</span><span class="taxonomy-count">1</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85/" data-taxonomy-term="%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85"><span class="taxonomy-label">Типы Данных</span><span class="taxonomy-count">8</span></a></li> - <li><a class="taxonomy-term" href="http://localhost:1313/tags/%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8/" data-taxonomy-term="%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8"><span class="taxonomy-label">Функции</span><span class="taxonomy-count">1</span></a></li> - </ul> - </div> - - - </aside> - <main class="col-12 col-md-9 col-xl-8 ps-md-5 pe-md-4" role="main"> - <a class="td-rss-button" title="RSS" href="/blog/index.xml" target="_blank" rel="noopener"> - <i class="fa-solid fa-rss" aria-hidden="true"></i> - </a> - -<div class="td-content"> - <h1>Необычная концепция синтаксиса языка программирования</h1> - - <div class="td-byline mb-4"> - - <time datetime="2021-05-24" class="text-muted">Monday, May 24, 2021</time> - </div> - <header class="article-meta"> - - </header> - <p><img alt="КДПВ" src="/blog/langs.jpeg"></p> - - -<div class="pageinfo pageinfo-primary"> -<p>Внимание!!!</p> -<p>Данная статья содержит описание синтаксиса NewLnag предыдущей версии.</p> -<p>Актуальную версию синтаксиса языка можно посмотреть <a href="/docs/">тут</a>.</p> - -</div> - -<p>Хочу представить на обсуждение читателей немного необычный концепт языка программирования, в котором отсутствует проблема, -присущая практически всем промышленным языкам - постоянное увеличение сложности синтаксиса языка из-за его естественного развития по мере выхода новых версий и добавления новых фич. -Эта проблема описана в статье <a href="/blog/complex-prog/">&ldquo;Простое сложное программирование&rdquo;</a> и <a href="/blog/lang-final/">Какая &ldquo;идеальная&rdquo; цель развития у языков программирования?</a></p> -<p>После нескольких экспериментов с синтаксисом, хочется проверить выработанную идею на широкой аудитории <a href="https://habr.com/companies/timeweb/articles/558738/">Хабра</a>, которая как нельзя лучше подходит для этих целей.</p> -<p>Особенности языка:</p> -<ul> -<li>Низкий порог входа и естественное ограничение уровня сложности в течение длительного времени даже при условии постоянного развития самого языка.</li> -<li>Возможность писать код программы как в декларативной, так и в императивной парадигме с использованием процедурного, модульного и объектно-ориентированного подхода.</li> -</ul> -<p>Ну и в соответствии с собственным наблюдением <a href="https://habr.com/post/539674/">Хабр — ума палата</a>, буду рад любым комментариям и предложениям, которые помогут протестировать или улучшить предлагаемое решение.</p> -<h2 id="введение">Введение<a class="td-heading-self-link" href="#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h2> -<p>Первой необычной особенностью языка является полное отсутствие зарезервированных ключевых слов. -Точнее, планируется использовать только одно единственное ключевое слово (название языка), которое может быть как главной точкой входа в приложение, -так и способом доступа к настройкам языка под конкретную предметную область, например при необходимости реализации <a href="https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%B4%D0%BC%D0%B5%D1%82%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D1%8F%D0%B7%D1%8B%D0%BA">DSL парадигмы</a>.</p> -<p>В настоящий момент название языка не выбрано, поэтому для примеров используется просто слово <em>lang</em>, которое в будущем будет изменено.</p> -<p>Данная особенность (отсутствие зарезервированных ключевых слов) реализуется за счет того, грамматика языка основана на использовании общеупотребительных символов и классических знаков препинания, -а все остальные букво-символьные последовательности при парсинге программы рассматриваются как &ldquo;токены&rdquo;.</p> -<p>Компилятор языка реализуется как <a href="https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B0%D0%BD%D1%81%D0%BF%D0%B0%D0%B9%D0%BB%D0%B5%D1%80">transpiler</a> - преобразование исходного кода программы, -написанной на одном языке программирования, в эквивалентный исходный код на другом языке. -Первые эксперименты с синтаксисом я начинал на Python, но после осознания необходимости разработки не только интерпретатора, -но и компилятора непосредственно в исполняемый код, решил остановиться на C++. Хотя в принципе, язык реализации может быть любым.</p> -<p>Использование <a href="https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B0%D0%BD%D1%81%D0%BF%D0%B0%D0%B9%D0%BB%D0%B5%D1%80">транспиляции</a> при реализации компилятора решает сразу множество очевидных и не очень задач. -Сразу отпадает необходимость разрабатывать низкоуровневый компилятор в исполняемый процессорный код, -а в моем случае основным бонусом такого подхода становится возможность использования императивной парадигмы программирования за счет вставок кода непосредственно в исходный код приложения на языке реализации.</p> -<p>И именно этот момент позволяет естественно разделить декларативный и императивный способ написания программы. -В этом случае в декларативной парадигме реализуется только одна из трех базовых управляющих конструкций, -необходимых и достаточных при реализации <a href="https://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5">любого алгоритма</a> — <em>следование</em>.</p> -<p>Другими словами, в декларативном стиле описывается только <em>последовательность</em> операций, которые следуют одна за другой, -но отсутствует возможность запрограммировать циклы или ветвление (переходы) по условию. -Из-за этого в декларативном стиле можно записать только следующие типы языковых конструкций:</p> -<ul> -<li>комментарий</li> -<li>определение переменной и присвоение ей значения</li> -<li>создание объекта и назначение его свойствам значений по умолчанию</li> -<li>создание функции (метода для всего класса объектов)</li> -<li>вызов функции или итератора</li> -<li>непосредственная вставка кода на языке реализации</li> -</ul> -<p>Так как цель текущей публикации - протестировать общую концепцию, то начну сразу с примеров без длинного описания подробностей, а некоторые нюансы буду комментировать по ходу дела. -Тем более, самая главная цель &ldquo;низкий порог входа&rdquo; само собой подразумевает возможность самостоятельно разобраться в синтаксисе. -Тем не менее, совсем без знаний языка реализации не обойтись и начальные знания в программировании на С/С++ все равно необходимы.</p> -<h2 id="привет-мир-в-императивной-парадигме">&ldquo;Привет, мир!&rdquo; в императивной парадигме<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b8%d0%b2%d0%b5%d1%82-%d0%bc%d0%b8%d1%80-%d0%b2-%d0%b8%d0%bc%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d0%bf%d0%b0%d1%80%d0%b0%d0%b4%d0%b8%d0%b3%d0%bc%d0%b5" aria-label="Heading self-link"></a></h2> -<p>Определение обычной функции выполняется с помощью оператора присвоения &ldquo;:=&rdquo;, а программный код на языке реализации (в данном случае на C++) -заключается в фигурные скобки. Простой пример вывода строки на экран выглядит примерно так:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span> <span style="color:#000">print</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">str</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#4e9a06">&#34;&#34;</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000;font-weight:bold">{</span> <span style="color:#000">printf</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;%s&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">static_cast</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#204a87;font-weight:bold">char</span> <span style="color:#ce5c00;font-weight:bold">*&gt;</span><span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">$</span><span style="color:#000">str</span><span style="color:#000;font-weight:bold">));</span> <span style="color:#000;font-weight:bold">}</span> -</span></span></code></pre></div><p>Функция <strong>print</strong> с аргументом по умолчанию в виде пустой строки внутри себя вызывает обычный printf из стандартной библиотеки.</p> -<p>Соответственно &ldquo;Привет, мир!&rdquo; в императивной парадигме программирования будет выглядеть тривиально:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic">#!/bin/lang -</span></span></span><span style="display:flex;"><span><span style="color:#8f5902;font-style:italic"></span> <span style="color:#000">print</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">str</span><span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#4e9a06">&#34;&#34;</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000;font-weight:bold">{</span> <span style="color:#000">printf</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;%s&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#204a87;font-weight:bold">static_cast</span><span style="color:#ce5c00;font-weight:bold">&lt;</span><span style="color:#204a87;font-weight:bold">char</span> <span style="color:#ce5c00;font-weight:bold">*&gt;</span><span style="color:#000;font-weight:bold">(</span><span style="color:#a40000">$</span><span style="color:#000">str</span><span style="color:#000;font-weight:bold">));</span> <span style="color:#000;font-weight:bold">};</span> -</span></span><span style="display:flex;"><span> <span style="color:#a40000">@</span><span style="color:#000">print</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Привет, мир!</span><span style="color:#4e9a06">\n</span><span style="color:#4e9a06">&#34;</span><span style="color:#000;font-weight:bold">);</span> -</span></span></code></pre></div><p>Из примера видно, что обращение к аргументам внутри С++ кода происходит с использованием символа <strong>$</strong>, который указывается вначале именованного аргумента. -Кроме этого, для доступа к аргументам функции можно обращаться по их порядковым номерам начиная с первого ($1, $2, $3 и т. д.). -Зарезервированный аргумент $0 содержит сам объект, метод которого вызывается или <em>nullptr</em>, если функция не принадлежит объекту.</p> -<p><em>Обычные</em> функции являются именно обычными функциями в понимании С/С++. -Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д. -Технически, код такой функции парсится на предмет замены использованных аргументов, -специальным образом декорируется её имя и добавляются специальные маркеры для идентификации содержимого. -После этого исходный текст готов для сборки обычным С++ компилятором для превращения в динамическую библиотеку -и после её загрузки функцию можно будет вызвать в любой момент (для вызова функции перед её именем необходимо указать символ <strong>&quot;@&quot;</strong>).</p> -<p>Непосредственное выполнение файла в режиме интерпретатора происходит в два этапа. На первом этапе из текста программы генерируется временный С++ файл с исходным кодом всех функций, этот файл компилируется gcc и собирается динамическая библиотека.</p> -<p>На втором этапе, собранная динамическая библиотека загружается средой выполнения, а исходный текст программы начинает последовательно выполнятся интерпретатором (все строки, за исключением определений функций).</p> -<p>Есть еще вариант, когда вместо интерпретации кода программы, генерируется С++ файл не только для функций, но и для основной части приложения. -Тогда на выходе компилятора будет уже обычный бинарный файл, хотя в том случае оперативно поправить текст программы уже не получится.</p> -<h2 id="логическое-программирование-в-декларативной-парадигме">Логическое программирование в декларативной парадигме<a class="td-heading-self-link" href="#%d0%bb%d0%be%d0%b3%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%b2-%d0%b4%d0%b5%d0%ba%d0%bb%d0%b0%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d0%bf%d0%b0%d1%80%d0%b0%d0%b4%d0%b8%d0%b3%d0%bc%d0%b5" aria-label="Heading self-link"></a></h2> -<p>Так как самым известным языком логического программирования в декларативном стиле считается Prolog, -поэтому приведу простой пример программы Brother (поиска братьев) на Прологе и эквивалентный ему код на новом языке.</p> -<p>Prolog:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> male<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Tom&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span>. -</span></span><span style="display:flex;"><span> male<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Tim&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span>. -</span></span><span style="display:flex;"><span> male<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Jake&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span>. -</span></span><span style="display:flex;"><span> female<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Janna&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span>. -</span></span><span style="display:flex;"><span> parent<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Tom&#34;</span>,<span style="color:#4e9a06">&#34;Jake&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span>. -</span></span><span style="display:flex;"><span> parent<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Janna&#34;</span>,<span style="color:#4e9a06">&#34;Jake&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span>. -</span></span><span style="display:flex;"><span> parent<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Tom&#34;</span>,<span style="color:#4e9a06">&#34;Tim&#34;</span><span style="color:#ce5c00;font-weight:bold">)</span>. -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> brother<span style="color:#ce5c00;font-weight:bold">(</span>X,Y<span style="color:#ce5c00;font-weight:bold">)</span>:- parent<span style="color:#ce5c00;font-weight:bold">(</span>Z,X<span style="color:#ce5c00;font-weight:bold">)</span>,parent<span style="color:#ce5c00;font-weight:bold">(</span>Z,Y<span style="color:#ce5c00;font-weight:bold">)</span>,male<span style="color:#ce5c00;font-weight:bold">(</span>X<span style="color:#ce5c00;font-weight:bold">)</span>,male<span style="color:#ce5c00;font-weight:bold">(</span>Y<span style="color:#ce5c00;font-weight:bold">)</span>,X<span style="color:#4e9a06">\=</span>Y. -</span></span></code></pre></div><p>Вывод: <strong>(Jake, Tim) (Tim, Jake)</strong></p> -<p>Тот же самый пример:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic">#!/bin/lang</span> -</span></span><span style="display:flex;"><span> human:<span style="color:#ce5c00;font-weight:bold">=</span>@term<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">sex</span><span style="color:#ce5c00;font-weight:bold">=</span>,parent<span style="color:#ce5c00;font-weight:bold">=)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Tom:<span style="color:#ce5c00;font-weight:bold">=</span>@human<span style="color:#ce5c00;font-weight:bold">(</span>male<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Janna:<span style="color:#ce5c00;font-weight:bold">=</span>@human<span style="color:#ce5c00;font-weight:bold">(</span>female<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Jake:<span style="color:#ce5c00;font-weight:bold">=</span>@human<span style="color:#ce5c00;font-weight:bold">(</span>male, <span style="color:#ce5c00;font-weight:bold">(</span>Tom, Janna,<span style="color:#ce5c00;font-weight:bold">))</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Tim:<span style="color:#ce5c00;font-weight:bold">=</span>@human<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">sex</span><span style="color:#ce5c00;font-weight:bold">=</span>male, <span style="color:#000">parent</span><span style="color:#ce5c00;font-weight:bold">=(</span>Tom,<span style="color:#ce5c00;font-weight:bold">))</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> human::brother<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">test</span><span style="color:#ce5c00;font-weight:bold">=</span>human!<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">&amp;&amp;=</span> <span style="color:#000">$0</span>!<span style="color:#ce5c00;font-weight:bold">=</span><span style="color:#000">$test</span>, <span style="color:#000">$0</span>.sex<span style="color:#ce5c00;font-weight:bold">==</span>male, @intersec<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">$0</span>.parent, <span style="color:#000">$test</span>.parent<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> human.brother? -</span></span></code></pre></div><p>Вывод: <strong>[Tim.brother(Jake), Jake.brother(Tim),]</strong></p> -<p>Надеюсь, что синтаксис интуитивно понятен, особенно при наличии эквивалентного кода на Прологе, но на всякий случай поясню отдельные моменты.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> human:<span style="color:#ce5c00;font-weight:bold">=</span>@term<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">sex</span><span style="color:#ce5c00;font-weight:bold">=</span>,parent<span style="color:#ce5c00;font-weight:bold">=)</span><span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>В этой строке создается объект с именем &ldquo;human&rdquo; и двумя свойствами &ldquo;sex&rdquo; и &ldquo;parent&rdquo;, -значения которых по умолчанию не определены, а родителем является системный объект &ldquo;term&rdquo;. -Использование символа <strong>&quot;@&quot;</strong> в начале термина обозначает вызов существующей функции с параметрами, указанными в скобках. -В данном случае вызывается конструктор системного объекта &ldquo;term&rdquo;, а возвращаемым результатом является новый термин &ldquo;human&rdquo;, -который можно воспринимать как один экземпляр класса, так и как имя целого класса, если он будет выступать в качестве родителя для других объектов.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> Tom:<span style="color:#ce5c00;font-weight:bold">=</span>@human<span style="color:#ce5c00;font-weight:bold">(</span>male<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Janna:<span style="color:#ce5c00;font-weight:bold">=</span>@human<span style="color:#ce5c00;font-weight:bold">(</span>female<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Jake:<span style="color:#ce5c00;font-weight:bold">=</span>@human<span style="color:#ce5c00;font-weight:bold">(</span>male, <span style="color:#ce5c00;font-weight:bold">(</span>Tom, Janna,<span style="color:#ce5c00;font-weight:bold">))</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> Tim:<span style="color:#ce5c00;font-weight:bold">=</span>@human<span style="color:#ce5c00;font-weight:bold">(</span><span style="color:#000">parent</span><span style="color:#ce5c00;font-weight:bold">=(</span>Tom,<span style="color:#ce5c00;font-weight:bold">)</span>, <span style="color:#000">sex</span><span style="color:#ce5c00;font-weight:bold">=</span>male<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>Первые две строки создают объекты &ldquo;Tom&rdquo; и &ldquo;Janna&rdquo;, у которых свойство &ldquo;sex&rdquo; установлено в значения &ldquo;male&rdquo; и &ldquo;female&rdquo; соответственно. -А в последней строке при создании объекта Tim значения свойств задается с указанием их имени.</p> -<p>Конструкции <em>(Tom, Janna,)</em> и <em>(Tom,)</em>, это определение константного литерала с типом словарь, которые присваиваются указанным свойствам.</p> -<p>Чтобы определение словаря не путать с указанием аргументов при вызове функции, в нем содержится обязательная финальная запятая перед закрывающей скобкой. -Это правило (финальная запятая перед закрывающей скобкой) действует и при определении литерала массива, только для записи которого используются скобки не круглые, а квадратные (например <strong>[,]</strong> - пустой массив). -Основным отличием словаря от массива, заключаются в способах доступа к их элементам. -Для доступа к элементу массива используется целочисленный индекс, а в словаре может быть использован как индекс, так и имя элемента при его наличии. -Между словарем и массивом есть еще отличия, но сейчас они не принципиальны.</p> -<p>И предпоследняя строка в примере:</p> -<p>human::brother(test=human <em>!</em>) <strong>&amp;&amp;=</strong> <em>$0</em> != <em>$test</em>, <em>$0</em>.sex==male, @intersec(<em>$0</em>.parent, <em>$test</em>.parent);</p> -<p>это определение <i>простой чистой</i> функции &ldquo;brother&rdquo; для всех объектов, производных от &ldquo;human&rdquo;. -Данная функция принимает один именованный аргумент &ldquo;test&rdquo;, значением по умолчанию которого является <em>итератор</em> объектов класса &ldquo;human&rdquo;.</p> -<p>Оператор <strong>&amp;&amp;=</strong> означает определение <em>простой чистой</em> функции, т. е. функции без внешних зависимостей, -которая не имеет доступа к глобальному контексту, а результат выполнения которой является логическое значение, -которое вычисляется по схеме <a href="https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BD%D1%8A%D1%8E%D0%BD%D0%BA%D1%86%D0%B8%D1%8F">логическое И</a> для всех условий, указанных в теле функции через запятую.</p> -<p>Выполнение и вывод результата выполнения программы происходит в строке -<code>human.brother?</code></p> -<p>Восклицательный и вопросительный знаки обозначают <a href="https://ru.wikipedia.org/wiki/%D0%98%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80">итератор</a>. Итератор &ldquo;<strong>!</strong>&rdquo; возвращает один текущий элемент из коллекции и передвигает указатель на следующий, -а итератор &ldquo;<strong>?</strong>&rdquo; возвращает сразу всю коллекцию объектов целиком.</p> -<p>Другими словами при выполнении строки программы <em>human.brother <strong>?</strong></em> происходит последовательный перебор всей коллекции объектов типа &ldquo;human&rdquo;, -где у каждого объекта выполняется функция &ldquo;brother&rdquo; с аргументами по умолчанию. -А так как в качестве аргумента по умолчанию указан итератор <em>human <strong>!</strong></em>, то в качестве аргумента последовательно предается каждый из элементов указанного класса. -По сути, при выполнении этой строки происходит полный перебор всех возможных комбинаций объектов класса &ldquo;human&rdquo; каждый с каждым.</p> -<blockquote> -<p>Более подробное описание работы итератора и причина выбора такого синтаксиса опубликовано в отдельной статье <a href="https://habr.com/company/timeweb/blog/559916/">Лаконичный итератор для декларативного синтаксиса</a></p> -</blockquote> -<p>Результат выполнения будет состоять из тех пар объектов, для которых функция &ldquo;brother&rdquo; вернет истину, т.е. результат выполнения будет массив из двух пар объектов <strong>[Tim.brother(Jake), Jake.brother(Tim),]</strong>.</p> -<h2 id="формулировка-проверяемой-концепции">Формулировка проверяемой концепции<a class="td-heading-self-link" href="#%d1%84%d0%be%d1%80%d0%bc%d1%83%d0%bb%d0%b8%d1%80%d0%be%d0%b2%d0%ba%d0%b0-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d1%8f%d0%b5%d0%bc%d0%be%d0%b9-%d0%ba%d0%be%d0%bd%d1%86%d0%b5%d0%bf%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h2> -<p>Тестируемая концепция заключается в следующем. Синтаксис языка программирования состоит как бы из двух частей, -каждая из которых является относительно независимой и в тоже время они связаны между собой.</p> -<p>Первая часть сложная — предназначена для описания алгоритмов в <em>императивном стиле</em> на обычном языке программирования, -поэтому внутри функций разработчику доступны все возможности языка реализации.</p> -<p>Вторая часть простая (по сравнению с первой) — предназначена только для логического описания задачи в <em>декларативном стиле</em>. -Именно эта часть используется для начального уровня использования, а естественное ограничение только на последовательное выполнение операторов -(т.е. отсутствие циклов и ветвлений) не доставляет чрезмерных сложностей в понимании исходного текста программы даже в будущем по мере развития языка.</p> -<p>Связь между двумя вариантами синтаксиса прозрачна и реализуется за счет совместного использования переменных и функций, -декларация и обращение к которым происходит в едином стиле в обоих случаях за счет унификации синтаксиса на уровне использования знаков препинания.</p> -<p>Сейчас я специально не привожу полного синтаксиса и подробного описания остальных возможностей языка, т.к. компилятор пока не готов для публичной презентации. -Но буду крайне благодарен за любой отклик или дельные предложения в отношении предложенной концепции.</p> -<p>Особенно это касается возможных конфликтов по синтаксису в представленных примерах.</p> - - <ul class="list-unstyled d-flex justify-content-between align-items-center mb-0 pt-5"> - <li> - <a href="/blog/complex-prog/" aria-label="Previous - Простое сложное программирование" class="btn btn-primary"><span class="me-1">←</span>Previous</a> - </li> - <li> - <a href="/blog/prog-styles-same-time/" aria-label="Next - Можно ли использовать декларативный и императивный стили написания программ одновременно?" class="btn btn-primary">Next<span class="ms-1">→</span></a> - </li> -</ul> - - </div> - - - </main> - </div> - </div> - <footer class="td-footer row d-print-none"> - <div class="container-fluid"> - <div class="row mx-md-2"> - <div class="td-footer__left col-6 col-sm-4 order-sm-1"> - <ul class="td-footer__links-list"> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="User mailing list" aria-label="User mailing list"> - <a target="_blank" rel="noopener" href="mailto:mail@newlang.net" aria-label="User mailing list"> - <i class="fa fa-envelope"></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - -</ul> - - </div><div class="td-footer__right col-6 col-sm-4 order-sm-3"> - <ul class="td-footer__links-list"> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="GitHub" aria-label="GitHub"> - <a target="_blank" rel="noopener" href="https://github.com/rsashka/newlang" aria-label="GitHub"> - <i class="fab fa-github"></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - - <li class="td-footer__links-item" data-bs-toggle="tooltip" title="" aria-label=""> - <a target="_blank" rel="noopener" href="" aria-label=""> - <i class=""></i> - </a> - </li> - -</ul> - - </div><div class="td-footer__center col-12 col-sm-4 py-2 order-sm-2"> - <span class="td-footer__copyright">&copy; - 2024 - <span class="td-footer__authors">The NewLang Authors</span></span><span class="td-footer__all_rights_reserved">All Rights Reserved</span> - </div> - </div> - </div> -</footer> - - </div> - <script src="/js/main.js"></script> -<script defer src="/js/click-to-copy.js" crossorigin="anonymous"></script> -<script src='/js/tabpane-persist.js'></script> - - </body> -</html> \ No newline at end of file diff --git a/docs/docs/_print/index.html b/docs/docs/_print/index.html index b1806157..5a730b79 100644 --- a/docs/docs/_print/index.html +++ b/docs/docs/_print/index.html @@ -174,7 +174,7 @@ <h1 class="title">Documentation</h1> -<li>1.5: <a href="#pg-66431dc9242fce562d24bb69bdc576f3">Макросы</a></li> +<li>1.5: <a href="#pg-66431dc9242fce562d24bb69bdc576f3">Macros</a></li> @@ -297,7 +297,7 @@ <h1 class="title">Documentation</h1> -<li>2.9: <a href="#pg-cf08b42ee4f3746e6fd20919aa6660c8">Нативные типы</a></li> +<li>2.9: <a href="#pg-cf08b42ee4f3746e6fd20919aa6660c8">Native Data Types</a></li> @@ -445,44 +445,15 @@ <h1 class="title">Documentation</h1> <div class="content"> - <p>Основные материалы по языку программирования NewLang.</p> -<p>Описание акутально для текущей версии 4.0</p> -<p>clang-17 не поддерживает:</p> -<table> -<thead> -<tr> -<th>Feature</th> -<th>Proposal</th> -<th>Available</th> -</tr> -</thead> -<tbody> -<tr> -<td>Coroutines</td> -<td>P0912R5</td> -<td><em>Partial</em> Fully supported on all targets except Windows, which still has some stability and ABI issues.</td> -</tr> -<tr> -<td>Extended floating-point types and standard names</td> -<td>P1467R9</td> -<td>No</td> -</tr> -<tr> -<td>Concepts</td> -<td>P0848R3</td> -<td>Clang 16 (Partial)</td> -</tr> -<tr> -<td>Modules</td> -<td></td> -<td>No</td> -</tr> -</tbody> -</table> -<h3 id="начиная-с-c-should-adopt-the-same-characters-for-c26">Начиная с C++ should adopt the same characters for C++26.<a class="td-heading-self-link" href="#%d0%bd%d0%b0%d1%87%d0%b8%d0%bd%d0%b0%d1%8f-%d1%81-c-should-adopt-the-same-characters-for-c26" aria-label="Heading self-link"></a></h3> -<ul> -<li>Add <strong>@</strong>, <strong>$</strong>, and ` to the basic character set P2558R2 Yes</li> -</ul> + + +<div class="pageinfo pageinfo-primary"> +<p>The materials are in the process of being translated into English!</p> + +</div> + +<p>Basic materials on the NewLang programming language.</p> +<p>The description is valid for the current <a href="https://github.com/rsashka/newlang/releases/tag/v0.4.0">version 0.4</a></p> </div> </div> @@ -502,17 +473,17 @@ <h3 id="начиная-с-c-should-adopt-the-same-characters-for-c26">Начин -<div class="td-content" style="page-break-before: always"> +<div class="td-content" style=""> <h1 id="pg-b5bb7377324fcfd7c83c1943bfd4e128">1 - Синтаксис</h1> <div class="lead">Правила синтаксиса и основные понятия языка программирования NewLang</div> <ul> -<li>Операторы разделяются точкой с запятой «;».</li> -<li>Отступы и переводы строк игнорируются.</li> -<li>Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash.</li> -<li>Многострочные комментарии соответствуют стилю С/С++ и должны располагаться между символами /* и */. Многосточные комментарии могут быть вложенными.</li> -<li>Последовательность команд <a href="/docs/ops/block/">(блок кода)</a> заключаются в фигурные скобки &ldquo;<strong>{</strong>&rdquo; и &ldquo;<strong>}</strong>&rdquo;.</li> -<li>Большинство операторов являются выражениями и возвращают результат выполнения последней операции.</li> +<li>Operators are separated by a semicolon &ldquo;;&rdquo;.</li> +<li>Indentations and line breaks are ignored.</li> +<li>Single-line comments start with the symbol &ldquo;#&rdquo; until the end of the line, following the style of Python and Bash comments.</li> +<li>Multi-line comments follow the C/C++ style and should be enclosed between &ldquo;/*&rdquo; and &ldquo;*/&rdquo;. Multi-line comments can be <em>nested</em>.</li> +<li>Command sequences <a href="/docs/ops/block/">(code block)</a> are enclosed in curly braces &ldquo;<strong>{</strong>&rdquo; and &ldquo;<strong>}</strong>&rdquo;.</li> +<li>Most operators are expressions and return the result of the last operation.</li> </ul> </div> @@ -1077,425 +1048,100 @@ <h3 id="пример-программы">Пример программы<a class <div class="td-content" style="page-break-before: always"> - <h1 id="pg-66431dc9242fce562d24bb69bdc576f3">1.5 - Макросы</h1> - - <p>Макросы в <strong>NewLang</strong>, это один или несколько последовательных терминов, которые заменяются на другой термин -или на целую синтаксическую конструкцию (последовательность лексем).</p> -<p>Макросы обработываются во время работы <strong>лексера</strong>, т.е. перед передачей последовательности лексем в парсер, -что позволяет с их помощью изменять даже сам синтаксис языка, например, при реализации собственных диалектов DSL.</p> -<h3 id="определение-макросов">Определение макросов<a class="td-heading-self-link" href="#%d0%be%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2" aria-label="Heading self-link"></a></h3> -<p>Определение макросов аналогично <a href="/docs/ops/create/">определению</a> других объектов и состоит из трех частей -<strong>&lt;имя макроса&gt; &lt;оператор создания/присвоения&gt; &lt;тело макроса&gt;</strong> и завершающая точка с запятой &ldquo;<strong>;</strong>&rdquo;, -т.е. применяются обычные операторы <strong>::=</strong>, <strong>=</strong> или <strong>:=</strong> для создания нового или переопределения уже существующего объекта, -а имя макроса указывается между двумя символами <strong>&quot;@@&quot;</strong> и может содержать одну или нескольких лексем (терминов).</p> -<p>Все макросы относятся к глобальному пространству имен, поэтому первый термин в имени макроса должен быть уникальным, -иначе он будет прекрывать имена локальных и глобальных переменных при <a href="/docs/syntax/naming/">разрешении имен</a>, -если они указаны в коде без квалификаторов.</p> -<p>??????????????????????? -Чистые (гигиеничные) макросы, <strong>::-</strong> <strong>:-</strong>, аргумента и переммые в которых гарантиованно не пересекаются с пространством имен программы?????????????????</p> -<p>Телом макроса могут быть корректное выражение языка, последовательность лексем (которые заключается в двойные собачки <strong>&quot;@@&quot;</strong>, -т.е. <strong><code>@@ лексема1 лексема1 @@</code></strong>) или обычная текстовая строка (которую нужно указать между тройными собачками <strong>&quot;@@@&quot;</strong>, т.е. <strong><code>@@@ текстовая строка @@@</code></strong>).</p> -<p>В имени макроса, кроме первого термина, могут присутствовать один или несколько шаблонов. -<em>Шаблон</em> — это термин, который при сопоставлении последовательности лексем с идентификатором макроса -может заменяться любым другим одиночным термином (т.е. фактически это сопоставление по образцу/шаблону).</p> -<p>Для создания термина-шаблона в начале его идентификатора нужно поставить знак доллара (что соответствует квалификатору локальной переменой), -т.е. имя макроса <code>@@ FUNC $name @@</code> будет соответствовать последовательности лексем как <code>FUNC my_func_name</code>, так и <code>FUNC other_name_func</code>.</p> -<p>Для удаления макроса используется специальный синтаксис: <code>@@@@ name @@@@;</code> или <code>@@@@ два термина @@@@;</code>, -т.е. необходимо указать идентификатор макроса между четырмя символами <strong>&quot;@@@@&quot;</strong>.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Тело макроса из текстовой строки (как в препроцессоре С/С++)</span> -</span></span><span style="display:flex;"><span> @@macro_str@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@@ строка - тело макроса @@@<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Строка для лексера</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Удаления макроса @macro_str</span> -</span></span><span style="display:flex;"><span> @@@@ macro_str @@@@<span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><h3 id="аргументы-макросов-и-их-раскрытие">Аргументы макросов и их раскрытие<a class="td-heading-self-link" href="#%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d1%8b-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2-%d0%b8-%d0%b8%d1%85-%d1%80%d0%b0%d1%81%d0%ba%d1%80%d1%8b%d1%82%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> -<p>Макросы можно определять как с аргументами (параметрами в скобках), так и без них. -Если макрос был определен с аргументами, то их проверка будет выполнятся макропроцессором при определении и раскрытии макроса. -Если макрос был определен без аргументов, то их наличие макропроцессором игнорируется.</p> -<p>Так как макропроцессор считает макросы с аргументами и без оных идентичными, то нельзя создать два макроса -с одинаковыми именами, один из которых будет с аргументами (скобками), а другой без них.</p> -<p>Поэтому, если требуется использовать макрос в двух разных вариантах (с аргументами и без них), -тогда следует определять макрос без аргументов и в этом случае контроль параметров будет производить компилятор.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> @@macro@@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Макрос без аргументов</span> + <h1 id="pg-66431dc9242fce562d24bb69bdc576f3">1.5 - Macros</h1> + + <p>Macros are also used to transform the original code of <em>NewLang</em> into a more familiar syntax based on <a href="/docs/syntax/dsl/">keywords</a>, +as such text is much easier to understand when reading the original code later.</p> +<p>In <strong>NewLang</strong>, macros are one or more consecutive terms that are replaced with another term or a whole syntactic construction (a sequence of lexemes).</p> +<p>Macros are processed during the operation of the <strong>lexer</strong>, i.e., before passing the sequence of lexemes to the parser, +allowing fragments of the language syntax to be modified using macros, for example, when implementing custom DSL dialects.</p> +<h3 id="defining-macros">Defining Macros<a class="td-heading-self-link" href="#defining-macros" aria-label="Heading self-link"></a></h3> +<p>The definition of macros is similar to the <a href="/docs/ops/create/">definition</a> of other objects and consists of three parts +<strong><macro name> &lt;creation/assignment operator&gt; <macro body></strong> and ends with a semicolon &ldquo;<strong>;</strong>&rdquo;, i.e., +normal operators <strong>::=</strong>(<strong>::-</strong>), <strong>=</strong>, or <strong>:=</strong>(<strong>:-</strong>) are used to create a new or redefine an existing object, +and the macro name is indicated between two symbols <strong>&quot;@@&quot;</strong> and can contain one or more lexemes (terms).</p> +<p>All macros belong to the global namespace, so the first term in the macro name must be unique, +otherwise it will override local and global variables during <a href="/docs/syntax/naming/#name-lookup">name lookup</a> +if they are written in the program text without <a href="/docs/syntax/naming/#sigil">qualifiers (sigils)</a>.</p> +<p>Using the operators <strong>::-</strong> and <strong>:-</strong> creates pure (hygienic) macros, arguments and variables in which are guaranteed not to intersect with the program&rsquo;s namespace.</p> +<p>The body of a macro can be a valid language expression, a sequence of lexemes (enclosed in double at symbols <strong>&quot;@@&quot;</strong>, +i.e. <strong><code>@@ lexeme1 lexeme2 @@</code></strong>), or a regular text string (which should be specified between triple at symbols <strong>&quot;@@@&quot;</strong>, +i.e. <strong><code>@@@ text string @@@</code></strong>).</p> +<p>In the macro name after the first term, one or more templates may be present. +A <em>template</em> is a term that, when matching a sequence of lexemes with the macro identifier, +can be replaced by any other single term (effectively, this is pattern/template matching).</p> +<p>To create a template term, a dollar sign should be placed at the beginning of its identifier (which corresponds to a qualifier of a local variable), +i.e. the macro name <code>@@ FUNC $name @@</code> will correspond to the sequence of lexemes as <code>FUNC my_func_name</code> as well as <code>FUNC other_name_func</code>.</p> +<p>To remove a macro, a special syntax is used: <code>@@@@ name @@@@;</code> or <code>@@@@ two terms @@@@;</code>, +i.e. you need to specify the macro identifier between four characters <strong>&quot;@@@@&quot;</strong>.</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Macro body from a text string (as in C/C++ preprocessor)</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#5c35cc;font-weight:bold">@macro_str</span><span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@@</span> <span style="color:#000">string</span> <span style="color:#ce5c00;font-weight:bold">-</span> <span style="color:#000">macro</span> <span style="color:#000">body</span> <span style="color:#ce5c00;font-weight:bold">@@@</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># String for the lexer</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Removing macro @macro_str</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@@@</span> <span style="color:#000">macro_str</span> <span style="color:#ce5c00;font-weight:bold">@@@@</span><span style="color:#000;font-weight:bold">;</span> +</span></span></code></pre></div><h3 id="args">Macro Arguments and Expansion<a class="td-heading-self-link" href="#args" aria-label="Heading self-link"></a></h3> +<p>Macros can be defined with arguments (parameters in parentheses) or without them. +If a macro was defined with arguments, their validation will be performed by the macro processor during definition and expansion of the macro. +If a macro was defined without arguments, the presence of arguments will be ignored by the macro processor.</p> +<p>The macroprocessor considers macros with and without arguments identical, +so it is not possible to create two macros with the same name, one with arguments (in parentheses) and the other without.</p> +<p>Therefore, if you need to use a macro in two different ways (with arguments and without), +you should define the macro without arguments, and in this case, the parameter control will be done by the compiler.</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> @@ macro @@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Macro without arguments</span> </span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> macro<span style="color:#ce5c00;font-weight:bold">(</span>args<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># ОК -&gt; term(args);</span> -</span></span><span style="display:flex;"><span> macro<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># ОК -&gt; term;</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Но </span> -</span></span><span style="display:flex;"><span> @@call<span style="color:#ce5c00;font-weight:bold">()</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> call<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># ОК -&gt; term();</span> -</span></span><span style="display:flex;"><span> call<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Ошибка (@call определен с аргументами) </span> -</span></span></code></pre></div><p>Если при определении макроса указаны аргументы, то место для их вставки в теле макроса -записывается как имя локальной переменой, перед которой добавлен символ <strong>&quot;@&quot;</strong>, т.е. <strong>@$arg</strong>.</p> -<p>Произвольное количество аргументов у макроса отмечается троеточием <strong>&quot;&hellip;&quot;</strong>, а место для их вставки отмечается в теле макроса лексемой <strong>&quot;@$&hellip;&quot;</strong>.</p> -<p>Место для вставки числа реально переданных аргументов отмечается лексемой <strong>&quot;@$#&quot;</strong>. -Если требуется вставить переданные аргументы в виде элементов словаря, -то место для вставки отмечается лексемой <strong>&quot;@$*&quot;</strong>.</p> -<p>По аналогии с препроцессором С/С++, для соединения двух лексем в одну, в теле макроса используется оператор <strong>&quot;@##&quot;</strong>, -а для преобразование лексемы в текстову строку применяется операторы <strong>@#</strong>, <strong>@#&quot;</strong> или <strong>@#&rsquo;</strong>, например, -<code>@@macro($arg)@@ := @@ func_ @## @$arg( @#&quot; arg ) @;</code>, тогда вызов <code>macro(name);</code> будет преобразован в <code>func_name (&quot;name&quot;);</code></p> - - -<div class="pageinfo pageinfo-primary"> -<h4 id="ограничения-макропроцессора-в-текущей-версии">Ограничения макропроцессора в текущей версии<a class="td-heading-self-link" href="#%d0%be%d0%b3%d1%80%d0%b0%d0%bd%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d0%bf%d1%80%d0%be%d1%86%d0%b5%d1%81%d1%81%d0%be%d1%80%d0%b0-%d0%b2-%d1%82%d0%b5%d0%ba%d1%83%d1%89%d0%b5%d0%b9-%d0%b2%d0%b5%d1%80%d1%81%d0%b8%d0%b8" aria-label="Heading self-link"></a></h4> -<p>На текущий момент макросы реализованы в минимальном объеме для самых простых сценариев использования:</p> -<ul> -<li>DSL для keyword based syntax (if, else, return, match, while и т.д.) - (1 термин с произвольными аргументами и без) - требуется сейчас !!!</li> -</ul> -<p><em>Парсер при обработке макросов может анализировать информацию о типах данных, если она указана.</em> -<em>Но на текущий момент типы данных в макросах никак не обрабатываются и это одна из обязательных фич, которая будет реализована в будущем.</em></p> -<ul> -<li>Определения (func, class) - (несколько терминов с аргументами и без аргументов) - Реализация ООП и импорт С++ классов</li> -<li>Модификации при определениях (override) - (несколько терминов и шаблоны с аргументами и без аргументов) - Реализация ООП и импорт С++ классов</li> -</ul> - -</div> - -<h1 id="макросы-без-аргументов-или-все-аргументы-сразу-">МАКРОСЫ БЕЗ АРГУМЕНТОВ ИЛИ ВСЕ АРГУМЕНТЫ СРАЗУ !!!!!<a class="td-heading-self-link" href="#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b1%d0%b5%d0%b7-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d0%b8%d0%bb%d0%b8-%d0%b2%d1%81%d0%b5-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d1%8b-%d1%81%d1%80%d0%b0%d0%b7%d1%83-" aria-label="Heading self-link"></a></h1> -<h1 id="анализа-аргументов-или-их-типов-не-производится-">анализа аргументов или их типов не производится !!!<a class="td-heading-self-link" href="#%d0%b0%d0%bd%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d0%b8%d0%bb%d0%b8-%d0%b8%d1%85-%d1%82%d0%b8%d0%bf%d0%be%d0%b2-%d0%bd%d0%b5-%d0%bf%d1%80%d0%be%d0%b8%d0%b7%d0%b2%d0%be%d0%b4%d0%b8%d1%82%d1%81%d1%8f-" aria-label="Heading self-link"></a></h1> -<p>Lambda -@@ lambda $name(&hellip;) @@ ::= @@ @$name( @$&hellip; ) ::= ( _( @$&hellip; ) ::= @<strong>PRAGMA_FINALIZE</strong>( @), {, {+, {-, {* ) @@</p> -<h3 id="примеры-использования-макросов">Примеры использования макросов<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80%d1%8b-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2" aria-label="Heading self-link"></a></h3> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Обычные макросы (тело макроса корректное выражение)</span> -</span></span><span style="display:flex;"><span> @@macro@@ :<span style="color:#ce5c00;font-weight:bold">=</span> replace<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@macro2<span style="color:#ce5c00;font-weight:bold">(</span>arg<span style="color:#ce5c00;font-weight:bold">)</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">{</span> call<span style="color:#ce5c00;font-weight:bold">(</span>@<span style="color:#000">$arg</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> call<span style="color:#ce5c00;font-weight:bold">()}</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Тело макросов из последовательности лексем</span> -</span></span><span style="display:flex;"><span> @@if<span style="color:#ce5c00;font-weight:bold">(</span>...<span style="color:#ce5c00;font-weight:bold">)</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ <span style="color:#ce5c00;font-weight:bold">[</span> <span style="color:#4e9a06">\$</span><span style="color:#204a87;font-weight:bold">if</span><span style="color:#ce5c00;font-weight:bold">(</span>*<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">]</span>--&gt; @@<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Выражение может быть не полным</span> -</span></span><span style="display:flex;"><span> @@elif<span style="color:#ce5c00;font-weight:bold">(</span>...<span style="color:#ce5c00;font-weight:bold">)</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ ,<span style="color:#ce5c00;font-weight:bold">[</span> <span style="color:#4e9a06">\$</span><span style="color:#204a87;font-weight:bold">elif</span><span style="color:#ce5c00;font-weight:bold">(</span>*<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">]</span>--&gt; @@<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@else@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ ,<span style="color:#ce5c00;font-weight:bold">[</span>_<span style="color:#ce5c00;font-weight:bold">]</span>--&gt; @@<span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> macro<span style="color:#ce5c00;font-weight:bold">(</span>args<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># OK -&gt; term(args);</span> +</span></span><span style="display:flex;"><span> macro<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># OK -&gt; term;</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># But</span> +</span></span><span style="display:flex;"><span> @@ call<span style="color:#ce5c00;font-weight:bold">()</span> @@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span> call<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># OK -&gt; term();</span> +</span></span><span style="display:flex;"><span> call<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Error (@call is defined with arguments) </span> +</span></span></code></pre></div><p>If arguments are specified when defining a macro, the place for their insertion in the body of the macro is written +as the name of a local variable with the symbol <strong>&quot;@&quot;</strong> added before it, i.e. <strong>@$arg</strong>.</p> +<p>The place for inserting the number of actual arguments passed is marked by the lexeme <strong>&quot;@$#&quot;</strong>. +If it is necessary to insert the passed arguments as a dictionary, the place for insertion is marked by the lexeme <strong>&quot;@$*&quot;</strong>.</p> +<p>If the macro takes an arbitrary number of arguments (the macro arguments are terminated by an ellipsis), +the place for their insertion in the body of the macro is marked by the lexeme <strong>&quot;@$&hellip;&quot;</strong>.</p> +<p>Analogous to the C/C++ preprocessor, to concatenate two lexemes into one, the operator <strong>&quot;@##&quot;</strong> is used in the body of the macro, +and to convert a lexeme into a text string, the operators <strong>@#</strong>, <strong>@#&quot;</strong>, or <strong>@#&rsquo;</strong> are applied, for example, +<code>@@macro($arg)@@ := @@ func_ @## @$arg( @#&quot; arg ) @;</code>, then the call <code>macro(name);</code> will be transformed into <code>func_name (&quot;name&quot;);</code></p> +<p>Examples of using macros:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Ordinary macros (the body of the macro is a correct expression)</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000">macro</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000">replace</span><span style="color:#000;font-weight:bold">();</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000">macro2</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">arg</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000;font-weight:bold">{</span> <span style="color:#000">call</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#a40000">$</span><span style="color:#000">arg</span><span style="color:#000;font-weight:bold">);</span> <span style="color:#000">call</span><span style="color:#000;font-weight:bold">()};</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># The body of the macros from a sequence of tokens</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#204a87;font-weight:bold">if</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000;font-weight:bold">[</span> <span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#a40000">$</span><span style="color:#ce5c00;font-weight:bold">...</span> <span style="color:#000;font-weight:bold">]</span><span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#ce5c00;font-weight:bold">@@</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># The expression may not be complete</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#204a87;font-weight:bold">elif</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000;font-weight:bold">,[</span> <span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#a40000">$</span><span style="color:#ce5c00;font-weight:bold">...</span> <span style="color:#000;font-weight:bold">]</span><span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#ce5c00;font-weight:bold">@@</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000;font-weight:bold">,[</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">]</span><span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#ce5c00;font-weight:bold">@@</span><span style="color:#000;font-weight:bold">;</span> </span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Запись условного оператора с использованием </span> -</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># определенных выше макросов</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">if</span><span style="color:#ce5c00;font-weight:bold">(</span> condition <span style="color:#ce5c00;font-weight:bold">){</span> -</span></span><span style="display:flex;"><span> ... -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">elif</span><span style="color:#ce5c00;font-weight:bold">(</span> condition2 <span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> ... -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#ce5c00;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> ... -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>Зачем нужна трансформация синтаксиса? -Нативная поддержка других языков нужна чтобы не переписывать легаси код на этих языках.</p> -<p>Чтобы можно было использовать существующие исходники как собственные требуется настройка работы -препроцессора и лексера под конкретный язык программирования (описание DSL). -Для <strong>С/С++</strong> потребуется выделять лексером комментарии из-за пересечения синтаксиса (которые сейчас игнорируются). -Для <strong>Python</strong> требуется выделять лексером отступы (которые сейчас тоже игнорируются), причем потребуется реализация не только синтаксиса, -но и зависимых пакетов с последующая трансляцией этого кода в С++, что в настоящий момент делать не целесообразно (cython ???).</p> -<p>Но так как возможность трансформации кода с других языков программирования принципиальная возможна, -стоит над этим думать только после полноценного релиза NewLang и его перехода в прод.</p> -<p>Для реализации DSL требуется передача команд в парсер для управления его работой (по аналогии с командой #pragma) -Но так как обработка таких команд должна происходить в лексере до передачи данных в парсер (анализатор), -то команды для макропроцессора должны быть в максимально простом виде и состоять из элементов, -которые лексер может самостоятельно идентифицировать, т.е. термины, строки и цифры (без выражений и именованных аргументов).</p> -<p>После обработки такой команды она анализируется макропроцессором и удаляется из потока лексем, т.е. в парсер (анализатор) не передается. -Но в случае ошибки с синтаксисе, данные команды нужно уметь однозначно идентифировать и самый простой способ, -комбинация признака макроса и системного имени, т.е. что-то вроде</p> -<pre tabindex="0"><code> @__PRAGMA_DIAG__(push) - @__PRAGMA_DIAG__(ignored, &#34;-Wundef&#34;) - @__PRAGMA_DIAG__(warning, &#34;-Wformat&#34;) - @__PRAGMA_DIAG__(error &#34;-Wuninitialized&#34;) - @__PRAGMA_DIAG__(pop) - - #pragma message &#34;Compiling &#34; __FILE__ &#34;...&#34; - @__PRAGMA_MESSAGE__(&#34;Compiling &#34;, __FILE__, &#34;...&#34;) - - #pragma error &#34;Error &#34; __FILE__ &#34;...&#34; - @__PRAGMA_ERROR__(&#34;Error &#34;, __FILE__, &#34;...&#34;) - - -#define DO_PRAGMA(x) _Pragma (#x) -#define TODO(x) DO_PRAGMA(message (&#34;TODO - &#34; #x)) - -@@TODO( ... )@@ := @__PRAGMA_MESSAGE__(&#34;TODO - &#34;, @*) - -@TODO(Remember to fix this) # note: TODO - Remember to fix this - -\\.__lexer__ignore_space__ = 1; -\\.__lexer__ignore_indent__ = 1; -\\.__lexer__ignore_comment__ = 1; -\\.__lexer__ignore_crlf__ = 1; -</code></pre><p>Таким образом можно трансформировать условный оператор на питоне в синтаксис NewLang следующим макросом:</p> -<pre tabindex="0"><code> -#pragma clang attribute push -#pragma clang diagnostic ignored &#34;-Wundef&#34; -#pragma clang diagnostic ignored &#34;-Wunused-variable&#34; - - -#elif __GNUC__ - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored &#34;-Wuninitialized&#34; - -#pragma GCC diagnostic ignored &#34;-Wall&#34; -#pragma GCC diagnostic ignored &#34;-Wextra&#34; - - @pragma warning(pop) - - @@ pragma warning(...) @@ := __PRAGMA_TERM_DIAG_WARNING__(); -@__PRAGMA_DIAG__(warning, pop); - -Обработка терминов в макропроцессоре в максимально простом виде. -Агрументы только термины, строки и цифры без вложенных выражений и именованных аргументов, -т.е. только элементы, которые может самостоятельно идентифицировать лексер. - -@warning(&#34;--&#34;) - @@ if ... : @@ := @@ [ @$* ]-&gt; __TERM_BLOCK_INDENT__(&#34;{&#34;, force_semicolon=1) @@ - - if __name__ == &#34;__main__&#34;: - run1() - run2() - - [ __name__ == &#34;__main__&#34; ]-&gt; { - run1(); - run2(); - }; - - -</code></pre><p>Ключ &ndash;parser-syntax-only только текстовый парсинг исходного кода без загрузки модулей, раскрытия макросов и проверки имен.</p> -<p>Ключ &ndash;parser-no-macros - без раскрытия макросов -Ключ &ndash;parser-no-module - без загрузки модулей (и мокросов, если они в них определяются) -Ключ &ndash;parser-no-check-prototype - без проверки имен при обращении</p> -<p>prototype -@<strong>PRAGMA_PROTOTYPE</strong>(define) -@<strong>PRAGMA_PROTOTYPE</strong>(implement)</p> -<p>$$</p> -<p>\$ - корень системы (система)</p> -<p>$ - текущий модуль</p> -<h1 id="макросы-для-конвертора-проверки-в-python">Макросы для конвертора проверки в Python<a class="td-heading-self-link" href="#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b4%d0%bb%d1%8f-%d0%ba%d0%be%d0%bd%d0%b2%d0%b5%d1%80%d1%82%d0%be%d1%80%d0%b0-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b8-%d0%b2-python" aria-label="Heading self-link"></a></h1> -<h1 id="if-__name__--__main__">if <strong>name</strong> == &ldquo;<strong>main</strong>&rdquo;:<a class="td-heading-self-link" href="#if-__name__--__main__" aria-label="Heading self-link"></a></h1> -<p>@@ <strong>name</strong> @@ ::= @@ $. @<strong>PRAGMA_NO_MACRO</strong>() <strong>name</strong> @@ -@@ if $&hellip; @: @@ ::= @@ [ @$&hellip; ] &ndash;&gt; @@</p> -<p>@if( $.<strong>name</strong> == &ldquo;<strong>main</strong>&rdquo; ) {</p> -<p>}</p> -<p>\каталог\модуль() - статический импорт модуля -\(&ldquo;каталог\модуль&rdquo;)() - динамический импорт модуля</p> -<p>printf := :Pointer(&lsquo;printf(format:FmtChar, &hellip;):Int32&rsquo;); -printf := %printf(format:FmtChar, &hellip;):Int32;</p> -<h1 id="регистрация-прототипа-нативной-функции">Регистрация прототипа нативной функции<a class="td-heading-self-link" href="#%d1%80%d0%b5%d0%b3%d0%b8%d1%81%d1%82%d1%80%d0%b0%d1%86%d0%b8%d1%8f-%d0%bf%d1%80%d0%be%d1%82%d0%be%d1%82%d0%b8%d0%bf%d0%b0-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h1> -<p>@prototype -%puts(format:StrChar):Int32;</p> -<h1 id="импорт-нативной-функции-с-предварительной-проверкой-её-наличия-во-время-компиляции-статическая-линковка">Импорт нативной функции с предварительной проверкой её наличия во время компиляции (статическая линковка)<a class="td-heading-self-link" href="#%d0%b8%d0%bc%d0%bf%d0%be%d1%80%d1%82-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d1%81-%d0%bf%d1%80%d0%b5%d0%b4%d0%b2%d0%b0%d1%80%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d0%be%d0%b9-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%be%d0%b9-%d0%b5%d1%91-%d0%bd%d0%b0%d0%bb%d0%b8%d1%87%d0%b8%d1%8f-%d0%b2%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d1%8f-%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%86%d0%b8%d0%b8-%d1%81%d1%82%d0%b0%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bb%d0%b8%d0%bd%d0%ba%d0%be%d0%b2%d0%ba%d0%b0" aria-label="Heading self-link"></a></h1> -<p>puts2(format:StrChar):Int32 := %puts(format:StrChar):Int32;</p> -<h1 id="импорт-нативной-функции-по-её-прототипу-во-время-выполнения-динамическая-линковка">Импорт нативной функции по её прототипу во время выполнения (динамическая линковка)<a class="td-heading-self-link" href="#%d0%b8%d0%bc%d0%bf%d0%be%d1%80%d1%82-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d0%bf%d0%be-%d0%b5%d1%91-%d0%bf%d1%80%d0%be%d1%82%d0%be%d1%82%d0%b8%d0%bf%d1%83-%d0%b2%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d1%8f-%d0%b2%d1%8b%d0%bf%d0%be%d0%bb%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b4%d0%b8%d0%bd%d0%b0%d0%bc%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bb%d0%b8%d0%bd%d0%ba%d0%be%d0%b2%d0%ba%d0%b0" aria-label="Heading self-link"></a></h1> -<p>puts3(format:StrChar):Int32 := :Pointer(&lsquo;puts(format:StrChar):Int32&rsquo;);</p> -<p>%puts(&lsquo;Тест вывода строки&rsquo;); # Линковка с нативной функцией во время компиляции и непосредственный вызов с оптимизацией передачи параметров -puts2(&lsquo;Тест 2 вывода строки&rsquo;); # Линковка с нативной функцией во время компиляции -puts3(&lsquo;Тест 3 вывода строки&rsquo;); # Линковка с нативной функцией во время выполнения при первом вызове puts3</p> -<ul> -<li>Парсинг исходного текста без раскрытия макросов и загрузки модулей</li> -<li>Парсинг исходного текста с раскрытием макросов (требуется загрузка модулей для зависимых и переопределяемых макросов)</li> -<li>Загружатся модули могут как в виде исходников (которые требуется парсить и компилировть/выполнять) -или в виде бинарников (в них должны быть список макросов, типов и имена объектов)</li> -<li>После парсинга получается список <strong>имен</strong> макросов, типов и объектов (TermPtr)</li> -<li>После выполнения модуля - список <strong>имен</strong> заполняется реальными объектами (ObjPtr).</li> -</ul> -<h1 id="компиляция-файла">Компиляция файла<a class="td-heading-self-link" href="#%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%86%d0%b8%d1%8f-%d1%84%d0%b0%d0%b9%d0%bb%d0%b0" aria-label="Heading self-link"></a></h1> -<ul> -<li>Парсинг исходника для построения AST (без анализа имен, связей, загрузки модулей и пр. только исходые тексты с раскрытием макросов</li> -<li></li> -</ul> -<h1 id="систематизация-реализации-макросов">Систематизация реализации макросов<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0%d1%82%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d1%80%d0%b5%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d0%b8-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2" aria-label="Heading self-link"></a></h1> -<p>последовательность лексем MACRO_SEQ мужду @@ @@ сохраняется в m_block, так как фрагменты блоков не могут быть идентификаторами</p> -<p>Разбор макросов происходит в лексере. Определением макроса всегда является целая строка, -которая заканчивается точкой с запятой, а идентификатором макроса всегда выступает последовательность лексем:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> @@ id @@ :<span style="color:#ce5c00;font-weight:bold">=</span> macro<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@ id @@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ @@<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@ id @@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@@ @@@<span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>Хранилищем текущих максросов является объект класса MacroBuffer. -Последовательность лексем идентификатора (id) макроса должна сохраняется в отдельном поле термина и однозначно его идентифицирует. -Первый термин в идентификаторе хранится как ключ hashmap, а дальше происходит поиск полным перебором. -Этапы работы с макросами</p> -<ul> -<li> -<p>Входные термины из лексера получаются вызовом GetNextToken, внутри которой и происходит раскрытие макросов. -Внутренний буфер заполняется до окончания строки (выражения), т.е. до символа &lsquo;;&rsquo; или <END>, после чего производится -поиск макросов в объекте MacroBuffer для текущей последовательности лексем в буфере.</p> -</li> -<li> -<p>Если макрос найден, то соответствющая ему последоваетльность заменяется на тело макроса и происходит переход -на повторный анализ входного буфера.</p> -</li> -<li> -<p>Если макрос не найден, то данные передаются в парсер для дальнейшего синтаксическго анализа.</p> -</li> -<li> -<p>Для этого во входном потоке лексем (parser.y) во время оператората создания/присвоения вызывается функция проверки на макрос. -MacroBuffer::CheckMacroAndConvertDel($$), и после этого выходному значению присваивается результат выполнения driver.MacroEval($$), -и в дальнейшем этот макрос никак не обработывается.</p> -</li> -<li> -<p>Создание макросов, проверка на дубликаты и логические ошибки в определении происходит путем обращения к методам объекта MacroBuffer.</p> -<p>/*</p> -<ul> -<li>Макросы хрянтся как фрагменты AST в виде объектов типа Term,</li> -<li>так как создаются после обработки парсером по правилам стандратной грамматики.</li> -<li></li> -<li>Но анализ входных данных на предмет раскрытия макросов проиходит из потока (последовательности) лексем,</li> -<li>т.е. <strong>ДО</strong> обработки парсером, так как при раскрытии макросов может меняться грамматика выражений.</li> -<li></li> -<li>Функция \ref CompareMacro сравнивает входной буфер (последовательность лексем)</li> -<li>на предмет возможного соответствия одному конкретному макросу.</li> -<li>Сравниваются только ключевые словам без учета аргументов в скобках,</li> -<li>но само наличие аргументов проверяется ??????????????????</li> -<li></li> -<li>Проблема:</li> -<li>К функции можно обратится с целью её вызова (указав после имени скобки),</li> -<li>так и по имени без скобок (например для получения ссылки на объект).</li> -<li>Так и к переменной можно обратиться только по имени,</li> -<li>так и указав скобки после имени как к функции (при копировании объекта).</li> -<li></li> -<li>Сделать один макрос под оба сценария (со скобками и без скобок) не получится, так как непонятно,</li> -<li>что делать с аргументами при раскрытии тела макроса, когда они не указаны.</li> -<li></li> -<li>Но может быть следует переименовывать только одно имя без учета скобок,</li> -<li>например, оставив такую возможность только для одиночных макросов.</li> -<li></li> -<li>\name -&gt; name или name (&hellip;), hash: name</li> -<li>но \name(&hellip;) -&gt; name(&hellip;), а name - ошибка !!!! hash: name</li> -<li></li> -<li>Или все же следует различать макросы со скобками и без скобок как два разных объекта???</li> -<li>\name := name2; и \name(&hellip;) := name2(&hellip;); будут разными объектами</li> -<li></li> -<li>Или добавить макросы-алиасы без аргументов только для переименования отдельных терминов?</li> -<li>\alias :- name2; но как их отличать от обычных макросов в операции удаления?</li> -<li>Или вообще не нужно отличать и оставить только один варинат (либо макрос, либо алиас)</li> -<li>Тода вопрос со скобками закрывается сам собой, алиасы всегда без скобок,</li> -<li>макросы со скбками или без скобок, но должно быть полное соответствие.</li> -<li></li> -<li>@ name name2 @ -&gt; name name2, но name name2(&hellip;) - ошибка!!! (hash: name,name2)</li> -<li>@ name name2(&hellip;) @ -&gt; name name2(&hellip;), но name name2 - ошибка !!!! (hash: name,name2)</li> -<li>@ name name2<a href="...">&hellip;</a> @ -&gt; name name2<a href="...">&hellip;</a>, но name name2 - ошибка !!!! ( hash: name,name2 )</li> -<li>@ name $tmpl<a href="...">&hellip;</a> name3@ -&gt; name $tmpl<a href="...">&hellip;</a> name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )</li> -<li></li> -<li>Но!</li> -<li>@ name name2 @ ::- -&gt; name name2 - ок, но name name2(&hellip;) - ок</li> -<li>@ name $tmpl name3@ ::- -&gt; name $tmpl<a href="...">&hellip;</a> name3 - ок, name $tmpl(&hellip;) name3[&hellip;] - ок</li> -<li></li> -<li></li> -<li></li> -<li>Для последовательности лексем требуется полное соответствие с учетом скобок ???</li> -<li>и может ли быть несколько скобок одного типа (несколько крыглях, или несколько квардратных????</li> -<li>&lt;Может быть несколько скобок одного типа, например, при указании типа у аргументов или типа возвращаемого значения.&gt;</li> -<li></li> -<li>@ name name2 @ -&gt; name name2, но name name2(&hellip;) - ошибка!!! (hash: name,name2)</li> -<li>@ name name2(&hellip;) @ -&gt; name name2(&hellip;), но name name2 - ошибка !!!! (hash: name,name2)</li> -<li>@ name name2<a href="...">&hellip;</a> @ -&gt; name name2<a href="...">&hellip;</a>, но name name2 - ошибка !!!! ( hash: name,name2 )</li> -<li>@ name $tmpl<a href="...">&hellip;</a> name3@ -&gt; name $tmpl<a href="...">&hellip;</a> name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )</li> -<li></li> -<li>Проблема скобок возникает из-за сценария замены одного термина на другой,</li> -<li>который есть в препроцессоре С/С++, но отсутствует при реализации с использованием шаблонов.</li> -<li></li> -<li></li> -</ul> -<p>*/</p> -</li> -</ul> -<p>Макросы используются и для превращеня исходного кода <em>NewLang</em> в более привычный синтаксис на основе <a href="https://newlang.net/syntax_dsl.html">ключевых слов</a>, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода.</p> -<p><a href="https://newlang.net/syntax_dsl.html">Например:</a>.</p> -<pre tabindex="0"><code> @@if(...)@@ ::= @@ [ \$* ]--&gt; @@; - @@while(...)@@ ::= @@ [\$*] &lt;-&gt; @@; - @@return $arg@@::= @@ -- \$arg -- @@; - @@true@@ ::= 1; -</code></pre><p>Тогда цикл до 5:</p> -<pre tabindex="0"><code>count:=1; -[ 1 ] &lt;-&gt; { - [count&gt;5] --&gt; { - -- 42 --; - }; - count+=1; -}; -</code></pre><p>будет выглядеть более привычно</p> -<pre tabindex="0"><code>count:=1; -while( true ) { - if(count&gt;5) { - return 42; - }; - count+=1; -}; -</code></pre><h2 id="идеи-на-будущее">Идеи на будущее<a class="td-heading-self-link" href="#%d0%b8%d0%b4%d0%b5%d0%b8-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5" aria-label="Heading self-link"></a></h2> -<h3 id="символьное-программирование">Символьное программирование<a class="td-heading-self-link" href="#%d1%81%d0%b8%d0%bc%d0%b2%d0%be%d0%bb%d1%8c%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> -<blockquote> -<p>Символьное программирование, часто называемое декларативным программированием, представляет собой парадигму программирования, которая использует математическую логику, отношения и символы для представления знаний и помощи в решении проблем. Вместо того, чтобы сосредотачиваться на описании последовательности операций, необходимых для выполнения вычислений, как в императивном программировании, символическое программирование делает упор на выражении отношений и ограничений между структурами данных, уделяя особое внимание «что», а не «как».</p> -<p>В контексте парадигм программирования символическое программирование часто противопоставляется процедурному или императивному программированию, где программы определяют пошаговые процедуры для достижения своих целей. В то время как императивное программирование фокусируется на описании потока управления с использованием таких конструкций, как циклы и условные выражения, для управления выполнением, символическое программирование сосредоточено на выражении фактов о проблеме и позволяет выполнению естественным образом выводить последующие последствия из предоставленной информации.</p> -<p>Одним из основных преимуществ символьного программирования является его способность обеспечивать более высокий уровень абстракции, что упрощает анализ кода и снижает вероятность ошибок. Непосредственно выражая отношения и ограничения, символическое программирование позволяет разработчикам сосредоточиться на моделировании и спецификации проблем, позволяя базовой системе управлять реализацией и выполнением алгоритмов.</p> -<p>Существует несколько языков программирования и сред, использующих парадигму символьного программирования, например Prolog, Lisp и Haskell. Например, Пролог — это язык логического программирования, который позволяет разработчикам выражать взаимосвязи и факты о проблемных областях, в то время как выполнение автоматически обосновывает и извлекает новые факты на основе исходной информации. В том же духе Лисп, функциональный язык программирования, использует символьные вычисления для манипулирования структурами данных и выполнения сложных операций над ними, используя краткий и математически обоснованный синтаксис. Haskell, еще один функциональный язык программирования, использует строгую типизацию и ленивые вычисления, чтобы обеспечить символическое рассуждение и облегчить эффективное создание программ.</p> -<p>Символьное программирование может быть полезным в широком спектре проблемных областей, включая искусственный интеллект, экспертные системы, программирование логики ограничений и символьную математику, среди других. Более высокий уровень абстракции, обеспечиваемый декларативными языками программирования, облегчает разработку сложных систем, сводя к минимуму вероятность ошибки и улучшая удобство обслуживания. В частности, использование символьного программирования в искусственном интеллекте позволяет разработчикам создавать системы представления знаний и механизмы рассуждения, которые можно применять для обработки естественного языка, машинного обучения и автоматического доказательства теорем.</p> -</blockquote> -<p>Различие между символьным программированием и препроцессором</p> -<ul> -<li>Задача препроцессора - раскрыть(расширить) макрос, тогда как при символьном программировании нужно сокращать (сворачивать) выражения</li> -<li>Препроцессор обрабатывает последовательности лексем (плоские данные), тогда как символьное программирование оперирует выражениями (деревом лексем)</li> -<li>Макрос у препроцессора идентифицируется первым термином, и если макрос не может быть раскрыт, то возникает ошибка. В символьном программировани требуется точное соответствие всего выражения и только в этом случае производится сокращение выражения.</li> -</ul> -<p>Предпосылки для реализации символьного программирования -Компилятор - интерепретатор с REPL и обработка AST как во время компиляции, так и во время выполнения. -Необходимо добавить конструкции для определения правил символьного программрования (чистые функции?) -Необходимо добавить конструкцию для вычисления выражений в символьном программировании.</p> -<p>Wolfram -<a href="https://habr.com/articles/772984/">https://habr.com/articles/772984/</a></p> -<pre tabindex="0"><code>diffRules = { - Sin[x] -&gt; Cos[x], - Cos[x] -&gt; -Sin[x], - x^2 -&gt; 2*x, - x -&gt; 1, - Log[x] -&gt; 1/x -}; -</code></pre><pre tabindex="0"><code>diffRules := ( - Sin(x) @-&gt; Cos(x), - Cos(x) @-&gt; -Sin(x), - x^2 @-&gt; 2*x, - x @-&gt; 1, - Log(x) @-&gt; 1\x, -); - -expr @-&gt; Sin(x) - x^2 + Log(x); - -# И применим к нему правила дифференцирования - -#expr /. diffRules -#(* 1/x - 2 x + Cos[x] *) - -sym := SymEval(expr, diffRules); -res := Eval(sym, x=0.123); -</code></pre><pre tabindex="0"><code>expr = a^2 + 3 * b^3 - c^4 + 2 * x^2 - x + 4*c + 3 - -И я хочу это выражение линеаризовать, т.е. отбросить все степени выше первой. Я могу сделать это напрямую, как в примерах выше: - -expr /. { - a^2 -&gt; 0, - b^3 -&gt; 0, - c^4 -&gt; 0, - x^2 -&gt; 0 -} -(* 3 + 4 c - x *) - -Но это слишком неудобно. Что если я не знаю ни точную степень, ни имя переменной? Как просто указать, что нужно заменить все места, где встречается возведение в степень на ноль? Это можно сделать при помощи шаблонов вот так: - -expr /. Power[_, _] -&gt; 0 -(* 3 + 4 c - x *) - -Либо вот так: - -expr /. _ ^ _ -&gt; 0 -(* 3 + 4 c - x *) -</code></pre><pre tabindex="0"><code>:diffRules() := { - {@ Sin(x) @} ::- {@ Cos(x) @}; - Cos(x) @-&gt; -Sin(x), - x^2 @-&gt; 2*x, - x @-&gt; 1, - Log(x) @-&gt; 1\x, -}; - -expr @-&gt; Sin(x) - x^2 + Log(x); - -# И применим к нему правила дифференцирования - -#expr /. diffRules -#(* 1/x - 2 x + Cos[x] *) - -sym := SymEval(expr, diffRules); -res := Eval(sym, x=0.123); -</code></pre> +</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Writing a conditional statement using</span> +</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># the macros defined above</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@if</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">condition</span> <span style="color:#000;font-weight:bold">){</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">...</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> <span style="color:#5c35cc;font-weight:bold">@elif</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">condition2</span> <span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">...</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> <span style="color:#5c35cc;font-weight:bold">@else</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">...</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span></code></pre></div><p>For example, a loop up to 5:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">[</span> <span style="color:#0000cf;font-weight:bold">1</span> <span style="color:#000;font-weight:bold">]</span> <span style="color:#ce5c00;font-weight:bold">&lt;-&gt;</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">[</span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#0000cf;font-weight:bold">5</span> <span style="color:#000;font-weight:bold">]</span> <span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">--</span> <span style="color:#0000cf;font-weight:bold">42</span> <span style="color:#ce5c00;font-weight:bold">--</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span><span style="display:flex;"><span> <span style="color:#000">count</span><span style="color:#ce5c00;font-weight:bold">+=</span><span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span></code></pre></div><p>This will look more familiar:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@while</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">true</span> <span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@if</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#0000cf;font-weight:bold">5</span> <span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@return</span> <span style="color:#0000cf;font-weight:bold">42</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span><span style="display:flex;"><span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">+=</span> <span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span></code></pre></div> </div> @@ -2144,235 +1790,145 @@ <h2 id="предопределенные-макросы">Предопредел <h1 id="pg-8e386bb5b373d09fe8bcbec82c31b73f">1.9 - Keyword syntax (DSL)</h1> - <h2 id="dsl">DSL<a class="td-heading-self-link" href="#dsl" aria-label="Heading self-link"></a></h2> -<h3 id="features-of-associative-memory">Features of associative memory<a class="td-heading-self-link" href="#features-of-associative-memory" aria-label="Heading self-link"></a></h3> + <h3 id="features-of-associative-memory">Features of associative memory<a class="td-heading-self-link" href="#features-of-associative-memory" aria-label="Heading self-link"></a></h3> <p>The syntax of the <em>NewLang</em> language is based on strict rules without the use of keywords, and no matter how logical it may seem, association by keywords is much easier to remember, for example, <strong>if</strong>, than the combination <em>minus minus right angle bracket</em> <strong>&ndash;&gt;</strong>. Because of this, it makes sense to use not a &ldquo;pure&rdquo; basic syntax, but a more familiar dialect with the use of keywords.</p> -<h3 id="syntax-based-on-keywords">Syntax based on keywords<a class="td-heading-self-link" href="#syntax-based-on-keywords" aria-label="Heading self-link"></a></h3> -<p>In the dsl.nlp file, there is a set of macros that expand the basic syntax of <em>NewLang</em>, based on rules, -with a set of predefined keywords as in classical programming languages. -And if necessary, they can be adapted or supplemented for your own domain.</p> -<h2 id="константы">Константы<a class="td-heading-self-link" href="#%d0%ba%d0%be%d0%bd%d1%81%d1%82%d0%b0%d0%bd%d1%82%d1%8b" aria-label="Heading self-link"></a></h2> -<h3 id="логические">Логические<a class="td-heading-self-link" href="#%d0%bb%d0%be%d0%b3%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> +<p><em>NewLang</em> already contains a set of macros that extend the basic rule-based syntax of <em>NewLang</em>, +a set of predefined keywords as in classical programming languages, +which can be adapted or supplemented to suit your own subject area.</p> +<h3 id="constants">Constants<a class="td-heading-self-link" href="#constants" aria-label="Heading self-link"></a></h3> <ul> -<li><strong>true</strong> - 1</li> -<li><strong>yes</strong> - 1</li> -<li><strong>false</strong> - 0</li> -<li><strong>no</strong> - 0</li> +<li> +<p><em>@true</em> - 1</p> +</li> +<li> +<p><em>@yes</em> - 1</p> +</li> +<li> +<p><em>@false</em> - 0</p> +</li> +<li> +<p><em>@no</em> - 0</p> +</li> +<li> +<p><em>@this</em> или <em>@self</em> - Current object</p> +</li> +<li> +<p><em>@super</em> - Parent object</p> +</li> +<li> +<p><em>@latter</em> or <em>@last</em>- Result of the last operation</p> +</li> </ul> -<h3 id="системные-имена">Системные имена<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%8b%d0%b5-%d0%b8%d0%bc%d0%b5%d0%bd%d0%b0" aria-label="Heading self-link"></a></h3> +<h3 id="logical-operators">Logical operators<a class="td-heading-self-link" href="#logical-operators" aria-label="Heading self-link"></a></h3> <ul> -<li><strong>this</strong> - Текущий объект (<strong>$0</strong>)</li> -<li><strong>parent</strong> - Родительский объект (<strong>$$</strong>)</li> -<li><strong>last</strong> - Результат выполнения последнего оператора (<strong>$^</strong>)</li> +<li><em>@and</em> - Logical <strong>AND</strong></li> +<li><em>@or</em> - Logical <strong>OR</strong></li> +<li><em>@xor</em> - Logical <strong>Exclusive OR</strong></li> +<li><em>@not(value)</em> - Logical negation</li> </ul> -<p>!!!!!!!!- <strong>args</strong> - Все аргументы функции (<strong>$*</strong>)</p> -<p>!!!!!!!!- <strong>sys</strong> - Системный контекст запущенной программы (<strong>@@</strong>) -!!!!!!!!- <strong>current</strong> - Текущий модуль (<strong>@$</strong>) -!!!!!!!!- <strong>cmd</strong> - Все аргументы выполняющегося приложения из командной строки (<strong>@*</strong>)</p> -<p>!!!!!!!!!!1### Типовые функции и проверки -!!!!!!!!!!- <strong>run(&lsquo;filename&rsquo;)</strong> - Выполнить указанный файл (<strong>@@(&lsquo;filename&rsquo;)</strong>) -!!!!!!!!!!- <strong>ifmain</strong> - Проверка, если текущий модуль основной (<strong>[@$.$0] &ndash;&gt;</strong> { &hellip; }) -!!!!!!!!!!- <strong>ifload</strong> - Проверка, если текущий модуль загружается впервые (<strong>[@$.<strong>load</strong>] &ndash;&gt;</strong> { &hellip; })</p> -<h3 id="операторы">Операторы<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b" aria-label="Heading self-link"></a></h3> +<h3 id="operators">Operators<a class="td-heading-self-link" href="#operators" aria-label="Heading self-link"></a></h3> <ul> <li> -<p><strong>match(cond)</strong> - Оператор <a href="https://newlang.net/ops.html#%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B0-%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F">оценки выражения</a></p> +<p><em>@if(&hellip;)</em> - First conditional statement</p> </li> <li> -<p><strong>if(&hellip;)</strong> - Первый условный оператор (<strong>[$*]&ndash;&gt;</strong> { &hellip; })</p> +<p><em>@elif(&hellip;)</em> - Second and all subsequent conditional statements</p> </li> <li> -<p><strong>elif(&hellip;)</strong> - Второй и все последующие (<strong>,[$*]&ndash;&gt;</strong> { &hellip; })</p> +<p><em>@else</em> - Operator <em>otherwise</em></p> </li> <li> -<p><strong>else</strong> - Оператор <em>иначе</em> (<strong>,[_]&ndash;&gt;</strong> { &hellip; })</p> +<p><em>@while(&hellip;)</em> - Loop operator with precondition</p> </li> <li> -<p><strong>while(cond)</strong> - Оператор цикла с предусловием (<strong>[@$cond] &lt;-&gt;</strong> { &hellip; } )</p> +<p><em>@dowhile(&hellip;)</em> - Loop operator with postcondition</p> </li> <li> -<p><strong>dowhile(cond)</strong> - Оператор цикла с постусловием ({ &hellip; } <strong>&lt;-&gt;[@$cond]</strong>)</p> +<p><em>@loop</em> - Infinite loop operator</p> </li> <li> -<p><strong>iter(obj, &hellip; )</strong> - Создание итератора ( <strong>@$obj</strong> ? (@$*) )</p> +<p><em>@break $label</em> - Operator to break out of a named named block of code</p> </li> <li> -<p><strong>next(obj, &hellip; )</strong> - Следующий элемент итератора ( <strong>@$obj</strong> ! ($*) )</p> +<p><em>@continue $label</em> - Jump operator to the beginning of a named block of code</p> </li> <li> -<p><strong>curr(obj, &hellip; )</strong> - Текущий элемент итератора ( <strong>@$obj</strong> !? ($*) )</p> +<p><em>@return( result )</em> - Operator for returning a value and exiting a function</p> </li> <li> -<p><strong>first(obj)</strong> - Перейти на первый элемент итератора ( <strong>@$obj</strong> !! )</p> +<p><em>@throw( error )</em> - Operator for creating an exception and returning an error</p> </li> <li> -<p><strong>all(obj)</strong> - Получить сразу все элементы итератора ( <strong>@$obj</strong> ??)</p> +<p><em>@match( &hellip; )</em> - Expression evaluation operator</p> </li> -</ul> -<h3 id="прерывания">Прерывания<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b5%d1%80%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h3> -<ul> <li> -<p><strong>return</strong> - Положительное прерывание (<strong>++</strong>)</p> +<p><em>@case( &hellip; )</em> - Pattern comparison operator</p> </li> <li> -<p><strong>return(&hellip;)</strong>- Положительное прерывание с возвратом значения (<strong>++</strong> @$value <strong>++</strong>)</p> +<p><em>@default</em> - Selection operator</p> </li> <li> -<p><strong>error</strong> - Отрицательное прерывание (<strong>--</strong>)</p> +<p><em>@iter(obj, &hellip; )</em> - Creating an iterator</p> </li> <li> -<p><strong>error(&hellip;)</strong> - Отрицательное прерывание с возвратом значения (<strong>--</strong> @$value <strong>--</strong>)</p> +<p><em>@next(obj, &hellip; )</em> - Get the next element of the iterator</p> </li> <li> -<p><strong>break+</strong> и <strong>break-</strong> - Выход из цикла:</p> +<p><em>@curr(obj, &hellip; )</em> - Get the current iterator element</p> +</li> +<li> +<p><em>@first(obj)</em> - Go to the first element of the iterator</p> +</li> +<li> +<p><em>@all(obj)</em> - Get all elements of the iterator at once</p> </li> </ul> -<pre tabindex="0"><code> while(...) {+ - ++ :Break ++ - +} - while(...) {- - -- :Break -- - -} -</code></pre><ul> -<li><strong>continue+</strong> и <strong>continue-</strong> - В начало цикла:</li> -</ul> -<pre tabindex="0"><code> while(...) {+ - ++ :Continue ++ - +} - while(...) {- - -- :Continue -- - -} -</code></pre><p>obj { -.field = 1; -.prop(); -};</p> -<p>#Python</p> -<h1 id="1-without-using-with-statement">1) without using with statement<a class="td-heading-self-link" href="#1-without-using-with-statement" aria-label="Heading self-link"></a></h1> -<p>file = open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) -file.write(&lsquo;hello world !&rsquo;) -file.close()</p> -<h1 id="2-without-using-with-statement">2) without using with statement<a class="td-heading-self-link" href="#2-without-using-with-statement" aria-label="Heading self-link"></a></h1> -<p>file = open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) -try: -file.write(&lsquo;hello world&rsquo;) -finally: -file.close()</p> -<p>open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) { -.write(&lsquo;hello world !&rsquo;); -.close(); -}</p> -<p>Python3</p> -<h1 id="using-with-statement">using with statement<a class="td-heading-self-link" href="#using-with-statement" aria-label="Heading self-link"></a></h1> -<p>with open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) as file: -file.write(&lsquo;hello world !&rsquo;)</p> -<h1 id="a-simple-file-writer-object">a simple file writer object<a class="td-heading-self-link" href="#a-simple-file-writer-object" aria-label="Heading self-link"></a></h1> -<p>class MessageWriter(object): -def <strong>init</strong>(self, file_name): -self.file_name = file_name</p> -<pre><code>def __enter__(self): - self.file = open(self.file_name, 'w') - return self.file - -def __exit__(self, *args): - self.file.close() -</code></pre> -<h1 id="using-with-statement-with-messagewriter">using with statement with MessageWriter<a class="td-heading-self-link" href="#using-with-statement-with-messagewriter" aria-label="Heading self-link"></a></h1> -<p>with MessageWriter(&lsquo;my_file.txt&rsquo;) as xfile: -xfile.write(&lsquo;hello world&rsquo;)</p> -<h1 id="a-simple-file-writer-object-1">a simple file writer object<a class="td-heading-self-link" href="#a-simple-file-writer-object-1" aria-label="Heading self-link"></a></h1> -<p>:MessageWriter { -def <strong>init</strong>(self, file_name): -self.file_name = file_name</p> -<pre><code>def __enter__(self): - self.file = open(self.file_name, 'w') - return self.file - -def __exit__(self, *args): - self.file.close() -</code></pre> -<p>}</p> -<h1 id="using-with-statement-with-messagewriter-1">using with statement with MessageWriter<a class="td-heading-self-link" href="#using-with-statement-with-messagewriter-1" aria-label="Heading self-link"></a></h1> -<p>MessageWriter(&lsquo;my_file.txt&rsquo;) { -.write(&lsquo;hello world&rsquo;); -};</p> -<p>from contextlib import contextmanager</p> -<p>class MessageWriter(object): -def <strong>init</strong>(self, filename): -self.file_name = filename</p> -<pre><code>@contextmanager -def open_file(self): - try: - file = open(self.file_name, 'w') - yield file - finally: - file.close() -</code></pre> -<h1 id="usage">usage<a class="td-heading-self-link" href="#usage" aria-label="Heading self-link"></a></h1> -<p>message_writer = MessageWriter(&lsquo;hello.txt&rsquo;) -with message_writer.open_file() as my_file: -my_file.write(&lsquo;hello world&rsquo;)</p> -<p>:MessageWriter(object) { -def <strong>init</strong>(self, filename): -self.file_name = filename</p> -<pre><code>@contextmanager -def open_file(self): - try: - file = open(self.file_name, 'w') - yield file - finally: - file.close() -</code></pre> -<p>}</p> -<h1 id="usage-1">usage<a class="td-heading-self-link" href="#usage-1" aria-label="Heading self-link"></a></h1> -<p>message_writer = MessageWriter(&lsquo;hello.txt&rsquo;) -with message_writer.open_file() as my_file: -my_file.write(&lsquo;hello world&rsquo;)</p> -<h1 id="приложения">Приложения<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b8%d0%bb%d0%be%d0%b6%d0%b5%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h1> -<h2 id="предопределенные-макросы">Предопределенные макросы<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b5%d0%b4%d0%be%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%bd%d1%8b%d0%b5-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b" aria-label="Heading self-link"></a></h2> -<p>При работе парсера <em>NewLang</em> автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. -Данные предопределенные макросы можно использовать как обычные константы.</p> +<h2 id="predefined-macros">Predefined macros<a class="td-heading-self-link" href="#predefined-macros" aria-label="Heading self-link"></a></h2> +<p>When the <em>NewLang</em> parser is running, several reserved macros are automatically generated, +some of which correspond to preprocessor macros in C/C++. +These predefined macros can be used as regular constants.</p> <ul> <li> -<p>__FILE__ или __FILE_NAME__ - имя и полный путь текущего файла</p> +<p>__FILE__ or __FILE_NAME__ - name and full path of the current file</p> </li> <li> -<p>__LINE__ или __FILE_LINE__ - содержит номер текущей строки в файле</p> +<p>__LINE__ or __FILE_LINE__ - contains the number of the current line in the file</p> </li> <li> -<p>__FILE_TIMESTAMP__ - дату и время последней модификации текущего файла в строковом представлении</p> +<p>__FILE_TIMESTAMP__ - date and time of the last modification of the current file in string representation</p> </li> <li> -<p>__FILE_MD5__ - md5 хеш текущего файла в строковом виде</p> +<p>__FILE_MD5__ - md5 hash of the current file in string form</p> </li> <li> -<p>__COUNTER__ - целочисленный счетчик, который увеличивает свое значение при каждом обращении</p> +<p>__COUNTER__ - an integer counter that increases its value with each access</p> </li> <li> -<p>__DATE__ - дата начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)</p> +<p>__DATE__ - start date of the compiler launch (has the same value for all processed files)</p> </li> <li> -<p>__TIME__ - время начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)</p> +<p>__TIME__ - start time of the compiler launch (has the same value for all processed files)</p> </li> <li> -<p>__TIMESTAMP__ - дату и время начала запуска компилятора (например: &ldquo;Fri 19 Aug 13:32:58 2016&rdquo;)</p> +<p>__TIMESTAMP__ - date and time when the compiler started running (for example: &ldquo;Fri 19 Aug 13:32:58 2016&rdquo;)</p> </li> <li> -<p>__TIMESTAMP_ISO__ - дату и время начала запуска компилятора в формате ISO (например: &ldquo;2013-07-06T00:50:06Z&rdquo;)</p> +<p>__TIMESTAMP_ISO__ - date and time when the compiler started running in ISO format (for example: &ldquo;2013-07-06T00:50:06Z&rdquo;)</p> </li> <li> -<p>__NLC_VER__ - Страшая и младшая версия компилятора NewLang (8 битное число, по 4 бита на цифру)</p> +<p>__NLC_VER__ - Older and younger version of the NewLang compiler (8-bit number, 4 bits per digit)</p> </li> <li> -<p>__NLC_DATE_BUILD__ - текстовая строка с датой сборки компилятора NewLang (например, &ldquo;23.06.04 20:51:39&rdquo;)</p> +<p>__NLC_DATE_BUILD__ - text string with the build date of the NewLang compiler (for example, &ldquo;06/23/04 20:51:39&rdquo;)</p> </li> <li> -<p>__NLC_SOURCE_GIT__ - текстовая строка с идентификатором исходных файлов NewLang git репозитория, использованных при сборке компилятора (например, &ldquo;v0.3.0-fef8c371&rdquo;)</p> +<p>__NLC_SOURCE_GIT__ - text string with the identifier of the NewLang git repository source files used to build the compiler (for example, &ldquo;v0.3.0-fef8c371&rdquo;)</p> </li> <li> -<p>__NLC_SOURCE_BUILD__ - дата сборки и git идентификатор исходных файлов NewLang одной текстовой строкой (например, &ldquo;v0.3.0-fef8c371 23.06.04 20:51:39&rdquo;)</p> +<p>__NLC_SOURCE_BUILD__ - build date and git identifier of NewLang source files in one text line (for example, &ldquo;v0.3.0-fef8c371 06/23/04 20:51:39&rdquo;)</p> </li> </ul> @@ -3132,22 +2688,35 @@ <h3 id="еще-пример-возможностей-для-расширения <div class="td-content" style="page-break-before: always"> - <h1 id="pg-cf08b42ee4f3746e6fd20919aa6660c8">2.9 - Нативные типы</h1> - - <h2 id="нативные-типы-данных">Нативные типы данных<a class="td-heading-self-link" href="#%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85" aria-label="Heading self-link"></a></h2> -<p>Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &ldquo;<strong>%</strong>&rdquo;. -В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат.</p> -<h3 id="pointer--указатель-на-системную-область-памяти-или-нативную-функцию">:Pointer — указатель на системную область памяти или нативную функцию<a class="td-heading-self-link" href="#pointer--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%83%d1%8e-%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8-%d0%b8%d0%bb%d0%b8-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%83%d1%8e-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8e" aria-label="Heading self-link"></a></h3> -<p>Так как любой программе приходится взаимодействовать с внешним миром, т -о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, -и для этих целей служит тип <em>:Pointer</em>. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. -Но можно вывести его значение, например для отладки.</p> -<h3 id="plain--указатель-на-представление-данных-в-бинарном-виде">:Plain — указатель на представление данных в бинарном виде<a class="td-heading-self-link" href="#plain--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d0%bf%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%be%d0%bc-%d0%b2%d0%b8%d0%b4%d0%b5" aria-label="Heading self-link"></a></h3> -<p>Для взаимодействия с внешними библиотеками требуется еще и обмен данными. -И для этих целей служит тип данных <em>:Plain</em> — который также является указателем, но на двоичное представление данных в области памяти. -Конечно, если их можно представить в виде одного фрагмента.</p> -<h3 id="перечисление-структура-и-объединение">Перечисление, структура и объединение<a class="td-heading-self-link" href="#%d0%bf%d0%b5%d1%80%d0%b5%d1%87%d0%b8%d1%81%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d0%b8-%d0%be%d0%b1%d1%8a%d0%b5%d0%b4%d0%b8%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> -<p><em>:Enum</em>, <em>:Struct</em> и <em>:Union</em> — это такие же <a href="http://localhost:1313/docs/types/dicts/#%D0%BF%D0%B5%D1%80%D0%B5%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D0%B0-%D0%B8-%D0%BE%D0%B1%D1%8A%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5">словари</a>, только на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера. Эти типы данных так же относятся к группе <em>:Plain</em> и могут быть представлены в двоичном виде в одной области машинной памяти.</p> + <h1 id="pg-cf08b42ee4f3746e6fd20919aa6660c8">2.9 - Native Data Types</h1> + + <p>Native (machine) data can be variables or functions, and the names of native objects start with the percent symbol &ldquo;<strong>%</strong>&rdquo;.</p> +<p>In the case of variables, these are binary data located in a single continuous area of machine memory at a specific address and have a strictly defined format.</p> +<p>To use existing libraries, you need to import the native object, thereby creating an object NewLang, +but with an implementation in another language, for example, in C/C++.</p> +<p>The syntax for importing native objects is the same as for <a href="/docs/ops/create/">creating</a> regular language objects, +only the name of the native object needs to be specified as the right operand in the creation operator.</p> +<p>When importing a native object, it is necessary to always specify the variable types, +as well as the types of arguments and return values for functions.</p> +<p>If the data types of the created object and the native object match (i.e., no type conversion is required), +then the native object name can be specified with an ellipsis, +which means that the data types will replicate those specified at the left operand.</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#000">Plain</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#000">fopen</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">filename</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">StrChar</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">modes</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">StrChar</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">FILE</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fopen</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">fclose</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">f</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fclose</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">fflush</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">f</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fflush</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">fprintf</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">f</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#204a87">format</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FmtChar</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fprintf</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#000">fremove</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">filename</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">String</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">remove</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">frename</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">old</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">String</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">new</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">String</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">rename</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span></code></pre></div> + +<div class="pageinfo pageinfo-primary"> +<p>The following description is under development.</p> + +</div> + </div> diff --git a/docs/docs/arch/errors/index.html b/docs/docs/arch/errors/index.html index 1b3860f7..c38b7e40 100644 --- a/docs/docs/arch/errors/index.html +++ b/docs/docs/arch/errors/index.html @@ -148,7 +148,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -179,7 +179,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/arch/index.html b/docs/docs/arch/index.html index a05e99b5..5cb559ee 100644 --- a/docs/docs/arch/index.html +++ b/docs/docs/arch/index.html @@ -141,7 +141,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -172,7 +172,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/arch/mangling/index.html b/docs/docs/arch/mangling/index.html index 4f588d09..7c03c6a6 100644 --- a/docs/docs/arch/mangling/index.html +++ b/docs/docs/arch/mangling/index.html @@ -148,7 +148,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -179,7 +179,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/index.html b/docs/docs/index.html index 6907dc98..86f6cec7 100644 --- a/docs/docs/index.html +++ b/docs/docs/index.html @@ -137,7 +137,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -168,7 +168,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> @@ -219,18 +219,7 @@ </div> - <div class="td-toc"> - <nav id="TableOfContents"> - <ul> - <li> - <ul> - <li><a href="#начиная-с-c-should-adopt-the-same-characters-for-c26">Начиная с C++ should adopt the same characters for C++26.</a></li> - </ul> - </li> - </ul> -</nav> - </div> - + <div class="taxonomy taxonomy-terms-cloud taxo-tags"> <h5 class="taxonomy-title">Tag Cloud</h5> <ul class="taxonomy-terms"> @@ -262,44 +251,15 @@ <h1>Documentation</h1> <header class="article-meta"> </header> - <p>Основные материалы по языку программирования NewLang.</p> -<p>Описание акутально для текущей версии 4.0</p> -<p>clang-17 не поддерживает:</p> -<table> -<thead> -<tr> -<th>Feature</th> -<th>Proposal</th> -<th>Available</th> -</tr> -</thead> -<tbody> -<tr> -<td>Coroutines</td> -<td>P0912R5</td> -<td><em>Partial</em> Fully supported on all targets except Windows, which still has some stability and ABI issues.</td> -</tr> -<tr> -<td>Extended floating-point types and standard names</td> -<td>P1467R9</td> -<td>No</td> -</tr> -<tr> -<td>Concepts</td> -<td>P0848R3</td> -<td>Clang 16 (Partial)</td> -</tr> -<tr> -<td>Modules</td> -<td></td> -<td>No</td> -</tr> -</tbody> -</table> -<h3 id="начиная-с-c-should-adopt-the-same-characters-for-c26">Начиная с C++ should adopt the same characters for C++26.<a class="td-heading-self-link" href="#%d0%bd%d0%b0%d1%87%d0%b8%d0%bd%d0%b0%d1%8f-%d1%81-c-should-adopt-the-same-characters-for-c26" aria-label="Heading self-link"></a></h3> -<ul> -<li>Add <strong>@</strong>, <strong>$</strong>, and ` to the basic character set P2558R2 Yes</li> -</ul> + + +<div class="pageinfo pageinfo-primary"> +<p>The materials are in the process of being translated into English!</p> + +</div> + +<p>Basic materials on the NewLang programming language.</p> +<p>The description is valid for the current <a href="https://github.com/rsashka/newlang/releases/tag/v0.4.0">version 0.4</a></p> <div class="section-index"> diff --git a/docs/docs/index.xml b/docs/docs/index.xml index c1a54899..be4b4938 100644 --- a/docs/docs/index.xml +++ b/docs/docs/index.xml @@ -1584,6 +1584,110 @@ Sum1(arg1, arg2) :- {$arg1+$arg2;}; # Создать или переопреде </description> </item> + <item> + <title>Docs: Macros</title> + <link>http://localhost:1313/docs/syntax/macros/</link> + <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate> + + <guid>http://localhost:1313/docs/syntax/macros/</guid> + <description> + + + &lt;p&gt;Macros are also used to transform the original code of &lt;em&gt;NewLang&lt;/em&gt; into a more familiar syntax based on &lt;a href=&#34;http://localhost:1313/docs/syntax/dsl/&#34;&gt;keywords&lt;/a&gt;, +as such text is much easier to understand when reading the original code later.&lt;/p&gt; +&lt;p&gt;In &lt;strong&gt;NewLang&lt;/strong&gt;, macros are one or more consecutive terms that are replaced with another term or a whole syntactic construction (a sequence of lexemes).&lt;/p&gt; +&lt;p&gt;Macros are processed during the operation of the &lt;strong&gt;lexer&lt;/strong&gt;, i.e., before passing the sequence of lexemes to the parser, +allowing fragments of the language syntax to be modified using macros, for example, when implementing custom DSL dialects.&lt;/p&gt; +&lt;h3 id=&#34;defining-macros&#34;&gt;Defining Macros&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#defining-macros&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; +&lt;p&gt;The definition of macros is similar to the &lt;a href=&#34;http://localhost:1313/docs/ops/create/&#34;&gt;definition&lt;/a&gt; of other objects and consists of three parts +&lt;strong&gt;&lt;macro name&gt; &amp;lt;creation/assignment operator&amp;gt; &lt;macro body&gt;&lt;/strong&gt; and ends with a semicolon &amp;ldquo;&lt;strong&gt;;&lt;/strong&gt;&amp;rdquo;, i.e., +normal operators &lt;strong&gt;::=&lt;/strong&gt;(&lt;strong&gt;::-&lt;/strong&gt;), &lt;strong&gt;=&lt;/strong&gt;, or &lt;strong&gt;:=&lt;/strong&gt;(&lt;strong&gt;:-&lt;/strong&gt;) are used to create a new or redefine an existing object, +and the macro name is indicated between two symbols &lt;strong&gt;&amp;quot;@@&amp;quot;&lt;/strong&gt; and can contain one or more lexemes (terms).&lt;/p&gt; +&lt;p&gt;All macros belong to the global namespace, so the first term in the macro name must be unique, +otherwise it will override local and global variables during &lt;a href=&#34;http://localhost:1313/docs/syntax/naming/#name-lookup&#34;&gt;name lookup&lt;/a&gt; +if they are written in the program text without &lt;a href=&#34;http://localhost:1313/docs/syntax/naming/#sigil&#34;&gt;qualifiers (sigils)&lt;/a&gt;.&lt;/p&gt; +&lt;p&gt;Using the operators &lt;strong&gt;::-&lt;/strong&gt; and &lt;strong&gt;:-&lt;/strong&gt; creates pure (hygienic) macros, arguments and variables in which are guaranteed not to intersect with the program&amp;rsquo;s namespace.&lt;/p&gt; +&lt;p&gt;The body of a macro can be a valid language expression, a sequence of lexemes (enclosed in double at symbols &lt;strong&gt;&amp;quot;@@&amp;quot;&lt;/strong&gt;, +i.e. &lt;strong&gt;&lt;code&gt;@@ lexeme1 lexeme2 @@&lt;/code&gt;&lt;/strong&gt;), or a regular text string (which should be specified between triple at symbols &lt;strong&gt;&amp;quot;@@@&amp;quot;&lt;/strong&gt;, +i.e. &lt;strong&gt;&lt;code&gt;@@@ text string @@@&lt;/code&gt;&lt;/strong&gt;).&lt;/p&gt; +&lt;p&gt;In the macro name after the first term, one or more templates may be present. +A &lt;em&gt;template&lt;/em&gt; is a term that, when matching a sequence of lexemes with the macro identifier, +can be replaced by any other single term (effectively, this is pattern/template matching).&lt;/p&gt; +&lt;p&gt;To create a template term, a dollar sign should be placed at the beginning of its identifier (which corresponds to a qualifier of a local variable), +i.e. the macro name &lt;code&gt;@@ FUNC $name @@&lt;/code&gt; will correspond to the sequence of lexemes as &lt;code&gt;FUNC my_func_name&lt;/code&gt; as well as &lt;code&gt;FUNC other_name_func&lt;/code&gt;.&lt;/p&gt; +&lt;p&gt;To remove a macro, a special syntax is used: &lt;code&gt;@@@@ name @@@@;&lt;/code&gt; or &lt;code&gt;@@@@ two terms @@@@;&lt;/code&gt;, +i.e. you need to specify the macro identifier between four characters &lt;strong&gt;&amp;quot;@@@@&amp;quot;&lt;/strong&gt;.&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Macro body from a text string (as in C/C++ preprocessor)&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@macro_str&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@@&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;macro&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;body&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@@&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# String for the lexer&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Removing macro @macro_str&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@@@&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;macro_str&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@@@&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;args&#34;&gt;Macro Arguments and Expansion&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#args&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; +&lt;p&gt;Macros can be defined with arguments (parameters in parentheses) or without them. +If a macro was defined with arguments, their validation will be performed by the macro processor during definition and expansion of the macro. +If a macro was defined without arguments, the presence of arguments will be ignored by the macro processor.&lt;/p&gt; +&lt;p&gt;The macroprocessor considers macros with and without arguments identical, +so it is not possible to create two macros with the same name, one with arguments (in parentheses) and the other without.&lt;/p&gt; +&lt;p&gt;Therefore, if you need to use a macro in two different ways (with arguments and without), +you should define the macro without arguments, and in this case, the parameter control will be done by the compiler.&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@ macro @@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; term&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Macro without arguments&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; macro&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;args&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# OK -&amp;gt; term(args);&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; macro&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# OK -&amp;gt; term;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# But&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@ call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt; @@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; term&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# OK -&amp;gt; term();&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; call&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Error (@call is defined with arguments) &lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If arguments are specified when defining a macro, the place for their insertion in the body of the macro is written +as the name of a local variable with the symbol &lt;strong&gt;&amp;quot;@&amp;quot;&lt;/strong&gt; added before it, i.e. &lt;strong&gt;@$arg&lt;/strong&gt;.&lt;/p&gt; +&lt;p&gt;The place for inserting the number of actual arguments passed is marked by the lexeme &lt;strong&gt;&amp;quot;@$#&amp;quot;&lt;/strong&gt;. +If it is necessary to insert the passed arguments as a dictionary, the place for insertion is marked by the lexeme &lt;strong&gt;&amp;quot;@$*&amp;quot;&lt;/strong&gt;.&lt;/p&gt; +&lt;p&gt;If the macro takes an arbitrary number of arguments (the macro arguments are terminated by an ellipsis), +the place for their insertion in the body of the macro is marked by the lexeme &lt;strong&gt;&amp;quot;@$&amp;hellip;&amp;quot;&lt;/strong&gt;.&lt;/p&gt; +&lt;p&gt;Analogous to the C/C++ preprocessor, to concatenate two lexemes into one, the operator &lt;strong&gt;&amp;quot;@##&amp;quot;&lt;/strong&gt; is used in the body of the macro, +and to convert a lexeme into a text string, the operators &lt;strong&gt;@#&lt;/strong&gt;, &lt;strong&gt;@#&amp;quot;&lt;/strong&gt;, or &lt;strong&gt;@#&amp;rsquo;&lt;/strong&gt; are applied, for example, +&lt;code&gt;@@macro($arg)@@ := @@ func_ @## @$arg( @#&amp;quot; arg ) @;&lt;/code&gt;, then the call &lt;code&gt;macro(name);&lt;/code&gt; will be transformed into &lt;code&gt;func_name (&amp;quot;name&amp;quot;);&lt;/code&gt;&lt;/p&gt; +&lt;p&gt;Examples of using macros:&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Ordinary macros (the body of the macro is a correct expression)&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;macro&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;replace&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;();&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;macro2&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;arg&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;call&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;arg&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;call&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;()};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# The body of the macros from a sequence of tokens&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# The expression may not be complete&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;elif&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,[&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,[&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Writing a conditional statement using&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# the macros defined above&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@if&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;condition&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;){&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@elif&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;condition2&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@else&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For example, a loop up to 5:&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;5&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;42&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;+=&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will look more familiar:&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@while&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;true&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@if&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;5&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@return&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;42&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; + </description> + </item> + <item> <title>Docs: Итераторы</title> <link>http://localhost:1313/docs/types/iter/</link> @@ -1657,435 +1761,6 @@ Sum1(arg1, arg2) :- {$arg1+$arg2;}; # Создать или переопреде </description> </item> - <item> - <title>Docs: Макросы</title> - <link>http://localhost:1313/docs/syntax/macros/</link> - <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate> - - <guid>http://localhost:1313/docs/syntax/macros/</guid> - <description> - - - &lt;p&gt;Макросы в &lt;strong&gt;NewLang&lt;/strong&gt;, это один или несколько последовательных терминов, которые заменяются на другой термин -или на целую синтаксическую конструкцию (последовательность лексем).&lt;/p&gt; -&lt;p&gt;Макросы обработываются во время работы &lt;strong&gt;лексера&lt;/strong&gt;, т.е. перед передачей последовательности лексем в парсер, -что позволяет с их помощью изменять даже сам синтаксис языка, например, при реализации собственных диалектов DSL.&lt;/p&gt; -&lt;h3 id=&#34;определение-макросов&#34;&gt;Определение макросов&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Определение макросов аналогично &lt;a href=&#34;http://localhost:1313/docs/ops/create/&#34;&gt;определению&lt;/a&gt; других объектов и состоит из трех частей -&lt;strong&gt;&amp;lt;имя макроса&amp;gt; &amp;lt;оператор создания/присвоения&amp;gt; &amp;lt;тело макроса&amp;gt;&lt;/strong&gt; и завершающая точка с запятой &amp;ldquo;&lt;strong&gt;;&lt;/strong&gt;&amp;rdquo;, -т.е. применяются обычные операторы &lt;strong&gt;::=&lt;/strong&gt;, &lt;strong&gt;=&lt;/strong&gt; или &lt;strong&gt;:=&lt;/strong&gt; для создания нового или переопределения уже существующего объекта, -а имя макроса указывается между двумя символами &lt;strong&gt;&amp;quot;@@&amp;quot;&lt;/strong&gt; и может содержать одну или нескольких лексем (терминов).&lt;/p&gt; -&lt;p&gt;Все макросы относятся к глобальному пространству имен, поэтому первый термин в имени макроса должен быть уникальным, -иначе он будет прекрывать имена локальных и глобальных переменных при &lt;a href=&#34;http://localhost:1313/docs/syntax/naming/&#34;&gt;разрешении имен&lt;/a&gt;, -если они указаны в коде без квалификаторов.&lt;/p&gt; -&lt;p&gt;??????????????????????? -Чистые (гигиеничные) макросы, &lt;strong&gt;::-&lt;/strong&gt; &lt;strong&gt;:-&lt;/strong&gt;, аргумента и переммые в которых гарантиованно не пересекаются с пространством имен программы?????????????????&lt;/p&gt; -&lt;p&gt;Телом макроса могут быть корректное выражение языка, последовательность лексем (которые заключается в двойные собачки &lt;strong&gt;&amp;quot;@@&amp;quot;&lt;/strong&gt;, -т.е. &lt;strong&gt;&lt;code&gt;@@ лексема1 лексема1 @@&lt;/code&gt;&lt;/strong&gt;) или обычная текстовая строка (которую нужно указать между тройными собачками &lt;strong&gt;&amp;quot;@@@&amp;quot;&lt;/strong&gt;, т.е. &lt;strong&gt;&lt;code&gt;@@@ текстовая строка @@@&lt;/code&gt;&lt;/strong&gt;).&lt;/p&gt; -&lt;p&gt;В имени макроса, кроме первого термина, могут присутствовать один или несколько шаблонов. -&lt;em&gt;Шаблон&lt;/em&gt; — это термин, который при сопоставлении последовательности лексем с идентификатором макроса -может заменяться любым другим одиночным термином (т.е. фактически это сопоставление по образцу/шаблону).&lt;/p&gt; -&lt;p&gt;Для создания термина-шаблона в начале его идентификатора нужно поставить знак доллара (что соответствует квалификатору локальной переменой), -т.е. имя макроса &lt;code&gt;@@ FUNC $name @@&lt;/code&gt; будет соответствовать последовательности лексем как &lt;code&gt;FUNC my_func_name&lt;/code&gt;, так и &lt;code&gt;FUNC other_name_func&lt;/code&gt;.&lt;/p&gt; -&lt;p&gt;Для удаления макроса используется специальный синтаксис: &lt;code&gt;@@@@ name @@@@;&lt;/code&gt; или &lt;code&gt;@@@@ два термина @@@@;&lt;/code&gt;, -т.е. необходимо указать идентификатор макроса между четырмя символами &lt;strong&gt;&amp;quot;@@@@&amp;quot;&lt;/strong&gt;.&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Тело макроса из текстовой строки (как в препроцессоре С/С++)&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@macro_str@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@@ строка - тело макроса @@@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Строка для лексера&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Удаления макроса @macro_str&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@@@ macro_str @@@@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;аргументы-макросов-и-их-раскрытие&#34;&gt;Аргументы макросов и их раскрытие&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d1%8b-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2-%d0%b8-%d0%b8%d1%85-%d1%80%d0%b0%d1%81%d0%ba%d1%80%d1%8b%d1%82%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Макросы можно определять как с аргументами (параметрами в скобках), так и без них. -Если макрос был определен с аргументами, то их проверка будет выполнятся макропроцессором при определении и раскрытии макроса. -Если макрос был определен без аргументов, то их наличие макропроцессором игнорируется.&lt;/p&gt; -&lt;p&gt;Так как макропроцессор считает макросы с аргументами и без оных идентичными, то нельзя создать два макроса -с одинаковыми именами, один из которых будет с аргументами (скобками), а другой без них.&lt;/p&gt; -&lt;p&gt;Поэтому, если требуется использовать макрос в двух разных вариантах (с аргументами и без них), -тогда следует определять макрос без аргументов и в этом случае контроль параметров будет производить компилятор.&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@macro@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; term&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Макрос без аргументов&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; macro&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;args&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# ОК -&amp;gt; term(args);&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; macro&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# ОК -&amp;gt; term;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Но &lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; term&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# ОК -&amp;gt; term();&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; call&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Ошибка (@call определен с аргументами) &lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Если при определении макроса указаны аргументы, то место для их вставки в теле макроса -записывается как имя локальной переменой, перед которой добавлен символ &lt;strong&gt;&amp;quot;@&amp;quot;&lt;/strong&gt;, т.е. &lt;strong&gt;@$arg&lt;/strong&gt;.&lt;/p&gt; -&lt;p&gt;Произвольное количество аргументов у макроса отмечается троеточием &lt;strong&gt;&amp;quot;&amp;hellip;&amp;quot;&lt;/strong&gt;, а место для их вставки отмечается в теле макроса лексемой &lt;strong&gt;&amp;quot;@$&amp;hellip;&amp;quot;&lt;/strong&gt;.&lt;/p&gt; -&lt;p&gt;Место для вставки числа реально переданных аргументов отмечается лексемой &lt;strong&gt;&amp;quot;@$#&amp;quot;&lt;/strong&gt;. -Если требуется вставить переданные аргументы в виде элементов словаря, -то место для вставки отмечается лексемой &lt;strong&gt;&amp;quot;@$*&amp;quot;&lt;/strong&gt;.&lt;/p&gt; -&lt;p&gt;По аналогии с препроцессором С/С++, для соединения двух лексем в одну, в теле макроса используется оператор &lt;strong&gt;&amp;quot;@##&amp;quot;&lt;/strong&gt;, -а для преобразование лексемы в текстову строку применяется операторы &lt;strong&gt;@#&lt;/strong&gt;, &lt;strong&gt;@#&amp;quot;&lt;/strong&gt; или &lt;strong&gt;@#&amp;rsquo;&lt;/strong&gt;, например, -&lt;code&gt;@@macro($arg)@@ := @@ func_ @## @$arg( @#&amp;quot; arg ) @;&lt;/code&gt;, тогда вызов &lt;code&gt;macro(name);&lt;/code&gt; будет преобразован в &lt;code&gt;func_name (&amp;quot;name&amp;quot;);&lt;/code&gt;&lt;/p&gt; - - -&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; -&lt;h4 id=&#34;ограничения-макропроцессора-в-текущей-версии&#34;&gt;Ограничения макропроцессора в текущей версии&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%b3%d1%80%d0%b0%d0%bd%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d0%bf%d1%80%d0%be%d1%86%d0%b5%d1%81%d1%81%d0%be%d1%80%d0%b0-%d0%b2-%d1%82%d0%b5%d0%ba%d1%83%d1%89%d0%b5%d0%b9-%d0%b2%d0%b5%d1%80%d1%81%d0%b8%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h4&gt; -&lt;p&gt;На текущий момент макросы реализованы в минимальном объеме для самых простых сценариев использования:&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;DSL для keyword based syntax (if, else, return, match, while и т.д.) - (1 термин с произвольными аргументами и без) - требуется сейчас !!!&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;&lt;em&gt;Парсер при обработке макросов может анализировать информацию о типах данных, если она указана.&lt;/em&gt; -&lt;em&gt;Но на текущий момент типы данных в макросах никак не обрабатываются и это одна из обязательных фич, которая будет реализована в будущем.&lt;/em&gt;&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Определения (func, class) - (несколько терминов с аргументами и без аргументов) - Реализация ООП и импорт С++ классов&lt;/li&gt; -&lt;li&gt;Модификации при определениях (override) - (несколько терминов и шаблоны с аргументами и без аргументов) - Реализация ООП и импорт С++ классов&lt;/li&gt; -&lt;/ul&gt; - -&lt;/div&gt; - -&lt;h1 id=&#34;макросы-без-аргументов-или-все-аргументы-сразу-&#34;&gt;МАКРОСЫ БЕЗ АРГУМЕНТОВ ИЛИ ВСЕ АРГУМЕНТЫ СРАЗУ !!!!!&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b1%d0%b5%d0%b7-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d0%b8%d0%bb%d0%b8-%d0%b2%d1%81%d0%b5-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d1%8b-%d1%81%d1%80%d0%b0%d0%b7%d1%83-&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;h1 id=&#34;анализа-аргументов-или-их-типов-не-производится-&#34;&gt;анализа аргументов или их типов не производится !!!&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b0%d0%bd%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d0%b8%d0%bb%d0%b8-%d0%b8%d1%85-%d1%82%d0%b8%d0%bf%d0%be%d0%b2-%d0%bd%d0%b5-%d0%bf%d1%80%d0%be%d0%b8%d0%b7%d0%b2%d0%be%d0%b4%d0%b8%d1%82%d1%81%d1%8f-&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;Lambda -@@ lambda $name(&amp;hellip;) @@ ::= @@ @$name( @$&amp;hellip; ) ::= ( _( @$&amp;hellip; ) ::= @&lt;strong&gt;PRAGMA_FINALIZE&lt;/strong&gt;( @), {, {+, {-, {* ) @@&lt;/p&gt; -&lt;h3 id=&#34;примеры-использования-макросов&#34;&gt;Примеры использования макросов&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80%d1%8b-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Обычные макросы (тело макроса корректное выражение)&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@macro@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; replace&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@macro2&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;arg&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt; call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;@&lt;span style=&#34;color:#000&#34;&gt;$arg&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()}&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Тело макросов из последовательности лексем&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@if&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;...&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@ &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;\$&lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;*&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;--&amp;gt; @@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Выражение может быть не полным&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@elif&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;...&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@ ,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;\$&lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;elif&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;*&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;--&amp;gt; @@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@else@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@ ,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;_&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;--&amp;gt; @@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Запись условного оператора с использованием &lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# определенных выше макросов&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt; condition &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;){&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ... -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;elif&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt; condition2 &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ... -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ... -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Зачем нужна трансформация синтаксиса? -Нативная поддержка других языков нужна чтобы не переписывать легаси код на этих языках.&lt;/p&gt; -&lt;p&gt;Чтобы можно было использовать существующие исходники как собственные требуется настройка работы -препроцессора и лексера под конкретный язык программирования (описание DSL). -Для &lt;strong&gt;С/С++&lt;/strong&gt; потребуется выделять лексером комментарии из-за пересечения синтаксиса (которые сейчас игнорируются). -Для &lt;strong&gt;Python&lt;/strong&gt; требуется выделять лексером отступы (которые сейчас тоже игнорируются), причем потребуется реализация не только синтаксиса, -но и зависимых пакетов с последующая трансляцией этого кода в С++, что в настоящий момент делать не целесообразно (cython ???).&lt;/p&gt; -&lt;p&gt;Но так как возможность трансформации кода с других языков программирования принципиальная возможна, -стоит над этим думать только после полноценного релиза NewLang и его перехода в прод.&lt;/p&gt; -&lt;p&gt;Для реализации DSL требуется передача команд в парсер для управления его работой (по аналогии с командой #pragma) -Но так как обработка таких команд должна происходить в лексере до передачи данных в парсер (анализатор), -то команды для макропроцессора должны быть в максимально простом виде и состоять из элементов, -которые лексер может самостоятельно идентифицировать, т.е. термины, строки и цифры (без выражений и именованных аргументов).&lt;/p&gt; -&lt;p&gt;После обработки такой команды она анализируется макропроцессором и удаляется из потока лексем, т.е. в парсер (анализатор) не передается. -Но в случае ошибки с синтаксисе, данные команды нужно уметь однозначно идентифировать и самый простой способ, -комбинация признака макроса и системного имени, т.е. что-то вроде&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; @__PRAGMA_DIAG__(push) - @__PRAGMA_DIAG__(ignored, &amp;#34;-Wundef&amp;#34;) - @__PRAGMA_DIAG__(warning, &amp;#34;-Wformat&amp;#34;) - @__PRAGMA_DIAG__(error &amp;#34;-Wuninitialized&amp;#34;) - @__PRAGMA_DIAG__(pop) - - #pragma message &amp;#34;Compiling &amp;#34; __FILE__ &amp;#34;...&amp;#34; - @__PRAGMA_MESSAGE__(&amp;#34;Compiling &amp;#34;, __FILE__, &amp;#34;...&amp;#34;) - - #pragma error &amp;#34;Error &amp;#34; __FILE__ &amp;#34;...&amp;#34; - @__PRAGMA_ERROR__(&amp;#34;Error &amp;#34;, __FILE__, &amp;#34;...&amp;#34;) - - -#define DO_PRAGMA(x) _Pragma (#x) -#define TODO(x) DO_PRAGMA(message (&amp;#34;TODO - &amp;#34; #x)) - -@@TODO( ... )@@ := @__PRAGMA_MESSAGE__(&amp;#34;TODO - &amp;#34;, @*) - -@TODO(Remember to fix this) # note: TODO - Remember to fix this - -\\.__lexer__ignore_space__ = 1; -\\.__lexer__ignore_indent__ = 1; -\\.__lexer__ignore_comment__ = 1; -\\.__lexer__ignore_crlf__ = 1; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Таким образом можно трансформировать условный оператор на питоне в синтаксис NewLang следующим макросом:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; -#pragma clang attribute push -#pragma clang diagnostic ignored &amp;#34;-Wundef&amp;#34; -#pragma clang diagnostic ignored &amp;#34;-Wunused-variable&amp;#34; - - -#elif __GNUC__ - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored &amp;#34;-Wuninitialized&amp;#34; - -#pragma GCC diagnostic ignored &amp;#34;-Wall&amp;#34; -#pragma GCC diagnostic ignored &amp;#34;-Wextra&amp;#34; - - @pragma warning(pop) - - @@ pragma warning(...) @@ := __PRAGMA_TERM_DIAG_WARNING__(); -@__PRAGMA_DIAG__(warning, pop); - -Обработка терминов в макропроцессоре в максимально простом виде. -Агрументы только термины, строки и цифры без вложенных выражений и именованных аргументов, -т.е. только элементы, которые может самостоятельно идентифицировать лексер. - -@warning(&amp;#34;--&amp;#34;) - @@ if ... : @@ := @@ [ @$* ]-&amp;gt; __TERM_BLOCK_INDENT__(&amp;#34;{&amp;#34;, force_semicolon=1) @@ - - if __name__ == &amp;#34;__main__&amp;#34;: - run1() - run2() - - [ __name__ == &amp;#34;__main__&amp;#34; ]-&amp;gt; { - run1(); - run2(); - }; - - -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ключ &amp;ndash;parser-syntax-only только текстовый парсинг исходного кода без загрузки модулей, раскрытия макросов и проверки имен.&lt;/p&gt; -&lt;p&gt;Ключ &amp;ndash;parser-no-macros - без раскрытия макросов -Ключ &amp;ndash;parser-no-module - без загрузки модулей (и мокросов, если они в них определяются) -Ключ &amp;ndash;parser-no-check-prototype - без проверки имен при обращении&lt;/p&gt; -&lt;p&gt;prototype -@&lt;strong&gt;PRAGMA_PROTOTYPE&lt;/strong&gt;(define) -@&lt;strong&gt;PRAGMA_PROTOTYPE&lt;/strong&gt;(implement)&lt;/p&gt; -&lt;p&gt;$$&lt;/p&gt; -&lt;p&gt;\$ - корень системы (система)&lt;/p&gt; -&lt;p&gt;$ - текущий модуль&lt;/p&gt; -&lt;h1 id=&#34;макросы-для-конвертора-проверки-в-python&#34;&gt;Макросы для конвертора проверки в Python&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b4%d0%bb%d1%8f-%d0%ba%d0%be%d0%bd%d0%b2%d0%b5%d1%80%d1%82%d0%be%d1%80%d0%b0-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b8-%d0%b2-python&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;h1 id=&#34;if-__name__--__main__&#34;&gt;if &lt;strong&gt;name&lt;/strong&gt; == &amp;ldquo;&lt;strong&gt;main&lt;/strong&gt;&amp;rdquo;:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#if-__name__--__main__&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;@@ &lt;strong&gt;name&lt;/strong&gt; @@ ::= @@ $. @&lt;strong&gt;PRAGMA_NO_MACRO&lt;/strong&gt;() &lt;strong&gt;name&lt;/strong&gt; @@ -@@ if $&amp;hellip; @: @@ ::= @@ [ @$&amp;hellip; ] &amp;ndash;&amp;gt; @@&lt;/p&gt; -&lt;p&gt;@if( $.&lt;strong&gt;name&lt;/strong&gt; == &amp;ldquo;&lt;strong&gt;main&lt;/strong&gt;&amp;rdquo; ) {&lt;/p&gt; -&lt;p&gt;}&lt;/p&gt; -&lt;p&gt;\каталог\модуль() - статический импорт модуля -\(&amp;ldquo;каталог\модуль&amp;rdquo;)() - динамический импорт модуля&lt;/p&gt; -&lt;p&gt;printf := :Pointer(&amp;lsquo;printf(format:FmtChar, &amp;hellip;):Int32&amp;rsquo;); -printf := %printf(format:FmtChar, &amp;hellip;):Int32;&lt;/p&gt; -&lt;h1 id=&#34;регистрация-прототипа-нативной-функции&#34;&gt;Регистрация прототипа нативной функции&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%80%d0%b5%d0%b3%d0%b8%d1%81%d1%82%d1%80%d0%b0%d1%86%d0%b8%d1%8f-%d0%bf%d1%80%d0%be%d1%82%d0%be%d1%82%d0%b8%d0%bf%d0%b0-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;@prototype -%puts(format:StrChar):Int32;&lt;/p&gt; -&lt;h1 id=&#34;импорт-нативной-функции-с-предварительной-проверкой-её-наличия-во-время-компиляции-статическая-линковка&#34;&gt;Импорт нативной функции с предварительной проверкой её наличия во время компиляции (статическая линковка)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b8%d0%bc%d0%bf%d0%be%d1%80%d1%82-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d1%81-%d0%bf%d1%80%d0%b5%d0%b4%d0%b2%d0%b0%d1%80%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d0%be%d0%b9-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%be%d0%b9-%d0%b5%d1%91-%d0%bd%d0%b0%d0%bb%d0%b8%d1%87%d0%b8%d1%8f-%d0%b2%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d1%8f-%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%86%d0%b8%d0%b8-%d1%81%d1%82%d0%b0%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bb%d0%b8%d0%bd%d0%ba%d0%be%d0%b2%d0%ba%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;puts2(format:StrChar):Int32 := %puts(format:StrChar):Int32;&lt;/p&gt; -&lt;h1 id=&#34;импорт-нативной-функции-по-её-прототипу-во-время-выполнения-динамическая-линковка&#34;&gt;Импорт нативной функции по её прототипу во время выполнения (динамическая линковка)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b8%d0%bc%d0%bf%d0%be%d1%80%d1%82-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d0%bf%d0%be-%d0%b5%d1%91-%d0%bf%d1%80%d0%be%d1%82%d0%be%d1%82%d0%b8%d0%bf%d1%83-%d0%b2%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d1%8f-%d0%b2%d1%8b%d0%bf%d0%be%d0%bb%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b4%d0%b8%d0%bd%d0%b0%d0%bc%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bb%d0%b8%d0%bd%d0%ba%d0%be%d0%b2%d0%ba%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;puts3(format:StrChar):Int32 := :Pointer(&amp;lsquo;puts(format:StrChar):Int32&amp;rsquo;);&lt;/p&gt; -&lt;p&gt;%puts(&amp;lsquo;Тест вывода строки&amp;rsquo;); # Линковка с нативной функцией во время компиляции и непосредственный вызов с оптимизацией передачи параметров -puts2(&amp;lsquo;Тест 2 вывода строки&amp;rsquo;); # Линковка с нативной функцией во время компиляции -puts3(&amp;lsquo;Тест 3 вывода строки&amp;rsquo;); # Линковка с нативной функцией во время выполнения при первом вызове puts3&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Парсинг исходного текста без раскрытия макросов и загрузки модулей&lt;/li&gt; -&lt;li&gt;Парсинг исходного текста с раскрытием макросов (требуется загрузка модулей для зависимых и переопределяемых макросов)&lt;/li&gt; -&lt;li&gt;Загружатся модули могут как в виде исходников (которые требуется парсить и компилировть/выполнять) -или в виде бинарников (в них должны быть список макросов, типов и имена объектов)&lt;/li&gt; -&lt;li&gt;После парсинга получается список &lt;strong&gt;имен&lt;/strong&gt; макросов, типов и объектов (TermPtr)&lt;/li&gt; -&lt;li&gt;После выполнения модуля - список &lt;strong&gt;имен&lt;/strong&gt; заполняется реальными объектами (ObjPtr).&lt;/li&gt; -&lt;/ul&gt; -&lt;h1 id=&#34;компиляция-файла&#34;&gt;Компиляция файла&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%86%d0%b8%d1%8f-%d1%84%d0%b0%d0%b9%d0%bb%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;ul&gt; -&lt;li&gt;Парсинг исходника для построения AST (без анализа имен, связей, загрузки модулей и пр. только исходые тексты с раскрытием макросов&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;/ul&gt; -&lt;h1 id=&#34;систематизация-реализации-макросов&#34;&gt;Систематизация реализации макросов&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0%d1%82%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d1%80%d0%b5%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d0%b8-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;последовательность лексем MACRO_SEQ мужду @@ @@ сохраняется в m_block, так как фрагменты блоков не могут быть идентификаторами&lt;/p&gt; -&lt;p&gt;Разбор макросов происходит в лексере. Определением макроса всегда является целая строка, -которая заканчивается точкой с запятой, а идентификатором макроса всегда выступает последовательность лексем:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@ id @@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; macro&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@ id @@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@ @@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@ id @@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@@ @@@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Хранилищем текущих максросов является объект класса MacroBuffer. -Последовательность лексем идентификатора (id) макроса должна сохраняется в отдельном поле термина и однозначно его идентифицирует. -Первый термин в идентификаторе хранится как ключ hashmap, а дальше происходит поиск полным перебором. -Этапы работы с макросами&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt; -&lt;p&gt;Входные термины из лексера получаются вызовом GetNextToken, внутри которой и происходит раскрытие макросов. -Внутренний буфер заполняется до окончания строки (выражения), т.е. до символа &amp;lsquo;;&amp;rsquo; или &lt;END&gt;, после чего производится -поиск макросов в объекте MacroBuffer для текущей последовательности лексем в буфере.&lt;/p&gt; -&lt;/li&gt; -&lt;li&gt; -&lt;p&gt;Если макрос найден, то соответствющая ему последоваетльность заменяется на тело макроса и происходит переход -на повторный анализ входного буфера.&lt;/p&gt; -&lt;/li&gt; -&lt;li&gt; -&lt;p&gt;Если макрос не найден, то данные передаются в парсер для дальнейшего синтаксическго анализа.&lt;/p&gt; -&lt;/li&gt; -&lt;li&gt; -&lt;p&gt;Для этого во входном потоке лексем (parser.y) во время оператората создания/присвоения вызывается функция проверки на макрос. -MacroBuffer::CheckMacroAndConvertDel($$), и после этого выходному значению присваивается результат выполнения driver.MacroEval($$), -и в дальнейшем этот макрос никак не обработывается.&lt;/p&gt; -&lt;/li&gt; -&lt;li&gt; -&lt;p&gt;Создание макросов, проверка на дубликаты и логические ошибки в определении происходит путем обращения к методам объекта MacroBuffer.&lt;/p&gt; -&lt;p&gt;/*&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Макросы хрянтся как фрагменты AST в виде объектов типа Term,&lt;/li&gt; -&lt;li&gt;так как создаются после обработки парсером по правилам стандратной грамматики.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Но анализ входных данных на предмет раскрытия макросов проиходит из потока (последовательности) лексем,&lt;/li&gt; -&lt;li&gt;т.е. &lt;strong&gt;ДО&lt;/strong&gt; обработки парсером, так как при раскрытии макросов может меняться грамматика выражений.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Функция \ref CompareMacro сравнивает входной буфер (последовательность лексем)&lt;/li&gt; -&lt;li&gt;на предмет возможного соответствия одному конкретному макросу.&lt;/li&gt; -&lt;li&gt;Сравниваются только ключевые словам без учета аргументов в скобках,&lt;/li&gt; -&lt;li&gt;но само наличие аргументов проверяется ??????????????????&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Проблема:&lt;/li&gt; -&lt;li&gt;К функции можно обратится с целью её вызова (указав после имени скобки),&lt;/li&gt; -&lt;li&gt;так и по имени без скобок (например для получения ссылки на объект).&lt;/li&gt; -&lt;li&gt;Так и к переменной можно обратиться только по имени,&lt;/li&gt; -&lt;li&gt;так и указав скобки после имени как к функции (при копировании объекта).&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Сделать один макрос под оба сценария (со скобками и без скобок) не получится, так как непонятно,&lt;/li&gt; -&lt;li&gt;что делать с аргументами при раскрытии тела макроса, когда они не указаны.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Но может быть следует переименовывать только одно имя без учета скобок,&lt;/li&gt; -&lt;li&gt;например, оставив такую возможность только для одиночных макросов.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;\name -&amp;gt; name или name (&amp;hellip;), hash: name&lt;/li&gt; -&lt;li&gt;но \name(&amp;hellip;) -&amp;gt; name(&amp;hellip;), а name - ошибка !!!! hash: name&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Или все же следует различать макросы со скобками и без скобок как два разных объекта???&lt;/li&gt; -&lt;li&gt;\name := name2; и \name(&amp;hellip;) := name2(&amp;hellip;); будут разными объектами&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Или добавить макросы-алиасы без аргументов только для переименования отдельных терминов?&lt;/li&gt; -&lt;li&gt;\alias :- name2; но как их отличать от обычных макросов в операции удаления?&lt;/li&gt; -&lt;li&gt;Или вообще не нужно отличать и оставить только один варинат (либо макрос, либо алиас)&lt;/li&gt; -&lt;li&gt;Тода вопрос со скобками закрывается сам собой, алиасы всегда без скобок,&lt;/li&gt; -&lt;li&gt;макросы со скбками или без скобок, но должно быть полное соответствие.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;@ name name2 @ -&amp;gt; name name2, но name name2(&amp;hellip;) - ошибка!!! (hash: name,name2)&lt;/li&gt; -&lt;li&gt;@ name name2(&amp;hellip;) @ -&amp;gt; name name2(&amp;hellip;), но name name2 - ошибка !!!! (hash: name,name2)&lt;/li&gt; -&lt;li&gt;@ name name2&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; @ -&amp;gt; name name2&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt;, но name name2 - ошибка !!!! ( hash: name,name2 )&lt;/li&gt; -&lt;li&gt;@ name $tmpl&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; name3@ -&amp;gt; name $tmpl&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Но!&lt;/li&gt; -&lt;li&gt;@ name name2 @ ::- -&amp;gt; name name2 - ок, но name name2(&amp;hellip;) - ок&lt;/li&gt; -&lt;li&gt;@ name $tmpl name3@ ::- -&amp;gt; name $tmpl&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; name3 - ок, name $tmpl(&amp;hellip;) name3[&amp;hellip;] - ок&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Для последовательности лексем требуется полное соответствие с учетом скобок ???&lt;/li&gt; -&lt;li&gt;и может ли быть несколько скобок одного типа (несколько крыглях, или несколько квардратных????&lt;/li&gt; -&lt;li&gt;&amp;lt;Может быть несколько скобок одного типа, например, при указании типа у аргументов или типа возвращаемого значения.&amp;gt;&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;@ name name2 @ -&amp;gt; name name2, но name name2(&amp;hellip;) - ошибка!!! (hash: name,name2)&lt;/li&gt; -&lt;li&gt;@ name name2(&amp;hellip;) @ -&amp;gt; name name2(&amp;hellip;), но name name2 - ошибка !!!! (hash: name,name2)&lt;/li&gt; -&lt;li&gt;@ name name2&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; @ -&amp;gt; name name2&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt;, но name name2 - ошибка !!!! ( hash: name,name2 )&lt;/li&gt; -&lt;li&gt;@ name $tmpl&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; name3@ -&amp;gt; name $tmpl&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Проблема скобок возникает из-за сценария замены одного термина на другой,&lt;/li&gt; -&lt;li&gt;который есть в препроцессоре С/С++, но отсутствует при реализации с использованием шаблонов.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;*/&lt;/p&gt; -&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;Макросы используются и для превращеня исходного кода &lt;em&gt;NewLang&lt;/em&gt; в более привычный синтаксис на основе &lt;a href=&#34;https://newlang.net/syntax_dsl.html&#34;&gt;ключевых слов&lt;/a&gt;, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода.&lt;/p&gt; -&lt;p&gt;&lt;a href=&#34;https://newlang.net/syntax_dsl.html&#34;&gt;Например:&lt;/a&gt;.&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; @@if(...)@@ ::= @@ [ \$* ]--&amp;gt; @@; - @@while(...)@@ ::= @@ [\$*] &amp;lt;-&amp;gt; @@; - @@return $arg@@::= @@ -- \$arg -- @@; - @@true@@ ::= 1; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Тогда цикл до 5:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;count:=1; -[ 1 ] &amp;lt;-&amp;gt; { - [count&amp;gt;5] --&amp;gt; { - -- 42 --; - }; - count+=1; -}; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;будет выглядеть более привычно&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;count:=1; -while( true ) { - if(count&amp;gt;5) { - return 42; - }; - count+=1; -}; -&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;идеи-на-будущее&#34;&gt;Идеи на будущее&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b8%d0%b4%d0%b5%d0%b8-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h3 id=&#34;символьное-программирование&#34;&gt;Символьное программирование&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d0%bc%d0%b2%d0%be%d0%bb%d1%8c%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;blockquote&gt; -&lt;p&gt;Символьное программирование, часто называемое декларативным программированием, представляет собой парадигму программирования, которая использует математическую логику, отношения и символы для представления знаний и помощи в решении проблем. Вместо того, чтобы сосредотачиваться на описании последовательности операций, необходимых для выполнения вычислений, как в императивном программировании, символическое программирование делает упор на выражении отношений и ограничений между структурами данных, уделяя особое внимание «что», а не «как».&lt;/p&gt; -&lt;p&gt;В контексте парадигм программирования символическое программирование часто противопоставляется процедурному или императивному программированию, где программы определяют пошаговые процедуры для достижения своих целей. В то время как императивное программирование фокусируется на описании потока управления с использованием таких конструкций, как циклы и условные выражения, для управления выполнением, символическое программирование сосредоточено на выражении фактов о проблеме и позволяет выполнению естественным образом выводить последующие последствия из предоставленной информации.&lt;/p&gt; -&lt;p&gt;Одним из основных преимуществ символьного программирования является его способность обеспечивать более высокий уровень абстракции, что упрощает анализ кода и снижает вероятность ошибок. Непосредственно выражая отношения и ограничения, символическое программирование позволяет разработчикам сосредоточиться на моделировании и спецификации проблем, позволяя базовой системе управлять реализацией и выполнением алгоритмов.&lt;/p&gt; -&lt;p&gt;Существует несколько языков программирования и сред, использующих парадигму символьного программирования, например Prolog, Lisp и Haskell. Например, Пролог — это язык логического программирования, который позволяет разработчикам выражать взаимосвязи и факты о проблемных областях, в то время как выполнение автоматически обосновывает и извлекает новые факты на основе исходной информации. В том же духе Лисп, функциональный язык программирования, использует символьные вычисления для манипулирования структурами данных и выполнения сложных операций над ними, используя краткий и математически обоснованный синтаксис. Haskell, еще один функциональный язык программирования, использует строгую типизацию и ленивые вычисления, чтобы обеспечить символическое рассуждение и облегчить эффективное создание программ.&lt;/p&gt; -&lt;p&gt;Символьное программирование может быть полезным в широком спектре проблемных областей, включая искусственный интеллект, экспертные системы, программирование логики ограничений и символьную математику, среди других. Более высокий уровень абстракции, обеспечиваемый декларативными языками программирования, облегчает разработку сложных систем, сводя к минимуму вероятность ошибки и улучшая удобство обслуживания. В частности, использование символьного программирования в искусственном интеллекте позволяет разработчикам создавать системы представления знаний и механизмы рассуждения, которые можно применять для обработки естественного языка, машинного обучения и автоматического доказательства теорем.&lt;/p&gt; -&lt;/blockquote&gt; -&lt;p&gt;Различие между символьным программированием и препроцессором&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Задача препроцессора - раскрыть(расширить) макрос, тогда как при символьном программировании нужно сокращать (сворачивать) выражения&lt;/li&gt; -&lt;li&gt;Препроцессор обрабатывает последовательности лексем (плоские данные), тогда как символьное программирование оперирует выражениями (деревом лексем)&lt;/li&gt; -&lt;li&gt;Макрос у препроцессора идентифицируется первым термином, и если макрос не может быть раскрыт, то возникает ошибка. В символьном программировани требуется точное соответствие всего выражения и только в этом случае производится сокращение выражения.&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;Предпосылки для реализации символьного программирования -Компилятор - интерепретатор с REPL и обработка AST как во время компиляции, так и во время выполнения. -Необходимо добавить конструкции для определения правил символьного программрования (чистые функции?) -Необходимо добавить конструкцию для вычисления выражений в символьном программировании.&lt;/p&gt; -&lt;p&gt;Wolfram -&lt;a href=&#34;https://habr.com/articles/772984/&#34;&gt;https://habr.com/articles/772984/&lt;/a&gt;&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;diffRules = { - Sin[x] -&amp;gt; Cos[x], - Cos[x] -&amp;gt; -Sin[x], - x^2 -&amp;gt; 2*x, - x -&amp;gt; 1, - Log[x] -&amp;gt; 1/x -}; -&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;diffRules := ( - Sin(x) @-&amp;gt; Cos(x), - Cos(x) @-&amp;gt; -Sin(x), - x^2 @-&amp;gt; 2*x, - x @-&amp;gt; 1, - Log(x) @-&amp;gt; 1\x, -); - -expr @-&amp;gt; Sin(x) - x^2 + Log(x); - -# И применим к нему правила дифференцирования - -#expr /. diffRules -#(* 1/x - 2 x + Cos[x] *) - -sym := SymEval(expr, diffRules); -res := Eval(sym, x=0.123); -&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;expr = a^2 + 3 * b^3 - c^4 + 2 * x^2 - x + 4*c + 3 - -И я хочу это выражение линеаризовать, т.е. отбросить все степени выше первой. Я могу сделать это напрямую, как в примерах выше: - -expr /. { - a^2 -&amp;gt; 0, - b^3 -&amp;gt; 0, - c^4 -&amp;gt; 0, - x^2 -&amp;gt; 0 -} -(* 3 + 4 c - x *) - -Но это слишком неудобно. Что если я не знаю ни точную степень, ни имя переменной? Как просто указать, что нужно заменить все места, где встречается возведение в степень на ноль? Это можно сделать при помощи шаблонов вот так: - -expr /. Power[_, _] -&amp;gt; 0 -(* 3 + 4 c - x *) - -Либо вот так: - -expr /. _ ^ _ -&amp;gt; 0 -(* 3 + 4 c - x *) -&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;:diffRules() := { - {@ Sin(x) @} ::- {@ Cos(x) @}; - Cos(x) @-&amp;gt; -Sin(x), - x^2 @-&amp;gt; 2*x, - x @-&amp;gt; 1, - Log(x) @-&amp;gt; 1\x, -}; - -expr @-&amp;gt; Sin(x) - x^2 + Log(x); - -# И применим к нему правила дифференцирования - -#expr /. diffRules -#(* 1/x - 2 x + Cos[x] *) - -sym := SymEval(expr, diffRules); -res := Eval(sym, x=0.123); -&lt;/code&gt;&lt;/pre&gt; - </description> - </item> - <item> <title>Docs: Другие типы данных</title> <link>http://localhost:1313/docs/types/other/</link> @@ -2242,7 +1917,7 @@ Number 5 from the thread!&lt;/p&gt; </item> <item> - <title>Docs: Нативные типы</title> + <title>Docs: Native Data Types</title> <link>http://localhost:1313/docs/types/native/</link> <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate> @@ -2250,20 +1925,33 @@ Number 5 from the thread!&lt;/p&gt; <description> - &lt;h2 id=&#34;нативные-типы-данных&#34;&gt;Нативные типы данных&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &amp;ldquo;&lt;strong&gt;%&lt;/strong&gt;&amp;rdquo;. -В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат.&lt;/p&gt; -&lt;h3 id=&#34;pointer--указатель-на-системную-область-памяти-или-нативную-функцию&#34;&gt;:Pointer — указатель на системную область памяти или нативную функцию&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#pointer--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%83%d1%8e-%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8-%d0%b8%d0%bb%d0%b8-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%83%d1%8e-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8e&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Так как любой программе приходится взаимодействовать с внешним миром, т -о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, -и для этих целей служит тип &lt;em&gt;:Pointer&lt;/em&gt;. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. -Но можно вывести его значение, например для отладки.&lt;/p&gt; -&lt;h3 id=&#34;plain--указатель-на-представление-данных-в-бинарном-виде&#34;&gt;:Plain — указатель на представление данных в бинарном виде&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#plain--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d0%bf%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%be%d0%bc-%d0%b2%d0%b8%d0%b4%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Для взаимодействия с внешними библиотеками требуется еще и обмен данными. -И для этих целей служит тип данных &lt;em&gt;:Plain&lt;/em&gt; — который также является указателем, но на двоичное представление данных в области памяти. -Конечно, если их можно представить в виде одного фрагмента.&lt;/p&gt; -&lt;h3 id=&#34;перечисление-структура-и-объединение&#34;&gt;Перечисление, структура и объединение&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d0%b5%d1%80%d0%b5%d1%87%d0%b8%d1%81%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d0%b8-%d0%be%d0%b1%d1%8a%d0%b5%d0%b4%d0%b8%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;&lt;em&gt;:Enum&lt;/em&gt;, &lt;em&gt;:Struct&lt;/em&gt; и &lt;em&gt;:Union&lt;/em&gt; — это такие же &lt;a href=&#34;http://localhost:1313/docs/types/dicts/#%D0%BF%D0%B5%D1%80%D0%B5%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D0%B0-%D0%B8-%D0%BE%D0%B1%D1%8A%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5&#34;&gt;словари&lt;/a&gt;, только на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера. Эти типы данных так же относятся к группе &lt;em&gt;:Plain&lt;/em&gt; и могут быть представлены в двоичном виде в одной области машинной памяти.&lt;/p&gt; + &lt;p&gt;Native (machine) data can be variables or functions, and the names of native objects start with the percent symbol &amp;ldquo;&lt;strong&gt;%&lt;/strong&gt;&amp;rdquo;.&lt;/p&gt; +&lt;p&gt;In the case of variables, these are binary data located in a single continuous area of machine memory at a specific address and have a strictly defined format.&lt;/p&gt; +&lt;p&gt;To use existing libraries, you need to import the native object, thereby creating an object NewLang, +but with an implementation in another language, for example, in C/C++.&lt;/p&gt; +&lt;p&gt;The syntax for importing native objects is the same as for &lt;a href=&#34;http://localhost:1313/docs/ops/create/&#34;&gt;creating&lt;/a&gt; regular language objects, +only the name of the native object needs to be specified as the right operand in the creation operator.&lt;/p&gt; +&lt;p&gt;When importing a native object, it is necessary to always specify the variable types, +as well as the types of arguments and return values for functions.&lt;/p&gt; +&lt;p&gt;If the data types of the created object and the native object match (i.e., no type conversion is required), +then the native object name can be specified with an ellipsis, +which means that the data types will replicate those specified at the left operand.&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Plain&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fopen&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;filename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;StrChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;modes&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;StrChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fopen&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fclose&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fclose&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fflush&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fflush&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fprintf&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#204a87&#34;&gt;format&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FmtChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fprintf&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fremove&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;filename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;remove&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;frename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;old&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;new&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;rename&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; + +&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; +&lt;p&gt;The following description is under development.&lt;/p&gt; + +&lt;/div&gt; + </description> </item> @@ -2984,235 +2672,145 @@ my_file.write(&amp;lsquo;hello world&amp;rsquo;)&lt;/p&gt; <description> - &lt;h2 id=&#34;dsl&#34;&gt;DSL&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#dsl&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h3 id=&#34;features-of-associative-memory&#34;&gt;Features of associative memory&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#features-of-associative-memory&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; + &lt;h3 id=&#34;features-of-associative-memory&#34;&gt;Features of associative memory&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#features-of-associative-memory&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;The syntax of the &lt;em&gt;NewLang&lt;/em&gt; language is based on strict rules without the use of keywords, and no matter how logical it may seem, association by keywords is much easier to remember, for example, &lt;strong&gt;if&lt;/strong&gt;, than the combination &lt;em&gt;minus minus right angle bracket&lt;/em&gt; &lt;strong&gt;&amp;ndash;&amp;gt;&lt;/strong&gt;. Because of this, it makes sense to use not a &amp;ldquo;pure&amp;rdquo; basic syntax, but a more familiar dialect with the use of keywords.&lt;/p&gt; -&lt;h3 id=&#34;syntax-based-on-keywords&#34;&gt;Syntax based on keywords&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#syntax-based-on-keywords&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;In the dsl.nlp file, there is a set of macros that expand the basic syntax of &lt;em&gt;NewLang&lt;/em&gt;, based on rules, -with a set of predefined keywords as in classical programming languages. -And if necessary, they can be adapted or supplemented for your own domain.&lt;/p&gt; -&lt;h2 id=&#34;константы&#34;&gt;Константы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%ba%d0%be%d0%bd%d1%81%d1%82%d0%b0%d0%bd%d1%82%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h3 id=&#34;логические&#34;&gt;Логические&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bb%d0%be%d0%b3%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; +&lt;p&gt;&lt;em&gt;NewLang&lt;/em&gt; already contains a set of macros that extend the basic rule-based syntax of &lt;em&gt;NewLang&lt;/em&gt;, +a set of predefined keywords as in classical programming languages, +which can be adapted or supplemented to suit your own subject area.&lt;/p&gt; +&lt;h3 id=&#34;constants&#34;&gt;Constants&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#constants&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; -&lt;li&gt;&lt;strong&gt;true&lt;/strong&gt; - 1&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;yes&lt;/strong&gt; - 1&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;false&lt;/strong&gt; - 0&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;no&lt;/strong&gt; - 0&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@true&lt;/em&gt; - 1&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@yes&lt;/em&gt; - 1&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@false&lt;/em&gt; - 0&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@no&lt;/em&gt; - 0&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@this&lt;/em&gt; или &lt;em&gt;@self&lt;/em&gt; - Current object&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@super&lt;/em&gt; - Parent object&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@latter&lt;/em&gt; or &lt;em&gt;@last&lt;/em&gt;- Result of the last operation&lt;/p&gt; +&lt;/li&gt; &lt;/ul&gt; -&lt;h3 id=&#34;системные-имена&#34;&gt;Системные имена&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%8b%d0%b5-%d0%b8%d0%bc%d0%b5%d0%bd%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; +&lt;h3 id=&#34;logical-operators&#34;&gt;Logical operators&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#logical-operators&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; -&lt;li&gt;&lt;strong&gt;this&lt;/strong&gt; - Текущий объект (&lt;strong&gt;$0&lt;/strong&gt;)&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;parent&lt;/strong&gt; - Родительский объект (&lt;strong&gt;$$&lt;/strong&gt;)&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;last&lt;/strong&gt; - Результат выполнения последнего оператора (&lt;strong&gt;$^&lt;/strong&gt;)&lt;/li&gt; +&lt;li&gt;&lt;em&gt;@and&lt;/em&gt; - Logical &lt;strong&gt;AND&lt;/strong&gt;&lt;/li&gt; +&lt;li&gt;&lt;em&gt;@or&lt;/em&gt; - Logical &lt;strong&gt;OR&lt;/strong&gt;&lt;/li&gt; +&lt;li&gt;&lt;em&gt;@xor&lt;/em&gt; - Logical &lt;strong&gt;Exclusive OR&lt;/strong&gt;&lt;/li&gt; +&lt;li&gt;&lt;em&gt;@not(value)&lt;/em&gt; - Logical negation&lt;/li&gt; &lt;/ul&gt; -&lt;p&gt;!!!!!!!!- &lt;strong&gt;args&lt;/strong&gt; - Все аргументы функции (&lt;strong&gt;$*&lt;/strong&gt;)&lt;/p&gt; -&lt;p&gt;!!!!!!!!- &lt;strong&gt;sys&lt;/strong&gt; - Системный контекст запущенной программы (&lt;strong&gt;@@&lt;/strong&gt;) -!!!!!!!!- &lt;strong&gt;current&lt;/strong&gt; - Текущий модуль (&lt;strong&gt;@$&lt;/strong&gt;) -!!!!!!!!- &lt;strong&gt;cmd&lt;/strong&gt; - Все аргументы выполняющегося приложения из командной строки (&lt;strong&gt;@*&lt;/strong&gt;)&lt;/p&gt; -&lt;p&gt;!!!!!!!!!!1### Типовые функции и проверки -!!!!!!!!!!- &lt;strong&gt;run(&amp;lsquo;filename&amp;rsquo;)&lt;/strong&gt; - Выполнить указанный файл (&lt;strong&gt;@@(&amp;lsquo;filename&amp;rsquo;)&lt;/strong&gt;) -!!!!!!!!!!- &lt;strong&gt;ifmain&lt;/strong&gt; - Проверка, если текущий модуль основной (&lt;strong&gt;[@$.$0] &amp;ndash;&amp;gt;&lt;/strong&gt; { &amp;hellip; }) -!!!!!!!!!!- &lt;strong&gt;ifload&lt;/strong&gt; - Проверка, если текущий модуль загружается впервые (&lt;strong&gt;[@$.&lt;strong&gt;load&lt;/strong&gt;] &amp;ndash;&amp;gt;&lt;/strong&gt; { &amp;hellip; })&lt;/p&gt; -&lt;h3 id=&#34;операторы&#34;&gt;Операторы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; +&lt;h3 id=&#34;operators&#34;&gt;Operators&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#operators&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;match(cond)&lt;/strong&gt; - Оператор &lt;a href=&#34;https://newlang.net/ops.html#%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B0-%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&#34;&gt;оценки выражения&lt;/a&gt;&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@if(&amp;hellip;)&lt;/em&gt; - First conditional statement&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;if(&amp;hellip;)&lt;/strong&gt; - Первый условный оператор (&lt;strong&gt;[$*]&amp;ndash;&amp;gt;&lt;/strong&gt; { &amp;hellip; })&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@elif(&amp;hellip;)&lt;/em&gt; - Second and all subsequent conditional statements&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;elif(&amp;hellip;)&lt;/strong&gt; - Второй и все последующие (&lt;strong&gt;,[$*]&amp;ndash;&amp;gt;&lt;/strong&gt; { &amp;hellip; })&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@else&lt;/em&gt; - Operator &lt;em&gt;otherwise&lt;/em&gt;&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;else&lt;/strong&gt; - Оператор &lt;em&gt;иначе&lt;/em&gt; (&lt;strong&gt;,[_]&amp;ndash;&amp;gt;&lt;/strong&gt; { &amp;hellip; })&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@while(&amp;hellip;)&lt;/em&gt; - Loop operator with precondition&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;while(cond)&lt;/strong&gt; - Оператор цикла с предусловием (&lt;strong&gt;[@$cond] &amp;lt;-&amp;gt;&lt;/strong&gt; { &amp;hellip; } )&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@dowhile(&amp;hellip;)&lt;/em&gt; - Loop operator with postcondition&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;dowhile(cond)&lt;/strong&gt; - Оператор цикла с постусловием ({ &amp;hellip; } &lt;strong&gt;&amp;lt;-&amp;gt;[@$cond]&lt;/strong&gt;)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@loop&lt;/em&gt; - Infinite loop operator&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;iter(obj, &amp;hellip; )&lt;/strong&gt; - Создание итератора ( &lt;strong&gt;@$obj&lt;/strong&gt; ? (@$*) )&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@break $label&lt;/em&gt; - Operator to break out of a named named block of code&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;next(obj, &amp;hellip; )&lt;/strong&gt; - Следующий элемент итератора ( &lt;strong&gt;@$obj&lt;/strong&gt; ! ($*) )&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@continue $label&lt;/em&gt; - Jump operator to the beginning of a named block of code&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;curr(obj, &amp;hellip; )&lt;/strong&gt; - Текущий элемент итератора ( &lt;strong&gt;@$obj&lt;/strong&gt; !? ($*) )&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@return( result )&lt;/em&gt; - Operator for returning a value and exiting a function&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;first(obj)&lt;/strong&gt; - Перейти на первый элемент итератора ( &lt;strong&gt;@$obj&lt;/strong&gt; !! )&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@throw( error )&lt;/em&gt; - Operator for creating an exception and returning an error&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;all(obj)&lt;/strong&gt; - Получить сразу все элементы итератора ( &lt;strong&gt;@$obj&lt;/strong&gt; ??)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@match( &amp;hellip; )&lt;/em&gt; - Expression evaluation operator&lt;/p&gt; &lt;/li&gt; -&lt;/ul&gt; -&lt;h3 id=&#34;прерывания&#34;&gt;Прерывания&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b5%d1%80%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;ul&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;return&lt;/strong&gt; - Положительное прерывание (&lt;strong&gt;++&lt;/strong&gt;)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@case( &amp;hellip; )&lt;/em&gt; - Pattern comparison operator&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;return(&amp;hellip;)&lt;/strong&gt;- Положительное прерывание с возвратом значения (&lt;strong&gt;++&lt;/strong&gt; @$value &lt;strong&gt;++&lt;/strong&gt;)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@default&lt;/em&gt; - Selection operator&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;error&lt;/strong&gt; - Отрицательное прерывание (&lt;strong&gt;--&lt;/strong&gt;)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@iter(obj, &amp;hellip; )&lt;/em&gt; - Creating an iterator&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;error(&amp;hellip;)&lt;/strong&gt; - Отрицательное прерывание с возвратом значения (&lt;strong&gt;--&lt;/strong&gt; @$value &lt;strong&gt;--&lt;/strong&gt;)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@next(obj, &amp;hellip; )&lt;/em&gt; - Get the next element of the iterator&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;break+&lt;/strong&gt; и &lt;strong&gt;break-&lt;/strong&gt; - Выход из цикла:&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@curr(obj, &amp;hellip; )&lt;/em&gt; - Get the current iterator element&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@first(obj)&lt;/em&gt; - Go to the first element of the iterator&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@all(obj)&lt;/em&gt; - Get all elements of the iterator at once&lt;/p&gt; &lt;/li&gt; &lt;/ul&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; while(...) {+ - ++ :Break ++ - +} - while(...) {- - -- :Break -- - -} -&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt; -&lt;li&gt;&lt;strong&gt;continue+&lt;/strong&gt; и &lt;strong&gt;continue-&lt;/strong&gt; - В начало цикла:&lt;/li&gt; -&lt;/ul&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; while(...) {+ - ++ :Continue ++ - +} - while(...) {- - -- :Continue -- - -} -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;obj { -.field = 1; -.prop(); -};&lt;/p&gt; -&lt;p&gt;#Python&lt;/p&gt; -&lt;h1 id=&#34;1-without-using-with-statement&#34;&gt;1) without using with statement&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#1-without-using-with-statement&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;file = open(&amp;lsquo;file_path&amp;rsquo;, &amp;lsquo;w&amp;rsquo;) -file.write(&amp;lsquo;hello world !&amp;rsquo;) -file.close()&lt;/p&gt; -&lt;h1 id=&#34;2-without-using-with-statement&#34;&gt;2) without using with statement&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#2-without-using-with-statement&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;file = open(&amp;lsquo;file_path&amp;rsquo;, &amp;lsquo;w&amp;rsquo;) -try: -file.write(&amp;lsquo;hello world&amp;rsquo;) -finally: -file.close()&lt;/p&gt; -&lt;p&gt;open(&amp;lsquo;file_path&amp;rsquo;, &amp;lsquo;w&amp;rsquo;) { -.write(&amp;lsquo;hello world !&amp;rsquo;); -.close(); -}&lt;/p&gt; -&lt;p&gt;Python3&lt;/p&gt; -&lt;h1 id=&#34;using-with-statement&#34;&gt;using with statement&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#using-with-statement&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;with open(&amp;lsquo;file_path&amp;rsquo;, &amp;lsquo;w&amp;rsquo;) as file: -file.write(&amp;lsquo;hello world !&amp;rsquo;)&lt;/p&gt; -&lt;h1 id=&#34;a-simple-file-writer-object&#34;&gt;a simple file writer object&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#a-simple-file-writer-object&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;class MessageWriter(object): -def &lt;strong&gt;init&lt;/strong&gt;(self, file_name): -self.file_name = file_name&lt;/p&gt; -&lt;pre&gt;&lt;code&gt;def __enter__(self): - self.file = open(self.file_name, &#39;w&#39;) - return self.file - -def __exit__(self, *args): - self.file.close() -&lt;/code&gt;&lt;/pre&gt; -&lt;h1 id=&#34;using-with-statement-with-messagewriter&#34;&gt;using with statement with MessageWriter&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#using-with-statement-with-messagewriter&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;with MessageWriter(&amp;lsquo;my_file.txt&amp;rsquo;) as xfile: -xfile.write(&amp;lsquo;hello world&amp;rsquo;)&lt;/p&gt; -&lt;h1 id=&#34;a-simple-file-writer-object-1&#34;&gt;a simple file writer object&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#a-simple-file-writer-object-1&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;:MessageWriter { -def &lt;strong&gt;init&lt;/strong&gt;(self, file_name): -self.file_name = file_name&lt;/p&gt; -&lt;pre&gt;&lt;code&gt;def __enter__(self): - self.file = open(self.file_name, &#39;w&#39;) - return self.file - -def __exit__(self, *args): - self.file.close() -&lt;/code&gt;&lt;/pre&gt; -&lt;p&gt;}&lt;/p&gt; -&lt;h1 id=&#34;using-with-statement-with-messagewriter-1&#34;&gt;using with statement with MessageWriter&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#using-with-statement-with-messagewriter-1&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;MessageWriter(&amp;lsquo;my_file.txt&amp;rsquo;) { -.write(&amp;lsquo;hello world&amp;rsquo;); -};&lt;/p&gt; -&lt;p&gt;from contextlib import contextmanager&lt;/p&gt; -&lt;p&gt;class MessageWriter(object): -def &lt;strong&gt;init&lt;/strong&gt;(self, filename): -self.file_name = filename&lt;/p&gt; -&lt;pre&gt;&lt;code&gt;@contextmanager -def open_file(self): - try: - file = open(self.file_name, &#39;w&#39;) - yield file - finally: - file.close() -&lt;/code&gt;&lt;/pre&gt; -&lt;h1 id=&#34;usage&#34;&gt;usage&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#usage&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;message_writer = MessageWriter(&amp;lsquo;hello.txt&amp;rsquo;) -with message_writer.open_file() as my_file: -my_file.write(&amp;lsquo;hello world&amp;rsquo;)&lt;/p&gt; -&lt;p&gt;:MessageWriter(object) { -def &lt;strong&gt;init&lt;/strong&gt;(self, filename): -self.file_name = filename&lt;/p&gt; -&lt;pre&gt;&lt;code&gt;@contextmanager -def open_file(self): - try: - file = open(self.file_name, &#39;w&#39;) - yield file - finally: - file.close() -&lt;/code&gt;&lt;/pre&gt; -&lt;p&gt;}&lt;/p&gt; -&lt;h1 id=&#34;usage-1&#34;&gt;usage&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#usage-1&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;message_writer = MessageWriter(&amp;lsquo;hello.txt&amp;rsquo;) -with message_writer.open_file() as my_file: -my_file.write(&amp;lsquo;hello world&amp;rsquo;)&lt;/p&gt; -&lt;h1 id=&#34;приложения&#34;&gt;Приложения&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b8%d0%bb%d0%be%d0%b6%d0%b5%d0%bd%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;h2 id=&#34;предопределенные-макросы&#34;&gt;Предопределенные макросы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b5%d0%b4%d0%be%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%bd%d1%8b%d0%b5-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;При работе парсера &lt;em&gt;NewLang&lt;/em&gt; автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. -Данные предопределенные макросы можно использовать как обычные константы.&lt;/p&gt; +&lt;h2 id=&#34;predefined-macros&#34;&gt;Predefined macros&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#predefined-macros&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; +&lt;p&gt;When the &lt;em&gt;NewLang&lt;/em&gt; parser is running, several reserved macros are automatically generated, +some of which correspond to preprocessor macros in C/C++. +These predefined macros can be used as regular constants.&lt;/p&gt; &lt;ul&gt; &lt;li&gt; -&lt;p&gt;__FILE__ или __FILE_NAME__ - имя и полный путь текущего файла&lt;/p&gt; +&lt;p&gt;__FILE__ or __FILE_NAME__ - name and full path of the current file&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__LINE__ или __FILE_LINE__ - содержит номер текущей строки в файле&lt;/p&gt; +&lt;p&gt;__LINE__ or __FILE_LINE__ - contains the number of the current line in the file&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__FILE_TIMESTAMP__ - дату и время последней модификации текущего файла в строковом представлении&lt;/p&gt; +&lt;p&gt;__FILE_TIMESTAMP__ - date and time of the last modification of the current file in string representation&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__FILE_MD5__ - md5 хеш текущего файла в строковом виде&lt;/p&gt; +&lt;p&gt;__FILE_MD5__ - md5 hash of the current file in string form&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__COUNTER__ - целочисленный счетчик, который увеличивает свое значение при каждом обращении&lt;/p&gt; +&lt;p&gt;__COUNTER__ - an integer counter that increases its value with each access&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__DATE__ - дата начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)&lt;/p&gt; +&lt;p&gt;__DATE__ - start date of the compiler launch (has the same value for all processed files)&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__TIME__ - время начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)&lt;/p&gt; +&lt;p&gt;__TIME__ - start time of the compiler launch (has the same value for all processed files)&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__TIMESTAMP__ - дату и время начала запуска компилятора (например: &amp;ldquo;Fri 19 Aug 13:32:58 2016&amp;rdquo;)&lt;/p&gt; +&lt;p&gt;__TIMESTAMP__ - date and time when the compiler started running (for example: &amp;ldquo;Fri 19 Aug 13:32:58 2016&amp;rdquo;)&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__TIMESTAMP_ISO__ - дату и время начала запуска компилятора в формате ISO (например: &amp;ldquo;2013-07-06T00:50:06Z&amp;rdquo;)&lt;/p&gt; +&lt;p&gt;__TIMESTAMP_ISO__ - date and time when the compiler started running in ISO format (for example: &amp;ldquo;2013-07-06T00:50:06Z&amp;rdquo;)&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__NLC_VER__ - Страшая и младшая версия компилятора NewLang (8 битное число, по 4 бита на цифру)&lt;/p&gt; +&lt;p&gt;__NLC_VER__ - Older and younger version of the NewLang compiler (8-bit number, 4 bits per digit)&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__NLC_DATE_BUILD__ - текстовая строка с датой сборки компилятора NewLang (например, &amp;ldquo;23.06.04 20:51:39&amp;rdquo;)&lt;/p&gt; +&lt;p&gt;__NLC_DATE_BUILD__ - text string with the build date of the NewLang compiler (for example, &amp;ldquo;06/23/04 20:51:39&amp;rdquo;)&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__NLC_SOURCE_GIT__ - текстовая строка с идентификатором исходных файлов NewLang git репозитория, использованных при сборке компилятора (например, &amp;ldquo;v0.3.0-fef8c371&amp;rdquo;)&lt;/p&gt; +&lt;p&gt;__NLC_SOURCE_GIT__ - text string with the identifier of the NewLang git repository source files used to build the compiler (for example, &amp;ldquo;v0.3.0-fef8c371&amp;rdquo;)&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__NLC_SOURCE_BUILD__ - дата сборки и git идентификатор исходных файлов NewLang одной текстовой строкой (например, &amp;ldquo;v0.3.0-fef8c371 23.06.04 20:51:39&amp;rdquo;)&lt;/p&gt; +&lt;p&gt;__NLC_SOURCE_BUILD__ - build date and git identifier of NewLang source files in one text line (for example, &amp;ldquo;v0.3.0-fef8c371 06/23/04 20:51:39&amp;rdquo;)&lt;/p&gt; &lt;/li&gt; &lt;/ul&gt; diff --git a/docs/docs/ops/block/index.html b/docs/docs/ops/block/index.html index 041e3645..d0f4894d 100644 --- a/docs/docs/ops/block/index.html +++ b/docs/docs/ops/block/index.html @@ -144,7 +144,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -175,7 +175,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/ops/compare/index.html b/docs/docs/ops/compare/index.html index 930cf560..4998dae6 100644 --- a/docs/docs/ops/compare/index.html +++ b/docs/docs/ops/compare/index.html @@ -148,7 +148,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -179,7 +179,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/ops/create/index.html b/docs/docs/ops/create/index.html index eb582987..b76f6358 100644 --- a/docs/docs/ops/create/index.html +++ b/docs/docs/ops/create/index.html @@ -144,7 +144,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -175,7 +175,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/ops/if/index.html b/docs/docs/ops/if/index.html index d92dbfa6..37b822db 100644 --- a/docs/docs/ops/if/index.html +++ b/docs/docs/ops/if/index.html @@ -144,7 +144,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -175,7 +175,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/ops/index.html b/docs/docs/ops/index.html index af584f38..873ad8db 100644 --- a/docs/docs/ops/index.html +++ b/docs/docs/ops/index.html @@ -137,7 +137,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -168,7 +168,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/ops/match/index.html b/docs/docs/ops/match/index.html index a84baad1..d2edae05 100644 --- a/docs/docs/ops/match/index.html +++ b/docs/docs/ops/match/index.html @@ -144,7 +144,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -175,7 +175,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/ops/math/index.html b/docs/docs/ops/math/index.html index d876887c..03f3cab6 100644 --- a/docs/docs/ops/math/index.html +++ b/docs/docs/ops/math/index.html @@ -144,7 +144,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -175,7 +175,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/ops/throw/index.html b/docs/docs/ops/throw/index.html index 360d9626..b09cea72 100644 --- a/docs/docs/ops/throw/index.html +++ b/docs/docs/ops/throw/index.html @@ -148,7 +148,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -179,7 +179,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/ops/while/index.html b/docs/docs/ops/while/index.html index 73319097..dbc7cfb6 100644 --- a/docs/docs/ops/while/index.html +++ b/docs/docs/ops/while/index.html @@ -144,7 +144,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -175,7 +175,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/ops/with/index.html b/docs/docs/ops/with/index.html index 78548112..3d4b4180 100644 --- a/docs/docs/ops/with/index.html +++ b/docs/docs/ops/with/index.html @@ -148,7 +148,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -179,7 +179,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/syntax/_print/index.html b/docs/docs/syntax/_print/index.html index 8a7f4847..74a58268 100644 --- a/docs/docs/syntax/_print/index.html +++ b/docs/docs/syntax/_print/index.html @@ -163,7 +163,7 @@ <h1 class="title">Синтаксис</h1> -<li>5: <a href="#pg-66431dc9242fce562d24bb69bdc576f3">Макросы</a></li> +<li>5: <a href="#pg-66431dc9242fce562d24bb69bdc576f3">Macros</a></li> @@ -206,12 +206,12 @@ <h1 class="title">Синтаксис</h1> <div class="content"> <ul> -<li>Операторы разделяются точкой с запятой «;».</li> -<li>Отступы и переводы строк игнорируются.</li> -<li>Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash.</li> -<li>Многострочные комментарии соответствуют стилю С/С++ и должны располагаться между символами /* и */. Многосточные комментарии могут быть вложенными.</li> -<li>Последовательность команд <a href="/docs/ops/block/">(блок кода)</a> заключаются в фигурные скобки &ldquo;<strong>{</strong>&rdquo; и &ldquo;<strong>}</strong>&rdquo;.</li> -<li>Большинство операторов являются выражениями и возвращают результат выполнения последней операции.</li> +<li>Operators are separated by a semicolon &ldquo;;&rdquo;.</li> +<li>Indentations and line breaks are ignored.</li> +<li>Single-line comments start with the symbol &ldquo;#&rdquo; until the end of the line, following the style of Python and Bash comments.</li> +<li>Multi-line comments follow the C/C++ style and should be enclosed between &ldquo;/*&rdquo; and &ldquo;*/&rdquo;. Multi-line comments can be <em>nested</em>.</li> +<li>Command sequences <a href="/docs/ops/block/">(code block)</a> are enclosed in curly braces &ldquo;<strong>{</strong>&rdquo; and &ldquo;<strong>}</strong>&rdquo;.</li> +<li>Most operators are expressions and return the result of the last operation.</li> </ul> </div> @@ -774,425 +774,100 @@ <h3 id="пример-программы">Пример программы<a class <div class="td-content" style="page-break-before: always"> - <h1 id="pg-66431dc9242fce562d24bb69bdc576f3">5 - Макросы</h1> - - <p>Макросы в <strong>NewLang</strong>, это один или несколько последовательных терминов, которые заменяются на другой термин -или на целую синтаксическую конструкцию (последовательность лексем).</p> -<p>Макросы обработываются во время работы <strong>лексера</strong>, т.е. перед передачей последовательности лексем в парсер, -что позволяет с их помощью изменять даже сам синтаксис языка, например, при реализации собственных диалектов DSL.</p> -<h3 id="определение-макросов">Определение макросов<a class="td-heading-self-link" href="#%d0%be%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2" aria-label="Heading self-link"></a></h3> -<p>Определение макросов аналогично <a href="/docs/ops/create/">определению</a> других объектов и состоит из трех частей -<strong>&lt;имя макроса&gt; &lt;оператор создания/присвоения&gt; &lt;тело макроса&gt;</strong> и завершающая точка с запятой &ldquo;<strong>;</strong>&rdquo;, -т.е. применяются обычные операторы <strong>::=</strong>, <strong>=</strong> или <strong>:=</strong> для создания нового или переопределения уже существующего объекта, -а имя макроса указывается между двумя символами <strong>&quot;@@&quot;</strong> и может содержать одну или нескольких лексем (терминов).</p> -<p>Все макросы относятся к глобальному пространству имен, поэтому первый термин в имени макроса должен быть уникальным, -иначе он будет прекрывать имена локальных и глобальных переменных при <a href="/docs/syntax/naming/">разрешении имен</a>, -если они указаны в коде без квалификаторов.</p> -<p>??????????????????????? -Чистые (гигиеничные) макросы, <strong>::-</strong> <strong>:-</strong>, аргумента и переммые в которых гарантиованно не пересекаются с пространством имен программы?????????????????</p> -<p>Телом макроса могут быть корректное выражение языка, последовательность лексем (которые заключается в двойные собачки <strong>&quot;@@&quot;</strong>, -т.е. <strong><code>@@ лексема1 лексема1 @@</code></strong>) или обычная текстовая строка (которую нужно указать между тройными собачками <strong>&quot;@@@&quot;</strong>, т.е. <strong><code>@@@ текстовая строка @@@</code></strong>).</p> -<p>В имени макроса, кроме первого термина, могут присутствовать один или несколько шаблонов. -<em>Шаблон</em> — это термин, который при сопоставлении последовательности лексем с идентификатором макроса -может заменяться любым другим одиночным термином (т.е. фактически это сопоставление по образцу/шаблону).</p> -<p>Для создания термина-шаблона в начале его идентификатора нужно поставить знак доллара (что соответствует квалификатору локальной переменой), -т.е. имя макроса <code>@@ FUNC $name @@</code> будет соответствовать последовательности лексем как <code>FUNC my_func_name</code>, так и <code>FUNC other_name_func</code>.</p> -<p>Для удаления макроса используется специальный синтаксис: <code>@@@@ name @@@@;</code> или <code>@@@@ два термина @@@@;</code>, -т.е. необходимо указать идентификатор макроса между четырмя символами <strong>&quot;@@@@&quot;</strong>.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Тело макроса из текстовой строки (как в препроцессоре С/С++)</span> -</span></span><span style="display:flex;"><span> @@macro_str@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@@ строка - тело макроса @@@<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Строка для лексера</span> + <h1 id="pg-66431dc9242fce562d24bb69bdc576f3">5 - Macros</h1> + + <p>Macros are also used to transform the original code of <em>NewLang</em> into a more familiar syntax based on <a href="/docs/syntax/dsl/">keywords</a>, +as such text is much easier to understand when reading the original code later.</p> +<p>In <strong>NewLang</strong>, macros are one or more consecutive terms that are replaced with another term or a whole syntactic construction (a sequence of lexemes).</p> +<p>Macros are processed during the operation of the <strong>lexer</strong>, i.e., before passing the sequence of lexemes to the parser, +allowing fragments of the language syntax to be modified using macros, for example, when implementing custom DSL dialects.</p> +<h3 id="defining-macros">Defining Macros<a class="td-heading-self-link" href="#defining-macros" aria-label="Heading self-link"></a></h3> +<p>The definition of macros is similar to the <a href="/docs/ops/create/">definition</a> of other objects and consists of three parts +<strong><macro name> &lt;creation/assignment operator&gt; <macro body></strong> and ends with a semicolon &ldquo;<strong>;</strong>&rdquo;, i.e., +normal operators <strong>::=</strong>(<strong>::-</strong>), <strong>=</strong>, or <strong>:=</strong>(<strong>:-</strong>) are used to create a new or redefine an existing object, +and the macro name is indicated between two symbols <strong>&quot;@@&quot;</strong> and can contain one or more lexemes (terms).</p> +<p>All macros belong to the global namespace, so the first term in the macro name must be unique, +otherwise it will override local and global variables during <a href="/docs/syntax/naming/#name-lookup">name lookup</a> +if they are written in the program text without <a href="/docs/syntax/naming/#sigil">qualifiers (sigils)</a>.</p> +<p>Using the operators <strong>::-</strong> and <strong>:-</strong> creates pure (hygienic) macros, arguments and variables in which are guaranteed not to intersect with the program&rsquo;s namespace.</p> +<p>The body of a macro can be a valid language expression, a sequence of lexemes (enclosed in double at symbols <strong>&quot;@@&quot;</strong>, +i.e. <strong><code>@@ lexeme1 lexeme2 @@</code></strong>), or a regular text string (which should be specified between triple at symbols <strong>&quot;@@@&quot;</strong>, +i.e. <strong><code>@@@ text string @@@</code></strong>).</p> +<p>In the macro name after the first term, one or more templates may be present. +A <em>template</em> is a term that, when matching a sequence of lexemes with the macro identifier, +can be replaced by any other single term (effectively, this is pattern/template matching).</p> +<p>To create a template term, a dollar sign should be placed at the beginning of its identifier (which corresponds to a qualifier of a local variable), +i.e. the macro name <code>@@ FUNC $name @@</code> will correspond to the sequence of lexemes as <code>FUNC my_func_name</code> as well as <code>FUNC other_name_func</code>.</p> +<p>To remove a macro, a special syntax is used: <code>@@@@ name @@@@;</code> or <code>@@@@ two terms @@@@;</code>, +i.e. you need to specify the macro identifier between four characters <strong>&quot;@@@@&quot;</strong>.</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Macro body from a text string (as in C/C++ preprocessor)</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#5c35cc;font-weight:bold">@macro_str</span><span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@@</span> <span style="color:#000">string</span> <span style="color:#ce5c00;font-weight:bold">-</span> <span style="color:#000">macro</span> <span style="color:#000">body</span> <span style="color:#ce5c00;font-weight:bold">@@@</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># String for the lexer</span> </span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Удаления макроса @macro_str</span> -</span></span><span style="display:flex;"><span> @@@@ macro_str @@@@<span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><h3 id="аргументы-макросов-и-их-раскрытие">Аргументы макросов и их раскрытие<a class="td-heading-self-link" href="#%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d1%8b-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2-%d0%b8-%d0%b8%d1%85-%d1%80%d0%b0%d1%81%d0%ba%d1%80%d1%8b%d1%82%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> -<p>Макросы можно определять как с аргументами (параметрами в скобках), так и без них. -Если макрос был определен с аргументами, то их проверка будет выполнятся макропроцессором при определении и раскрытии макроса. -Если макрос был определен без аргументов, то их наличие макропроцессором игнорируется.</p> -<p>Так как макропроцессор считает макросы с аргументами и без оных идентичными, то нельзя создать два макроса -с одинаковыми именами, один из которых будет с аргументами (скобками), а другой без них.</p> -<p>Поэтому, если требуется использовать макрос в двух разных вариантах (с аргументами и без них), -тогда следует определять макрос без аргументов и в этом случае контроль параметров будет производить компилятор.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> @@macro@@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Макрос без аргументов</span> +</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Removing macro @macro_str</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@@@</span> <span style="color:#000">macro_str</span> <span style="color:#ce5c00;font-weight:bold">@@@@</span><span style="color:#000;font-weight:bold">;</span> +</span></span></code></pre></div><h3 id="args">Macro Arguments and Expansion<a class="td-heading-self-link" href="#args" aria-label="Heading self-link"></a></h3> +<p>Macros can be defined with arguments (parameters in parentheses) or without them. +If a macro was defined with arguments, their validation will be performed by the macro processor during definition and expansion of the macro. +If a macro was defined without arguments, the presence of arguments will be ignored by the macro processor.</p> +<p>The macroprocessor considers macros with and without arguments identical, +so it is not possible to create two macros with the same name, one with arguments (in parentheses) and the other without.</p> +<p>Therefore, if you need to use a macro in two different ways (with arguments and without), +you should define the macro without arguments, and in this case, the parameter control will be done by the compiler.</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> @@ macro @@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Macro without arguments</span> </span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> macro<span style="color:#ce5c00;font-weight:bold">(</span>args<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># ОК -&gt; term(args);</span> -</span></span><span style="display:flex;"><span> macro<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># ОК -&gt; term;</span> +</span></span><span style="display:flex;"><span> macro<span style="color:#ce5c00;font-weight:bold">(</span>args<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># OK -&gt; term(args);</span> +</span></span><span style="display:flex;"><span> macro<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># OK -&gt; term;</span> </span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Но </span> -</span></span><span style="display:flex;"><span> @@call<span style="color:#ce5c00;font-weight:bold">()</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># But</span> +</span></span><span style="display:flex;"><span> @@ call<span style="color:#ce5c00;font-weight:bold">()</span> @@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> </span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> call<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># ОК -&gt; term();</span> -</span></span><span style="display:flex;"><span> call<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Ошибка (@call определен с аргументами) </span> -</span></span></code></pre></div><p>Если при определении макроса указаны аргументы, то место для их вставки в теле макроса -записывается как имя локальной переменой, перед которой добавлен символ <strong>&quot;@&quot;</strong>, т.е. <strong>@$arg</strong>.</p> -<p>Произвольное количество аргументов у макроса отмечается троеточием <strong>&quot;&hellip;&quot;</strong>, а место для их вставки отмечается в теле макроса лексемой <strong>&quot;@$&hellip;&quot;</strong>.</p> -<p>Место для вставки числа реально переданных аргументов отмечается лексемой <strong>&quot;@$#&quot;</strong>. -Если требуется вставить переданные аргументы в виде элементов словаря, -то место для вставки отмечается лексемой <strong>&quot;@$*&quot;</strong>.</p> -<p>По аналогии с препроцессором С/С++, для соединения двух лексем в одну, в теле макроса используется оператор <strong>&quot;@##&quot;</strong>, -а для преобразование лексемы в текстову строку применяется операторы <strong>@#</strong>, <strong>@#&quot;</strong> или <strong>@#&rsquo;</strong>, например, -<code>@@macro($arg)@@ := @@ func_ @## @$arg( @#&quot; arg ) @;</code>, тогда вызов <code>macro(name);</code> будет преобразован в <code>func_name (&quot;name&quot;);</code></p> - - -<div class="pageinfo pageinfo-primary"> -<h4 id="ограничения-макропроцессора-в-текущей-версии">Ограничения макропроцессора в текущей версии<a class="td-heading-self-link" href="#%d0%be%d0%b3%d1%80%d0%b0%d0%bd%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d0%bf%d1%80%d0%be%d1%86%d0%b5%d1%81%d1%81%d0%be%d1%80%d0%b0-%d0%b2-%d1%82%d0%b5%d0%ba%d1%83%d1%89%d0%b5%d0%b9-%d0%b2%d0%b5%d1%80%d1%81%d0%b8%d0%b8" aria-label="Heading self-link"></a></h4> -<p>На текущий момент макросы реализованы в минимальном объеме для самых простых сценариев использования:</p> -<ul> -<li>DSL для keyword based syntax (if, else, return, match, while и т.д.) - (1 термин с произвольными аргументами и без) - требуется сейчас !!!</li> -</ul> -<p><em>Парсер при обработке макросов может анализировать информацию о типах данных, если она указана.</em> -<em>Но на текущий момент типы данных в макросах никак не обрабатываются и это одна из обязательных фич, которая будет реализована в будущем.</em></p> -<ul> -<li>Определения (func, class) - (несколько терминов с аргументами и без аргументов) - Реализация ООП и импорт С++ классов</li> -<li>Модификации при определениях (override) - (несколько терминов и шаблоны с аргументами и без аргументов) - Реализация ООП и импорт С++ классов</li> -</ul> - -</div> - -<h1 id="макросы-без-аргументов-или-все-аргументы-сразу-">МАКРОСЫ БЕЗ АРГУМЕНТОВ ИЛИ ВСЕ АРГУМЕНТЫ СРАЗУ !!!!!<a class="td-heading-self-link" href="#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b1%d0%b5%d0%b7-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d0%b8%d0%bb%d0%b8-%d0%b2%d1%81%d0%b5-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d1%8b-%d1%81%d1%80%d0%b0%d0%b7%d1%83-" aria-label="Heading self-link"></a></h1> -<h1 id="анализа-аргументов-или-их-типов-не-производится-">анализа аргументов или их типов не производится !!!<a class="td-heading-self-link" href="#%d0%b0%d0%bd%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d0%b8%d0%bb%d0%b8-%d0%b8%d1%85-%d1%82%d0%b8%d0%bf%d0%be%d0%b2-%d0%bd%d0%b5-%d0%bf%d1%80%d0%be%d0%b8%d0%b7%d0%b2%d0%be%d0%b4%d0%b8%d1%82%d1%81%d1%8f-" aria-label="Heading self-link"></a></h1> -<p>Lambda -@@ lambda $name(&hellip;) @@ ::= @@ @$name( @$&hellip; ) ::= ( _( @$&hellip; ) ::= @<strong>PRAGMA_FINALIZE</strong>( @), {, {+, {-, {* ) @@</p> -<h3 id="примеры-использования-макросов">Примеры использования макросов<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80%d1%8b-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2" aria-label="Heading self-link"></a></h3> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Обычные макросы (тело макроса корректное выражение)</span> -</span></span><span style="display:flex;"><span> @@macro@@ :<span style="color:#ce5c00;font-weight:bold">=</span> replace<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@macro2<span style="color:#ce5c00;font-weight:bold">(</span>arg<span style="color:#ce5c00;font-weight:bold">)</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">{</span> call<span style="color:#ce5c00;font-weight:bold">(</span>@<span style="color:#000">$arg</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> call<span style="color:#ce5c00;font-weight:bold">()}</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> call<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># OK -&gt; term();</span> +</span></span><span style="display:flex;"><span> call<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Error (@call is defined with arguments) </span> +</span></span></code></pre></div><p>If arguments are specified when defining a macro, the place for their insertion in the body of the macro is written +as the name of a local variable with the symbol <strong>&quot;@&quot;</strong> added before it, i.e. <strong>@$arg</strong>.</p> +<p>The place for inserting the number of actual arguments passed is marked by the lexeme <strong>&quot;@$#&quot;</strong>. +If it is necessary to insert the passed arguments as a dictionary, the place for insertion is marked by the lexeme <strong>&quot;@$*&quot;</strong>.</p> +<p>If the macro takes an arbitrary number of arguments (the macro arguments are terminated by an ellipsis), +the place for their insertion in the body of the macro is marked by the lexeme <strong>&quot;@$&hellip;&quot;</strong>.</p> +<p>Analogous to the C/C++ preprocessor, to concatenate two lexemes into one, the operator <strong>&quot;@##&quot;</strong> is used in the body of the macro, +and to convert a lexeme into a text string, the operators <strong>@#</strong>, <strong>@#&quot;</strong>, or <strong>@#&rsquo;</strong> are applied, for example, +<code>@@macro($arg)@@ := @@ func_ @## @$arg( @#&quot; arg ) @;</code>, then the call <code>macro(name);</code> will be transformed into <code>func_name (&quot;name&quot;);</code></p> +<p>Examples of using macros:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Ordinary macros (the body of the macro is a correct expression)</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000">macro</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000">replace</span><span style="color:#000;font-weight:bold">();</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000">macro2</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">arg</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000;font-weight:bold">{</span> <span style="color:#000">call</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#a40000">$</span><span style="color:#000">arg</span><span style="color:#000;font-weight:bold">);</span> <span style="color:#000">call</span><span style="color:#000;font-weight:bold">()};</span> </span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Тело макросов из последовательности лексем</span> -</span></span><span style="display:flex;"><span> @@if<span style="color:#ce5c00;font-weight:bold">(</span>...<span style="color:#ce5c00;font-weight:bold">)</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ <span style="color:#ce5c00;font-weight:bold">[</span> <span style="color:#4e9a06">\$</span><span style="color:#204a87;font-weight:bold">if</span><span style="color:#ce5c00;font-weight:bold">(</span>*<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">]</span>--&gt; @@<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Выражение может быть не полным</span> -</span></span><span style="display:flex;"><span> @@elif<span style="color:#ce5c00;font-weight:bold">(</span>...<span style="color:#ce5c00;font-weight:bold">)</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ ,<span style="color:#ce5c00;font-weight:bold">[</span> <span style="color:#4e9a06">\$</span><span style="color:#204a87;font-weight:bold">elif</span><span style="color:#ce5c00;font-weight:bold">(</span>*<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">]</span>--&gt; @@<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@else@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ ,<span style="color:#ce5c00;font-weight:bold">[</span>_<span style="color:#ce5c00;font-weight:bold">]</span>--&gt; @@<span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># The body of the macros from a sequence of tokens</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#204a87;font-weight:bold">if</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000;font-weight:bold">[</span> <span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#a40000">$</span><span style="color:#ce5c00;font-weight:bold">...</span> <span style="color:#000;font-weight:bold">]</span><span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#ce5c00;font-weight:bold">@@</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># The expression may not be complete</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#204a87;font-weight:bold">elif</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000;font-weight:bold">,[</span> <span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#a40000">$</span><span style="color:#ce5c00;font-weight:bold">...</span> <span style="color:#000;font-weight:bold">]</span><span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#ce5c00;font-weight:bold">@@</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000;font-weight:bold">,[</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">]</span><span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#ce5c00;font-weight:bold">@@</span><span style="color:#000;font-weight:bold">;</span> </span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Запись условного оператора с использованием </span> -</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># определенных выше макросов</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">if</span><span style="color:#ce5c00;font-weight:bold">(</span> condition <span style="color:#ce5c00;font-weight:bold">){</span> -</span></span><span style="display:flex;"><span> ... -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">elif</span><span style="color:#ce5c00;font-weight:bold">(</span> condition2 <span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> ... -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#ce5c00;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> ... -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>Зачем нужна трансформация синтаксиса? -Нативная поддержка других языков нужна чтобы не переписывать легаси код на этих языках.</p> -<p>Чтобы можно было использовать существующие исходники как собственные требуется настройка работы -препроцессора и лексера под конкретный язык программирования (описание DSL). -Для <strong>С/С++</strong> потребуется выделять лексером комментарии из-за пересечения синтаксиса (которые сейчас игнорируются). -Для <strong>Python</strong> требуется выделять лексером отступы (которые сейчас тоже игнорируются), причем потребуется реализация не только синтаксиса, -но и зависимых пакетов с последующая трансляцией этого кода в С++, что в настоящий момент делать не целесообразно (cython ???).</p> -<p>Но так как возможность трансформации кода с других языков программирования принципиальная возможна, -стоит над этим думать только после полноценного релиза NewLang и его перехода в прод.</p> -<p>Для реализации DSL требуется передача команд в парсер для управления его работой (по аналогии с командой #pragma) -Но так как обработка таких команд должна происходить в лексере до передачи данных в парсер (анализатор), -то команды для макропроцессора должны быть в максимально простом виде и состоять из элементов, -которые лексер может самостоятельно идентифицировать, т.е. термины, строки и цифры (без выражений и именованных аргументов).</p> -<p>После обработки такой команды она анализируется макропроцессором и удаляется из потока лексем, т.е. в парсер (анализатор) не передается. -Но в случае ошибки с синтаксисе, данные команды нужно уметь однозначно идентифировать и самый простой способ, -комбинация признака макроса и системного имени, т.е. что-то вроде</p> -<pre tabindex="0"><code> @__PRAGMA_DIAG__(push) - @__PRAGMA_DIAG__(ignored, &#34;-Wundef&#34;) - @__PRAGMA_DIAG__(warning, &#34;-Wformat&#34;) - @__PRAGMA_DIAG__(error &#34;-Wuninitialized&#34;) - @__PRAGMA_DIAG__(pop) - - #pragma message &#34;Compiling &#34; __FILE__ &#34;...&#34; - @__PRAGMA_MESSAGE__(&#34;Compiling &#34;, __FILE__, &#34;...&#34;) - - #pragma error &#34;Error &#34; __FILE__ &#34;...&#34; - @__PRAGMA_ERROR__(&#34;Error &#34;, __FILE__, &#34;...&#34;) - - -#define DO_PRAGMA(x) _Pragma (#x) -#define TODO(x) DO_PRAGMA(message (&#34;TODO - &#34; #x)) - -@@TODO( ... )@@ := @__PRAGMA_MESSAGE__(&#34;TODO - &#34;, @*) - -@TODO(Remember to fix this) # note: TODO - Remember to fix this - -\\.__lexer__ignore_space__ = 1; -\\.__lexer__ignore_indent__ = 1; -\\.__lexer__ignore_comment__ = 1; -\\.__lexer__ignore_crlf__ = 1; -</code></pre><p>Таким образом можно трансформировать условный оператор на питоне в синтаксис NewLang следующим макросом:</p> -<pre tabindex="0"><code> -#pragma clang attribute push -#pragma clang diagnostic ignored &#34;-Wundef&#34; -#pragma clang diagnostic ignored &#34;-Wunused-variable&#34; - - -#elif __GNUC__ - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored &#34;-Wuninitialized&#34; - -#pragma GCC diagnostic ignored &#34;-Wall&#34; -#pragma GCC diagnostic ignored &#34;-Wextra&#34; - - @pragma warning(pop) - - @@ pragma warning(...) @@ := __PRAGMA_TERM_DIAG_WARNING__(); -@__PRAGMA_DIAG__(warning, pop); - -Обработка терминов в макропроцессоре в максимально простом виде. -Агрументы только термины, строки и цифры без вложенных выражений и именованных аргументов, -т.е. только элементы, которые может самостоятельно идентифицировать лексер. - -@warning(&#34;--&#34;) - @@ if ... : @@ := @@ [ @$* ]-&gt; __TERM_BLOCK_INDENT__(&#34;{&#34;, force_semicolon=1) @@ - - if __name__ == &#34;__main__&#34;: - run1() - run2() - - [ __name__ == &#34;__main__&#34; ]-&gt; { - run1(); - run2(); - }; - - -</code></pre><p>Ключ &ndash;parser-syntax-only только текстовый парсинг исходного кода без загрузки модулей, раскрытия макросов и проверки имен.</p> -<p>Ключ &ndash;parser-no-macros - без раскрытия макросов -Ключ &ndash;parser-no-module - без загрузки модулей (и мокросов, если они в них определяются) -Ключ &ndash;parser-no-check-prototype - без проверки имен при обращении</p> -<p>prototype -@<strong>PRAGMA_PROTOTYPE</strong>(define) -@<strong>PRAGMA_PROTOTYPE</strong>(implement)</p> -<p>$$</p> -<p>\$ - корень системы (система)</p> -<p>$ - текущий модуль</p> -<h1 id="макросы-для-конвертора-проверки-в-python">Макросы для конвертора проверки в Python<a class="td-heading-self-link" href="#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b4%d0%bb%d1%8f-%d0%ba%d0%be%d0%bd%d0%b2%d0%b5%d1%80%d1%82%d0%be%d1%80%d0%b0-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b8-%d0%b2-python" aria-label="Heading self-link"></a></h1> -<h1 id="if-__name__--__main__">if <strong>name</strong> == &ldquo;<strong>main</strong>&rdquo;:<a class="td-heading-self-link" href="#if-__name__--__main__" aria-label="Heading self-link"></a></h1> -<p>@@ <strong>name</strong> @@ ::= @@ $. @<strong>PRAGMA_NO_MACRO</strong>() <strong>name</strong> @@ -@@ if $&hellip; @: @@ ::= @@ [ @$&hellip; ] &ndash;&gt; @@</p> -<p>@if( $.<strong>name</strong> == &ldquo;<strong>main</strong>&rdquo; ) {</p> -<p>}</p> -<p>\каталог\модуль() - статический импорт модуля -\(&ldquo;каталог\модуль&rdquo;)() - динамический импорт модуля</p> -<p>printf := :Pointer(&lsquo;printf(format:FmtChar, &hellip;):Int32&rsquo;); -printf := %printf(format:FmtChar, &hellip;):Int32;</p> -<h1 id="регистрация-прототипа-нативной-функции">Регистрация прототипа нативной функции<a class="td-heading-self-link" href="#%d1%80%d0%b5%d0%b3%d0%b8%d1%81%d1%82%d1%80%d0%b0%d1%86%d0%b8%d1%8f-%d0%bf%d1%80%d0%be%d1%82%d0%be%d1%82%d0%b8%d0%bf%d0%b0-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h1> -<p>@prototype -%puts(format:StrChar):Int32;</p> -<h1 id="импорт-нативной-функции-с-предварительной-проверкой-её-наличия-во-время-компиляции-статическая-линковка">Импорт нативной функции с предварительной проверкой её наличия во время компиляции (статическая линковка)<a class="td-heading-self-link" href="#%d0%b8%d0%bc%d0%bf%d0%be%d1%80%d1%82-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d1%81-%d0%bf%d1%80%d0%b5%d0%b4%d0%b2%d0%b0%d1%80%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d0%be%d0%b9-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%be%d0%b9-%d0%b5%d1%91-%d0%bd%d0%b0%d0%bb%d0%b8%d1%87%d0%b8%d1%8f-%d0%b2%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d1%8f-%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%86%d0%b8%d0%b8-%d1%81%d1%82%d0%b0%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bb%d0%b8%d0%bd%d0%ba%d0%be%d0%b2%d0%ba%d0%b0" aria-label="Heading self-link"></a></h1> -<p>puts2(format:StrChar):Int32 := %puts(format:StrChar):Int32;</p> -<h1 id="импорт-нативной-функции-по-её-прототипу-во-время-выполнения-динамическая-линковка">Импорт нативной функции по её прототипу во время выполнения (динамическая линковка)<a class="td-heading-self-link" href="#%d0%b8%d0%bc%d0%bf%d0%be%d1%80%d1%82-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d0%bf%d0%be-%d0%b5%d1%91-%d0%bf%d1%80%d0%be%d1%82%d0%be%d1%82%d0%b8%d0%bf%d1%83-%d0%b2%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d1%8f-%d0%b2%d1%8b%d0%bf%d0%be%d0%bb%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b4%d0%b8%d0%bd%d0%b0%d0%bc%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bb%d0%b8%d0%bd%d0%ba%d0%be%d0%b2%d0%ba%d0%b0" aria-label="Heading self-link"></a></h1> -<p>puts3(format:StrChar):Int32 := :Pointer(&lsquo;puts(format:StrChar):Int32&rsquo;);</p> -<p>%puts(&lsquo;Тест вывода строки&rsquo;); # Линковка с нативной функцией во время компиляции и непосредственный вызов с оптимизацией передачи параметров -puts2(&lsquo;Тест 2 вывода строки&rsquo;); # Линковка с нативной функцией во время компиляции -puts3(&lsquo;Тест 3 вывода строки&rsquo;); # Линковка с нативной функцией во время выполнения при первом вызове puts3</p> -<ul> -<li>Парсинг исходного текста без раскрытия макросов и загрузки модулей</li> -<li>Парсинг исходного текста с раскрытием макросов (требуется загрузка модулей для зависимых и переопределяемых макросов)</li> -<li>Загружатся модули могут как в виде исходников (которые требуется парсить и компилировть/выполнять) -или в виде бинарников (в них должны быть список макросов, типов и имена объектов)</li> -<li>После парсинга получается список <strong>имен</strong> макросов, типов и объектов (TermPtr)</li> -<li>После выполнения модуля - список <strong>имен</strong> заполняется реальными объектами (ObjPtr).</li> -</ul> -<h1 id="компиляция-файла">Компиляция файла<a class="td-heading-self-link" href="#%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%86%d0%b8%d1%8f-%d1%84%d0%b0%d0%b9%d0%bb%d0%b0" aria-label="Heading self-link"></a></h1> -<ul> -<li>Парсинг исходника для построения AST (без анализа имен, связей, загрузки модулей и пр. только исходые тексты с раскрытием макросов</li> -<li></li> -</ul> -<h1 id="систематизация-реализации-макросов">Систематизация реализации макросов<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0%d1%82%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d1%80%d0%b5%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d0%b8-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2" aria-label="Heading self-link"></a></h1> -<p>последовательность лексем MACRO_SEQ мужду @@ @@ сохраняется в m_block, так как фрагменты блоков не могут быть идентификаторами</p> -<p>Разбор макросов происходит в лексере. Определением макроса всегда является целая строка, -которая заканчивается точкой с запятой, а идентификатором макроса всегда выступает последовательность лексем:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> @@ id @@ :<span style="color:#ce5c00;font-weight:bold">=</span> macro<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@ id @@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ @@<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@ id @@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@@ @@@<span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>Хранилищем текущих максросов является объект класса MacroBuffer. -Последовательность лексем идентификатора (id) макроса должна сохраняется в отдельном поле термина и однозначно его идентифицирует. -Первый термин в идентификаторе хранится как ключ hashmap, а дальше происходит поиск полным перебором. -Этапы работы с макросами</p> -<ul> -<li> -<p>Входные термины из лексера получаются вызовом GetNextToken, внутри которой и происходит раскрытие макросов. -Внутренний буфер заполняется до окончания строки (выражения), т.е. до символа &lsquo;;&rsquo; или <END>, после чего производится -поиск макросов в объекте MacroBuffer для текущей последовательности лексем в буфере.</p> -</li> -<li> -<p>Если макрос найден, то соответствющая ему последоваетльность заменяется на тело макроса и происходит переход -на повторный анализ входного буфера.</p> -</li> -<li> -<p>Если макрос не найден, то данные передаются в парсер для дальнейшего синтаксическго анализа.</p> -</li> -<li> -<p>Для этого во входном потоке лексем (parser.y) во время оператората создания/присвоения вызывается функция проверки на макрос. -MacroBuffer::CheckMacroAndConvertDel($$), и после этого выходному значению присваивается результат выполнения driver.MacroEval($$), -и в дальнейшем этот макрос никак не обработывается.</p> -</li> -<li> -<p>Создание макросов, проверка на дубликаты и логические ошибки в определении происходит путем обращения к методам объекта MacroBuffer.</p> -<p>/*</p> -<ul> -<li>Макросы хрянтся как фрагменты AST в виде объектов типа Term,</li> -<li>так как создаются после обработки парсером по правилам стандратной грамматики.</li> -<li></li> -<li>Но анализ входных данных на предмет раскрытия макросов проиходит из потока (последовательности) лексем,</li> -<li>т.е. <strong>ДО</strong> обработки парсером, так как при раскрытии макросов может меняться грамматика выражений.</li> -<li></li> -<li>Функция \ref CompareMacro сравнивает входной буфер (последовательность лексем)</li> -<li>на предмет возможного соответствия одному конкретному макросу.</li> -<li>Сравниваются только ключевые словам без учета аргументов в скобках,</li> -<li>но само наличие аргументов проверяется ??????????????????</li> -<li></li> -<li>Проблема:</li> -<li>К функции можно обратится с целью её вызова (указав после имени скобки),</li> -<li>так и по имени без скобок (например для получения ссылки на объект).</li> -<li>Так и к переменной можно обратиться только по имени,</li> -<li>так и указав скобки после имени как к функции (при копировании объекта).</li> -<li></li> -<li>Сделать один макрос под оба сценария (со скобками и без скобок) не получится, так как непонятно,</li> -<li>что делать с аргументами при раскрытии тела макроса, когда они не указаны.</li> -<li></li> -<li>Но может быть следует переименовывать только одно имя без учета скобок,</li> -<li>например, оставив такую возможность только для одиночных макросов.</li> -<li></li> -<li>\name -&gt; name или name (&hellip;), hash: name</li> -<li>но \name(&hellip;) -&gt; name(&hellip;), а name - ошибка !!!! hash: name</li> -<li></li> -<li>Или все же следует различать макросы со скобками и без скобок как два разных объекта???</li> -<li>\name := name2; и \name(&hellip;) := name2(&hellip;); будут разными объектами</li> -<li></li> -<li>Или добавить макросы-алиасы без аргументов только для переименования отдельных терминов?</li> -<li>\alias :- name2; но как их отличать от обычных макросов в операции удаления?</li> -<li>Или вообще не нужно отличать и оставить только один варинат (либо макрос, либо алиас)</li> -<li>Тода вопрос со скобками закрывается сам собой, алиасы всегда без скобок,</li> -<li>макросы со скбками или без скобок, но должно быть полное соответствие.</li> -<li></li> -<li>@ name name2 @ -&gt; name name2, но name name2(&hellip;) - ошибка!!! (hash: name,name2)</li> -<li>@ name name2(&hellip;) @ -&gt; name name2(&hellip;), но name name2 - ошибка !!!! (hash: name,name2)</li> -<li>@ name name2<a href="...">&hellip;</a> @ -&gt; name name2<a href="...">&hellip;</a>, но name name2 - ошибка !!!! ( hash: name,name2 )</li> -<li>@ name $tmpl<a href="...">&hellip;</a> name3@ -&gt; name $tmpl<a href="...">&hellip;</a> name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )</li> -<li></li> -<li>Но!</li> -<li>@ name name2 @ ::- -&gt; name name2 - ок, но name name2(&hellip;) - ок</li> -<li>@ name $tmpl name3@ ::- -&gt; name $tmpl<a href="...">&hellip;</a> name3 - ок, name $tmpl(&hellip;) name3[&hellip;] - ок</li> -<li></li> -<li></li> -<li></li> -<li>Для последовательности лексем требуется полное соответствие с учетом скобок ???</li> -<li>и может ли быть несколько скобок одного типа (несколько крыглях, или несколько квардратных????</li> -<li>&lt;Может быть несколько скобок одного типа, например, при указании типа у аргументов или типа возвращаемого значения.&gt;</li> -<li></li> -<li>@ name name2 @ -&gt; name name2, но name name2(&hellip;) - ошибка!!! (hash: name,name2)</li> -<li>@ name name2(&hellip;) @ -&gt; name name2(&hellip;), но name name2 - ошибка !!!! (hash: name,name2)</li> -<li>@ name name2<a href="...">&hellip;</a> @ -&gt; name name2<a href="...">&hellip;</a>, но name name2 - ошибка !!!! ( hash: name,name2 )</li> -<li>@ name $tmpl<a href="...">&hellip;</a> name3@ -&gt; name $tmpl<a href="...">&hellip;</a> name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )</li> -<li></li> -<li>Проблема скобок возникает из-за сценария замены одного термина на другой,</li> -<li>который есть в препроцессоре С/С++, но отсутствует при реализации с использованием шаблонов.</li> -<li></li> -<li></li> -</ul> -<p>*/</p> -</li> -</ul> -<p>Макросы используются и для превращеня исходного кода <em>NewLang</em> в более привычный синтаксис на основе <a href="https://newlang.net/syntax_dsl.html">ключевых слов</a>, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода.</p> -<p><a href="https://newlang.net/syntax_dsl.html">Например:</a>.</p> -<pre tabindex="0"><code> @@if(...)@@ ::= @@ [ \$* ]--&gt; @@; - @@while(...)@@ ::= @@ [\$*] &lt;-&gt; @@; - @@return $arg@@::= @@ -- \$arg -- @@; - @@true@@ ::= 1; -</code></pre><p>Тогда цикл до 5:</p> -<pre tabindex="0"><code>count:=1; -[ 1 ] &lt;-&gt; { - [count&gt;5] --&gt; { - -- 42 --; - }; - count+=1; -}; -</code></pre><p>будет выглядеть более привычно</p> -<pre tabindex="0"><code>count:=1; -while( true ) { - if(count&gt;5) { - return 42; - }; - count+=1; -}; -</code></pre><h2 id="идеи-на-будущее">Идеи на будущее<a class="td-heading-self-link" href="#%d0%b8%d0%b4%d0%b5%d0%b8-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5" aria-label="Heading self-link"></a></h2> -<h3 id="символьное-программирование">Символьное программирование<a class="td-heading-self-link" href="#%d1%81%d0%b8%d0%bc%d0%b2%d0%be%d0%bb%d1%8c%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> -<blockquote> -<p>Символьное программирование, часто называемое декларативным программированием, представляет собой парадигму программирования, которая использует математическую логику, отношения и символы для представления знаний и помощи в решении проблем. Вместо того, чтобы сосредотачиваться на описании последовательности операций, необходимых для выполнения вычислений, как в императивном программировании, символическое программирование делает упор на выражении отношений и ограничений между структурами данных, уделяя особое внимание «что», а не «как».</p> -<p>В контексте парадигм программирования символическое программирование часто противопоставляется процедурному или императивному программированию, где программы определяют пошаговые процедуры для достижения своих целей. В то время как императивное программирование фокусируется на описании потока управления с использованием таких конструкций, как циклы и условные выражения, для управления выполнением, символическое программирование сосредоточено на выражении фактов о проблеме и позволяет выполнению естественным образом выводить последующие последствия из предоставленной информации.</p> -<p>Одним из основных преимуществ символьного программирования является его способность обеспечивать более высокий уровень абстракции, что упрощает анализ кода и снижает вероятность ошибок. Непосредственно выражая отношения и ограничения, символическое программирование позволяет разработчикам сосредоточиться на моделировании и спецификации проблем, позволяя базовой системе управлять реализацией и выполнением алгоритмов.</p> -<p>Существует несколько языков программирования и сред, использующих парадигму символьного программирования, например Prolog, Lisp и Haskell. Например, Пролог — это язык логического программирования, который позволяет разработчикам выражать взаимосвязи и факты о проблемных областях, в то время как выполнение автоматически обосновывает и извлекает новые факты на основе исходной информации. В том же духе Лисп, функциональный язык программирования, использует символьные вычисления для манипулирования структурами данных и выполнения сложных операций над ними, используя краткий и математически обоснованный синтаксис. Haskell, еще один функциональный язык программирования, использует строгую типизацию и ленивые вычисления, чтобы обеспечить символическое рассуждение и облегчить эффективное создание программ.</p> -<p>Символьное программирование может быть полезным в широком спектре проблемных областей, включая искусственный интеллект, экспертные системы, программирование логики ограничений и символьную математику, среди других. Более высокий уровень абстракции, обеспечиваемый декларативными языками программирования, облегчает разработку сложных систем, сводя к минимуму вероятность ошибки и улучшая удобство обслуживания. В частности, использование символьного программирования в искусственном интеллекте позволяет разработчикам создавать системы представления знаний и механизмы рассуждения, которые можно применять для обработки естественного языка, машинного обучения и автоматического доказательства теорем.</p> -</blockquote> -<p>Различие между символьным программированием и препроцессором</p> -<ul> -<li>Задача препроцессора - раскрыть(расширить) макрос, тогда как при символьном программировании нужно сокращать (сворачивать) выражения</li> -<li>Препроцессор обрабатывает последовательности лексем (плоские данные), тогда как символьное программирование оперирует выражениями (деревом лексем)</li> -<li>Макрос у препроцессора идентифицируется первым термином, и если макрос не может быть раскрыт, то возникает ошибка. В символьном программировани требуется точное соответствие всего выражения и только в этом случае производится сокращение выражения.</li> -</ul> -<p>Предпосылки для реализации символьного программирования -Компилятор - интерепретатор с REPL и обработка AST как во время компиляции, так и во время выполнения. -Необходимо добавить конструкции для определения правил символьного программрования (чистые функции?) -Необходимо добавить конструкцию для вычисления выражений в символьном программировании.</p> -<p>Wolfram -<a href="https://habr.com/articles/772984/">https://habr.com/articles/772984/</a></p> -<pre tabindex="0"><code>diffRules = { - Sin[x] -&gt; Cos[x], - Cos[x] -&gt; -Sin[x], - x^2 -&gt; 2*x, - x -&gt; 1, - Log[x] -&gt; 1/x -}; -</code></pre><pre tabindex="0"><code>diffRules := ( - Sin(x) @-&gt; Cos(x), - Cos(x) @-&gt; -Sin(x), - x^2 @-&gt; 2*x, - x @-&gt; 1, - Log(x) @-&gt; 1\x, -); - -expr @-&gt; Sin(x) - x^2 + Log(x); - -# И применим к нему правила дифференцирования - -#expr /. diffRules -#(* 1/x - 2 x + Cos[x] *) - -sym := SymEval(expr, diffRules); -res := Eval(sym, x=0.123); -</code></pre><pre tabindex="0"><code>expr = a^2 + 3 * b^3 - c^4 + 2 * x^2 - x + 4*c + 3 - -И я хочу это выражение линеаризовать, т.е. отбросить все степени выше первой. Я могу сделать это напрямую, как в примерах выше: - -expr /. { - a^2 -&gt; 0, - b^3 -&gt; 0, - c^4 -&gt; 0, - x^2 -&gt; 0 -} -(* 3 + 4 c - x *) - -Но это слишком неудобно. Что если я не знаю ни точную степень, ни имя переменной? Как просто указать, что нужно заменить все места, где встречается возведение в степень на ноль? Это можно сделать при помощи шаблонов вот так: - -expr /. Power[_, _] -&gt; 0 -(* 3 + 4 c - x *) - -Либо вот так: - -expr /. _ ^ _ -&gt; 0 -(* 3 + 4 c - x *) -</code></pre><pre tabindex="0"><code>:diffRules() := { - {@ Sin(x) @} ::- {@ Cos(x) @}; - Cos(x) @-&gt; -Sin(x), - x^2 @-&gt; 2*x, - x @-&gt; 1, - Log(x) @-&gt; 1\x, -}; - -expr @-&gt; Sin(x) - x^2 + Log(x); - -# И применим к нему правила дифференцирования - -#expr /. diffRules -#(* 1/x - 2 x + Cos[x] *) - -sym := SymEval(expr, diffRules); -res := Eval(sym, x=0.123); -</code></pre> +</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Writing a conditional statement using</span> +</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># the macros defined above</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@if</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">condition</span> <span style="color:#000;font-weight:bold">){</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">...</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> <span style="color:#5c35cc;font-weight:bold">@elif</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">condition2</span> <span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">...</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> <span style="color:#5c35cc;font-weight:bold">@else</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">...</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span></code></pre></div><p>For example, a loop up to 5:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">[</span> <span style="color:#0000cf;font-weight:bold">1</span> <span style="color:#000;font-weight:bold">]</span> <span style="color:#ce5c00;font-weight:bold">&lt;-&gt;</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">[</span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#0000cf;font-weight:bold">5</span> <span style="color:#000;font-weight:bold">]</span> <span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">--</span> <span style="color:#0000cf;font-weight:bold">42</span> <span style="color:#ce5c00;font-weight:bold">--</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span><span style="display:flex;"><span> <span style="color:#000">count</span><span style="color:#ce5c00;font-weight:bold">+=</span><span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span></code></pre></div><p>This will look more familiar:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@while</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">true</span> <span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@if</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#0000cf;font-weight:bold">5</span> <span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@return</span> <span style="color:#0000cf;font-weight:bold">42</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span><span style="display:flex;"><span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">+=</span> <span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span></code></pre></div> </div> @@ -1841,235 +1516,145 @@ <h2 id="предопределенные-макросы">Предопредел <h1 id="pg-8e386bb5b373d09fe8bcbec82c31b73f">9 - Keyword syntax (DSL)</h1> - <h2 id="dsl">DSL<a class="td-heading-self-link" href="#dsl" aria-label="Heading self-link"></a></h2> -<h3 id="features-of-associative-memory">Features of associative memory<a class="td-heading-self-link" href="#features-of-associative-memory" aria-label="Heading self-link"></a></h3> + <h3 id="features-of-associative-memory">Features of associative memory<a class="td-heading-self-link" href="#features-of-associative-memory" aria-label="Heading self-link"></a></h3> <p>The syntax of the <em>NewLang</em> language is based on strict rules without the use of keywords, and no matter how logical it may seem, association by keywords is much easier to remember, for example, <strong>if</strong>, than the combination <em>minus minus right angle bracket</em> <strong>&ndash;&gt;</strong>. Because of this, it makes sense to use not a &ldquo;pure&rdquo; basic syntax, but a more familiar dialect with the use of keywords.</p> -<h3 id="syntax-based-on-keywords">Syntax based on keywords<a class="td-heading-self-link" href="#syntax-based-on-keywords" aria-label="Heading self-link"></a></h3> -<p>In the dsl.nlp file, there is a set of macros that expand the basic syntax of <em>NewLang</em>, based on rules, -with a set of predefined keywords as in classical programming languages. -And if necessary, they can be adapted or supplemented for your own domain.</p> -<h2 id="константы">Константы<a class="td-heading-self-link" href="#%d0%ba%d0%be%d0%bd%d1%81%d1%82%d0%b0%d0%bd%d1%82%d1%8b" aria-label="Heading self-link"></a></h2> -<h3 id="логические">Логические<a class="td-heading-self-link" href="#%d0%bb%d0%be%d0%b3%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> +<p><em>NewLang</em> already contains a set of macros that extend the basic rule-based syntax of <em>NewLang</em>, +a set of predefined keywords as in classical programming languages, +which can be adapted or supplemented to suit your own subject area.</p> +<h3 id="constants">Constants<a class="td-heading-self-link" href="#constants" aria-label="Heading self-link"></a></h3> <ul> -<li><strong>true</strong> - 1</li> -<li><strong>yes</strong> - 1</li> -<li><strong>false</strong> - 0</li> -<li><strong>no</strong> - 0</li> +<li> +<p><em>@true</em> - 1</p> +</li> +<li> +<p><em>@yes</em> - 1</p> +</li> +<li> +<p><em>@false</em> - 0</p> +</li> +<li> +<p><em>@no</em> - 0</p> +</li> +<li> +<p><em>@this</em> или <em>@self</em> - Current object</p> +</li> +<li> +<p><em>@super</em> - Parent object</p> +</li> +<li> +<p><em>@latter</em> or <em>@last</em>- Result of the last operation</p> +</li> </ul> -<h3 id="системные-имена">Системные имена<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%8b%d0%b5-%d0%b8%d0%bc%d0%b5%d0%bd%d0%b0" aria-label="Heading self-link"></a></h3> +<h3 id="logical-operators">Logical operators<a class="td-heading-self-link" href="#logical-operators" aria-label="Heading self-link"></a></h3> <ul> -<li><strong>this</strong> - Текущий объект (<strong>$0</strong>)</li> -<li><strong>parent</strong> - Родительский объект (<strong>$$</strong>)</li> -<li><strong>last</strong> - Результат выполнения последнего оператора (<strong>$^</strong>)</li> +<li><em>@and</em> - Logical <strong>AND</strong></li> +<li><em>@or</em> - Logical <strong>OR</strong></li> +<li><em>@xor</em> - Logical <strong>Exclusive OR</strong></li> +<li><em>@not(value)</em> - Logical negation</li> </ul> -<p>!!!!!!!!- <strong>args</strong> - Все аргументы функции (<strong>$*</strong>)</p> -<p>!!!!!!!!- <strong>sys</strong> - Системный контекст запущенной программы (<strong>@@</strong>) -!!!!!!!!- <strong>current</strong> - Текущий модуль (<strong>@$</strong>) -!!!!!!!!- <strong>cmd</strong> - Все аргументы выполняющегося приложения из командной строки (<strong>@*</strong>)</p> -<p>!!!!!!!!!!1### Типовые функции и проверки -!!!!!!!!!!- <strong>run(&lsquo;filename&rsquo;)</strong> - Выполнить указанный файл (<strong>@@(&lsquo;filename&rsquo;)</strong>) -!!!!!!!!!!- <strong>ifmain</strong> - Проверка, если текущий модуль основной (<strong>[@$.$0] &ndash;&gt;</strong> { &hellip; }) -!!!!!!!!!!- <strong>ifload</strong> - Проверка, если текущий модуль загружается впервые (<strong>[@$.<strong>load</strong>] &ndash;&gt;</strong> { &hellip; })</p> -<h3 id="операторы">Операторы<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b" aria-label="Heading self-link"></a></h3> +<h3 id="operators">Operators<a class="td-heading-self-link" href="#operators" aria-label="Heading self-link"></a></h3> <ul> <li> -<p><strong>match(cond)</strong> - Оператор <a href="https://newlang.net/ops.html#%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B0-%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F">оценки выражения</a></p> +<p><em>@if(&hellip;)</em> - First conditional statement</p> </li> <li> -<p><strong>if(&hellip;)</strong> - Первый условный оператор (<strong>[$*]&ndash;&gt;</strong> { &hellip; })</p> +<p><em>@elif(&hellip;)</em> - Second and all subsequent conditional statements</p> </li> <li> -<p><strong>elif(&hellip;)</strong> - Второй и все последующие (<strong>,[$*]&ndash;&gt;</strong> { &hellip; })</p> +<p><em>@else</em> - Operator <em>otherwise</em></p> </li> <li> -<p><strong>else</strong> - Оператор <em>иначе</em> (<strong>,[_]&ndash;&gt;</strong> { &hellip; })</p> +<p><em>@while(&hellip;)</em> - Loop operator with precondition</p> </li> <li> -<p><strong>while(cond)</strong> - Оператор цикла с предусловием (<strong>[@$cond] &lt;-&gt;</strong> { &hellip; } )</p> +<p><em>@dowhile(&hellip;)</em> - Loop operator with postcondition</p> </li> <li> -<p><strong>dowhile(cond)</strong> - Оператор цикла с постусловием ({ &hellip; } <strong>&lt;-&gt;[@$cond]</strong>)</p> +<p><em>@loop</em> - Infinite loop operator</p> </li> <li> -<p><strong>iter(obj, &hellip; )</strong> - Создание итератора ( <strong>@$obj</strong> ? (@$*) )</p> +<p><em>@break $label</em> - Operator to break out of a named named block of code</p> </li> <li> -<p><strong>next(obj, &hellip; )</strong> - Следующий элемент итератора ( <strong>@$obj</strong> ! ($*) )</p> +<p><em>@continue $label</em> - Jump operator to the beginning of a named block of code</p> </li> <li> -<p><strong>curr(obj, &hellip; )</strong> - Текущий элемент итератора ( <strong>@$obj</strong> !? ($*) )</p> +<p><em>@return( result )</em> - Operator for returning a value and exiting a function</p> </li> <li> -<p><strong>first(obj)</strong> - Перейти на первый элемент итератора ( <strong>@$obj</strong> !! )</p> +<p><em>@throw( error )</em> - Operator for creating an exception and returning an error</p> </li> <li> -<p><strong>all(obj)</strong> - Получить сразу все элементы итератора ( <strong>@$obj</strong> ??)</p> +<p><em>@match( &hellip; )</em> - Expression evaluation operator</p> </li> -</ul> -<h3 id="прерывания">Прерывания<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b5%d1%80%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h3> -<ul> <li> -<p><strong>return</strong> - Положительное прерывание (<strong>++</strong>)</p> +<p><em>@case( &hellip; )</em> - Pattern comparison operator</p> </li> <li> -<p><strong>return(&hellip;)</strong>- Положительное прерывание с возвратом значения (<strong>++</strong> @$value <strong>++</strong>)</p> +<p><em>@default</em> - Selection operator</p> </li> <li> -<p><strong>error</strong> - Отрицательное прерывание (<strong>--</strong>)</p> +<p><em>@iter(obj, &hellip; )</em> - Creating an iterator</p> </li> <li> -<p><strong>error(&hellip;)</strong> - Отрицательное прерывание с возвратом значения (<strong>--</strong> @$value <strong>--</strong>)</p> +<p><em>@next(obj, &hellip; )</em> - Get the next element of the iterator</p> </li> <li> -<p><strong>break+</strong> и <strong>break-</strong> - Выход из цикла:</p> +<p><em>@curr(obj, &hellip; )</em> - Get the current iterator element</p> +</li> +<li> +<p><em>@first(obj)</em> - Go to the first element of the iterator</p> +</li> +<li> +<p><em>@all(obj)</em> - Get all elements of the iterator at once</p> </li> </ul> -<pre tabindex="0"><code> while(...) {+ - ++ :Break ++ - +} - while(...) {- - -- :Break -- - -} -</code></pre><ul> -<li><strong>continue+</strong> и <strong>continue-</strong> - В начало цикла:</li> -</ul> -<pre tabindex="0"><code> while(...) {+ - ++ :Continue ++ - +} - while(...) {- - -- :Continue -- - -} -</code></pre><p>obj { -.field = 1; -.prop(); -};</p> -<p>#Python</p> -<h1 id="1-without-using-with-statement">1) without using with statement<a class="td-heading-self-link" href="#1-without-using-with-statement" aria-label="Heading self-link"></a></h1> -<p>file = open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) -file.write(&lsquo;hello world !&rsquo;) -file.close()</p> -<h1 id="2-without-using-with-statement">2) without using with statement<a class="td-heading-self-link" href="#2-without-using-with-statement" aria-label="Heading self-link"></a></h1> -<p>file = open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) -try: -file.write(&lsquo;hello world&rsquo;) -finally: -file.close()</p> -<p>open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) { -.write(&lsquo;hello world !&rsquo;); -.close(); -}</p> -<p>Python3</p> -<h1 id="using-with-statement">using with statement<a class="td-heading-self-link" href="#using-with-statement" aria-label="Heading self-link"></a></h1> -<p>with open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) as file: -file.write(&lsquo;hello world !&rsquo;)</p> -<h1 id="a-simple-file-writer-object">a simple file writer object<a class="td-heading-self-link" href="#a-simple-file-writer-object" aria-label="Heading self-link"></a></h1> -<p>class MessageWriter(object): -def <strong>init</strong>(self, file_name): -self.file_name = file_name</p> -<pre><code>def __enter__(self): - self.file = open(self.file_name, 'w') - return self.file - -def __exit__(self, *args): - self.file.close() -</code></pre> -<h1 id="using-with-statement-with-messagewriter">using with statement with MessageWriter<a class="td-heading-self-link" href="#using-with-statement-with-messagewriter" aria-label="Heading self-link"></a></h1> -<p>with MessageWriter(&lsquo;my_file.txt&rsquo;) as xfile: -xfile.write(&lsquo;hello world&rsquo;)</p> -<h1 id="a-simple-file-writer-object-1">a simple file writer object<a class="td-heading-self-link" href="#a-simple-file-writer-object-1" aria-label="Heading self-link"></a></h1> -<p>:MessageWriter { -def <strong>init</strong>(self, file_name): -self.file_name = file_name</p> -<pre><code>def __enter__(self): - self.file = open(self.file_name, 'w') - return self.file - -def __exit__(self, *args): - self.file.close() -</code></pre> -<p>}</p> -<h1 id="using-with-statement-with-messagewriter-1">using with statement with MessageWriter<a class="td-heading-self-link" href="#using-with-statement-with-messagewriter-1" aria-label="Heading self-link"></a></h1> -<p>MessageWriter(&lsquo;my_file.txt&rsquo;) { -.write(&lsquo;hello world&rsquo;); -};</p> -<p>from contextlib import contextmanager</p> -<p>class MessageWriter(object): -def <strong>init</strong>(self, filename): -self.file_name = filename</p> -<pre><code>@contextmanager -def open_file(self): - try: - file = open(self.file_name, 'w') - yield file - finally: - file.close() -</code></pre> -<h1 id="usage">usage<a class="td-heading-self-link" href="#usage" aria-label="Heading self-link"></a></h1> -<p>message_writer = MessageWriter(&lsquo;hello.txt&rsquo;) -with message_writer.open_file() as my_file: -my_file.write(&lsquo;hello world&rsquo;)</p> -<p>:MessageWriter(object) { -def <strong>init</strong>(self, filename): -self.file_name = filename</p> -<pre><code>@contextmanager -def open_file(self): - try: - file = open(self.file_name, 'w') - yield file - finally: - file.close() -</code></pre> -<p>}</p> -<h1 id="usage-1">usage<a class="td-heading-self-link" href="#usage-1" aria-label="Heading self-link"></a></h1> -<p>message_writer = MessageWriter(&lsquo;hello.txt&rsquo;) -with message_writer.open_file() as my_file: -my_file.write(&lsquo;hello world&rsquo;)</p> -<h1 id="приложения">Приложения<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b8%d0%bb%d0%be%d0%b6%d0%b5%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h1> -<h2 id="предопределенные-макросы">Предопределенные макросы<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b5%d0%b4%d0%be%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%bd%d1%8b%d0%b5-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b" aria-label="Heading self-link"></a></h2> -<p>При работе парсера <em>NewLang</em> автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. -Данные предопределенные макросы можно использовать как обычные константы.</p> +<h2 id="predefined-macros">Predefined macros<a class="td-heading-self-link" href="#predefined-macros" aria-label="Heading self-link"></a></h2> +<p>When the <em>NewLang</em> parser is running, several reserved macros are automatically generated, +some of which correspond to preprocessor macros in C/C++. +These predefined macros can be used as regular constants.</p> <ul> <li> -<p>__FILE__ или __FILE_NAME__ - имя и полный путь текущего файла</p> +<p>__FILE__ or __FILE_NAME__ - name and full path of the current file</p> </li> <li> -<p>__LINE__ или __FILE_LINE__ - содержит номер текущей строки в файле</p> +<p>__LINE__ or __FILE_LINE__ - contains the number of the current line in the file</p> </li> <li> -<p>__FILE_TIMESTAMP__ - дату и время последней модификации текущего файла в строковом представлении</p> +<p>__FILE_TIMESTAMP__ - date and time of the last modification of the current file in string representation</p> </li> <li> -<p>__FILE_MD5__ - md5 хеш текущего файла в строковом виде</p> +<p>__FILE_MD5__ - md5 hash of the current file in string form</p> </li> <li> -<p>__COUNTER__ - целочисленный счетчик, который увеличивает свое значение при каждом обращении</p> +<p>__COUNTER__ - an integer counter that increases its value with each access</p> </li> <li> -<p>__DATE__ - дата начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)</p> +<p>__DATE__ - start date of the compiler launch (has the same value for all processed files)</p> </li> <li> -<p>__TIME__ - время начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)</p> +<p>__TIME__ - start time of the compiler launch (has the same value for all processed files)</p> </li> <li> -<p>__TIMESTAMP__ - дату и время начала запуска компилятора (например: &ldquo;Fri 19 Aug 13:32:58 2016&rdquo;)</p> +<p>__TIMESTAMP__ - date and time when the compiler started running (for example: &ldquo;Fri 19 Aug 13:32:58 2016&rdquo;)</p> </li> <li> -<p>__TIMESTAMP_ISO__ - дату и время начала запуска компилятора в формате ISO (например: &ldquo;2013-07-06T00:50:06Z&rdquo;)</p> +<p>__TIMESTAMP_ISO__ - date and time when the compiler started running in ISO format (for example: &ldquo;2013-07-06T00:50:06Z&rdquo;)</p> </li> <li> -<p>__NLC_VER__ - Страшая и младшая версия компилятора NewLang (8 битное число, по 4 бита на цифру)</p> +<p>__NLC_VER__ - Older and younger version of the NewLang compiler (8-bit number, 4 bits per digit)</p> </li> <li> -<p>__NLC_DATE_BUILD__ - текстовая строка с датой сборки компилятора NewLang (например, &ldquo;23.06.04 20:51:39&rdquo;)</p> +<p>__NLC_DATE_BUILD__ - text string with the build date of the NewLang compiler (for example, &ldquo;06/23/04 20:51:39&rdquo;)</p> </li> <li> -<p>__NLC_SOURCE_GIT__ - текстовая строка с идентификатором исходных файлов NewLang git репозитория, использованных при сборке компилятора (например, &ldquo;v0.3.0-fef8c371&rdquo;)</p> +<p>__NLC_SOURCE_GIT__ - text string with the identifier of the NewLang git repository source files used to build the compiler (for example, &ldquo;v0.3.0-fef8c371&rdquo;)</p> </li> <li> -<p>__NLC_SOURCE_BUILD__ - дата сборки и git идентификатор исходных файлов NewLang одной текстовой строкой (например, &ldquo;v0.3.0-fef8c371 23.06.04 20:51:39&rdquo;)</p> +<p>__NLC_SOURCE_BUILD__ - build date and git identifier of NewLang source files in one text line (for example, &ldquo;v0.3.0-fef8c371 06/23/04 20:51:39&rdquo;)</p> </li> </ul> diff --git a/docs/docs/syntax/dsl/index.html b/docs/docs/syntax/dsl/index.html index eecebc30..b19e5bae 100644 --- a/docs/docs/syntax/dsl/index.html +++ b/docs/docs/syntax/dsl/index.html @@ -18,19 +18,19 @@ <link rel="icon" type="image/png" href="/favicons/android-192x192.png" sizes="192x192"> <title>Keyword syntax (DSL) | NewLang</title> -<meta name="description" content="DSL Features of associative memory The syntax of the NewLang language is based on strict rules without the use of keywords, and no matter how logical it may seem, association by keywords is much easier to remember, for example, if, than the combination minus minus right angle bracket &amp;ndash;&amp;gt;. Because of this, it makes sense to use not a &amp;ldquo;pure&amp;rdquo; basic syntax, but a more familiar dialect with the use of keywords."> +<meta name="description" content="Features of associative memory The syntax of the NewLang language is based on strict rules without the use of keywords, and no matter how logical it may seem, association by keywords is much easier to remember, for example, if, than the combination minus minus right angle bracket &amp;ndash;&amp;gt;. Because of this, it makes sense to use not a &amp;ldquo;pure&amp;rdquo; basic syntax, but a more familiar dialect with the use of keywords."> <meta property="og:title" content="Keyword syntax (DSL)" /> -<meta property="og:description" content="DSL Features of associative memory The syntax of the NewLang language is based on strict rules without the use of keywords, and no matter how logical it may seem, association by keywords is much easier to remember, for example, if, than the combination minus minus right angle bracket &ndash;&gt;. Because of this, it makes sense to use not a &ldquo;pure&rdquo; basic syntax, but a more familiar dialect with the use of keywords." /> +<meta property="og:description" content="Features of associative memory The syntax of the NewLang language is based on strict rules without the use of keywords, and no matter how logical it may seem, association by keywords is much easier to remember, for example, if, than the combination minus minus right angle bracket &ndash;&gt;. Because of this, it makes sense to use not a &ldquo;pure&rdquo; basic syntax, but a more familiar dialect with the use of keywords." /> <meta property="og:type" content="article" /> <meta property="og:url" content="http://localhost:1313/docs/syntax/dsl/" /><meta property="article:section" content="docs" /> -<meta property="article:modified_time" content="2024-03-22T23:57:08+03:00" /><meta property="og:site_name" content="NewLang" /> +<meta property="article:modified_time" content="2024-03-23T22:03:23+03:00" /><meta property="og:site_name" content="NewLang" /> <meta itemprop="name" content="Keyword syntax (DSL)"> -<meta itemprop="description" content="DSL Features of associative memory The syntax of the NewLang language is based on strict rules without the use of keywords, and no matter how logical it may seem, association by keywords is much easier to remember, for example, if, than the combination minus minus right angle bracket &ndash;&gt;. Because of this, it makes sense to use not a &ldquo;pure&rdquo; basic syntax, but a more familiar dialect with the use of keywords."> -<meta itemprop="dateModified" content="2024-03-22T23:57:08+03:00" /> -<meta itemprop="wordCount" content="794"> +<meta itemprop="description" content="Features of associative memory The syntax of the NewLang language is based on strict rules without the use of keywords, and no matter how logical it may seem, association by keywords is much easier to remember, for example, if, than the combination minus minus right angle bracket &ndash;&gt;. Because of this, it makes sense to use not a &ldquo;pure&rdquo; basic syntax, but a more familiar dialect with the use of keywords."> +<meta itemprop="dateModified" content="2024-03-23T22:03:23+03:00" /> +<meta itemprop="wordCount" content="548"> <meta itemprop="keywords" content="" /><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Keyword syntax (DSL)"/> -<meta name="twitter:description" content="DSL Features of associative memory The syntax of the NewLang language is based on strict rules without the use of keywords, and no matter how logical it may seem, association by keywords is much easier to remember, for example, if, than the combination minus minus right angle bracket &ndash;&gt;. Because of this, it makes sense to use not a &ldquo;pure&rdquo; basic syntax, but a more familiar dialect with the use of keywords."/> +<meta name="twitter:description" content="Features of associative memory The syntax of the NewLang language is based on strict rules without the use of keywords, and no matter how logical it may seem, association by keywords is much easier to remember, for example, if, than the combination minus minus right angle bracket &ndash;&gt;. Because of this, it makes sense to use not a &ldquo;pure&rdquo; basic syntax, but a more familiar dialect with the use of keywords."/> @@ -140,7 +140,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -171,7 +171,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> @@ -225,24 +225,15 @@ <div class="td-toc"> <nav id="TableOfContents"> <ul> - <li><a href="#dsl">DSL</a> + <li> <ul> <li><a href="#features-of-associative-memory">Features of associative memory</a></li> - <li><a href="#syntax-based-on-keywords">Syntax based on keywords</a></li> + <li><a href="#constants">Constants</a></li> + <li><a href="#logical-operators">Logical operators</a></li> + <li><a href="#operators">Operators</a></li> </ul> </li> - <li><a href="#константы">Константы</a> - <ul> - <li><a href="#логические">Логические</a></li> - <li><a href="#системные-имена">Системные имена</a></li> - <li><a href="#операторы">Операторы</a></li> - <li><a href="#прерывания">Прерывания</a></li> - </ul> - </li> - </ul> - - <ul> - <li><a href="#предопределенные-макросы">Предопределенные макросы</a></li> + <li><a href="#predefined-macros">Predefined macros</a></li> </ul> </nav> </div> @@ -282,235 +273,145 @@ <h1>Keyword syntax (DSL)</h1> <header class="article-meta"> </header> - <h2 id="dsl">DSL<a class="td-heading-self-link" href="#dsl" aria-label="Heading self-link"></a></h2> -<h3 id="features-of-associative-memory">Features of associative memory<a class="td-heading-self-link" href="#features-of-associative-memory" aria-label="Heading self-link"></a></h3> + <h3 id="features-of-associative-memory">Features of associative memory<a class="td-heading-self-link" href="#features-of-associative-memory" aria-label="Heading self-link"></a></h3> <p>The syntax of the <em>NewLang</em> language is based on strict rules without the use of keywords, and no matter how logical it may seem, association by keywords is much easier to remember, for example, <strong>if</strong>, than the combination <em>minus minus right angle bracket</em> <strong>&ndash;&gt;</strong>. Because of this, it makes sense to use not a &ldquo;pure&rdquo; basic syntax, but a more familiar dialect with the use of keywords.</p> -<h3 id="syntax-based-on-keywords">Syntax based on keywords<a class="td-heading-self-link" href="#syntax-based-on-keywords" aria-label="Heading self-link"></a></h3> -<p>In the dsl.nlp file, there is a set of macros that expand the basic syntax of <em>NewLang</em>, based on rules, -with a set of predefined keywords as in classical programming languages. -And if necessary, they can be adapted or supplemented for your own domain.</p> -<h2 id="константы">Константы<a class="td-heading-self-link" href="#%d0%ba%d0%be%d0%bd%d1%81%d1%82%d0%b0%d0%bd%d1%82%d1%8b" aria-label="Heading self-link"></a></h2> -<h3 id="логические">Логические<a class="td-heading-self-link" href="#%d0%bb%d0%be%d0%b3%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> +<p><em>NewLang</em> already contains a set of macros that extend the basic rule-based syntax of <em>NewLang</em>, +a set of predefined keywords as in classical programming languages, +which can be adapted or supplemented to suit your own subject area.</p> +<h3 id="constants">Constants<a class="td-heading-self-link" href="#constants" aria-label="Heading self-link"></a></h3> <ul> -<li><strong>true</strong> - 1</li> -<li><strong>yes</strong> - 1</li> -<li><strong>false</strong> - 0</li> -<li><strong>no</strong> - 0</li> +<li> +<p><em>@true</em> - 1</p> +</li> +<li> +<p><em>@yes</em> - 1</p> +</li> +<li> +<p><em>@false</em> - 0</p> +</li> +<li> +<p><em>@no</em> - 0</p> +</li> +<li> +<p><em>@this</em> или <em>@self</em> - Current object</p> +</li> +<li> +<p><em>@super</em> - Parent object</p> +</li> +<li> +<p><em>@latter</em> or <em>@last</em>- Result of the last operation</p> +</li> </ul> -<h3 id="системные-имена">Системные имена<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%8b%d0%b5-%d0%b8%d0%bc%d0%b5%d0%bd%d0%b0" aria-label="Heading self-link"></a></h3> +<h3 id="logical-operators">Logical operators<a class="td-heading-self-link" href="#logical-operators" aria-label="Heading self-link"></a></h3> <ul> -<li><strong>this</strong> - Текущий объект (<strong>$0</strong>)</li> -<li><strong>parent</strong> - Родительский объект (<strong>$$</strong>)</li> -<li><strong>last</strong> - Результат выполнения последнего оператора (<strong>$^</strong>)</li> +<li><em>@and</em> - Logical <strong>AND</strong></li> +<li><em>@or</em> - Logical <strong>OR</strong></li> +<li><em>@xor</em> - Logical <strong>Exclusive OR</strong></li> +<li><em>@not(value)</em> - Logical negation</li> </ul> -<p>!!!!!!!!- <strong>args</strong> - Все аргументы функции (<strong>$*</strong>)</p> -<p>!!!!!!!!- <strong>sys</strong> - Системный контекст запущенной программы (<strong>@@</strong>) -!!!!!!!!- <strong>current</strong> - Текущий модуль (<strong>@$</strong>) -!!!!!!!!- <strong>cmd</strong> - Все аргументы выполняющегося приложения из командной строки (<strong>@*</strong>)</p> -<p>!!!!!!!!!!1### Типовые функции и проверки -!!!!!!!!!!- <strong>run(&lsquo;filename&rsquo;)</strong> - Выполнить указанный файл (<strong>@@(&lsquo;filename&rsquo;)</strong>) -!!!!!!!!!!- <strong>ifmain</strong> - Проверка, если текущий модуль основной (<strong>[@$.$0] &ndash;&gt;</strong> { &hellip; }) -!!!!!!!!!!- <strong>ifload</strong> - Проверка, если текущий модуль загружается впервые (<strong>[@$.<strong>load</strong>] &ndash;&gt;</strong> { &hellip; })</p> -<h3 id="операторы">Операторы<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b" aria-label="Heading self-link"></a></h3> +<h3 id="operators">Operators<a class="td-heading-self-link" href="#operators" aria-label="Heading self-link"></a></h3> <ul> <li> -<p><strong>match(cond)</strong> - Оператор <a href="https://newlang.net/ops.html#%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B0-%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F">оценки выражения</a></p> +<p><em>@if(&hellip;)</em> - First conditional statement</p> </li> <li> -<p><strong>if(&hellip;)</strong> - Первый условный оператор (<strong>[$*]&ndash;&gt;</strong> { &hellip; })</p> +<p><em>@elif(&hellip;)</em> - Second and all subsequent conditional statements</p> </li> <li> -<p><strong>elif(&hellip;)</strong> - Второй и все последующие (<strong>,[$*]&ndash;&gt;</strong> { &hellip; })</p> +<p><em>@else</em> - Operator <em>otherwise</em></p> </li> <li> -<p><strong>else</strong> - Оператор <em>иначе</em> (<strong>,[_]&ndash;&gt;</strong> { &hellip; })</p> +<p><em>@while(&hellip;)</em> - Loop operator with precondition</p> </li> <li> -<p><strong>while(cond)</strong> - Оператор цикла с предусловием (<strong>[@$cond] &lt;-&gt;</strong> { &hellip; } )</p> +<p><em>@dowhile(&hellip;)</em> - Loop operator with postcondition</p> </li> <li> -<p><strong>dowhile(cond)</strong> - Оператор цикла с постусловием ({ &hellip; } <strong>&lt;-&gt;[@$cond]</strong>)</p> +<p><em>@loop</em> - Infinite loop operator</p> </li> <li> -<p><strong>iter(obj, &hellip; )</strong> - Создание итератора ( <strong>@$obj</strong> ? (@$*) )</p> +<p><em>@break $label</em> - Operator to break out of a named named block of code</p> </li> <li> -<p><strong>next(obj, &hellip; )</strong> - Следующий элемент итератора ( <strong>@$obj</strong> ! ($*) )</p> +<p><em>@continue $label</em> - Jump operator to the beginning of a named block of code</p> </li> <li> -<p><strong>curr(obj, &hellip; )</strong> - Текущий элемент итератора ( <strong>@$obj</strong> !? ($*) )</p> +<p><em>@return( result )</em> - Operator for returning a value and exiting a function</p> </li> <li> -<p><strong>first(obj)</strong> - Перейти на первый элемент итератора ( <strong>@$obj</strong> !! )</p> +<p><em>@throw( error )</em> - Operator for creating an exception and returning an error</p> </li> <li> -<p><strong>all(obj)</strong> - Получить сразу все элементы итератора ( <strong>@$obj</strong> ??)</p> +<p><em>@match( &hellip; )</em> - Expression evaluation operator</p> </li> -</ul> -<h3 id="прерывания">Прерывания<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b5%d1%80%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h3> -<ul> <li> -<p><strong>return</strong> - Положительное прерывание (<strong>++</strong>)</p> +<p><em>@case( &hellip; )</em> - Pattern comparison operator</p> </li> <li> -<p><strong>return(&hellip;)</strong>- Положительное прерывание с возвратом значения (<strong>++</strong> @$value <strong>++</strong>)</p> +<p><em>@default</em> - Selection operator</p> </li> <li> -<p><strong>error</strong> - Отрицательное прерывание (<strong>--</strong>)</p> +<p><em>@iter(obj, &hellip; )</em> - Creating an iterator</p> </li> <li> -<p><strong>error(&hellip;)</strong> - Отрицательное прерывание с возвратом значения (<strong>--</strong> @$value <strong>--</strong>)</p> +<p><em>@next(obj, &hellip; )</em> - Get the next element of the iterator</p> </li> <li> -<p><strong>break+</strong> и <strong>break-</strong> - Выход из цикла:</p> +<p><em>@curr(obj, &hellip; )</em> - Get the current iterator element</p> +</li> +<li> +<p><em>@first(obj)</em> - Go to the first element of the iterator</p> +</li> +<li> +<p><em>@all(obj)</em> - Get all elements of the iterator at once</p> </li> </ul> -<pre tabindex="0"><code> while(...) {+ - ++ :Break ++ - +} - while(...) {- - -- :Break -- - -} -</code></pre><ul> -<li><strong>continue+</strong> и <strong>continue-</strong> - В начало цикла:</li> -</ul> -<pre tabindex="0"><code> while(...) {+ - ++ :Continue ++ - +} - while(...) {- - -- :Continue -- - -} -</code></pre><p>obj { -.field = 1; -.prop(); -};</p> -<p>#Python</p> -<h1 id="1-without-using-with-statement">1) without using with statement<a class="td-heading-self-link" href="#1-without-using-with-statement" aria-label="Heading self-link"></a></h1> -<p>file = open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) -file.write(&lsquo;hello world !&rsquo;) -file.close()</p> -<h1 id="2-without-using-with-statement">2) without using with statement<a class="td-heading-self-link" href="#2-without-using-with-statement" aria-label="Heading self-link"></a></h1> -<p>file = open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) -try: -file.write(&lsquo;hello world&rsquo;) -finally: -file.close()</p> -<p>open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) { -.write(&lsquo;hello world !&rsquo;); -.close(); -}</p> -<p>Python3</p> -<h1 id="using-with-statement">using with statement<a class="td-heading-self-link" href="#using-with-statement" aria-label="Heading self-link"></a></h1> -<p>with open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) as file: -file.write(&lsquo;hello world !&rsquo;)</p> -<h1 id="a-simple-file-writer-object">a simple file writer object<a class="td-heading-self-link" href="#a-simple-file-writer-object" aria-label="Heading self-link"></a></h1> -<p>class MessageWriter(object): -def <strong>init</strong>(self, file_name): -self.file_name = file_name</p> -<pre><code>def __enter__(self): - self.file = open(self.file_name, 'w') - return self.file - -def __exit__(self, *args): - self.file.close() -</code></pre> -<h1 id="using-with-statement-with-messagewriter">using with statement with MessageWriter<a class="td-heading-self-link" href="#using-with-statement-with-messagewriter" aria-label="Heading self-link"></a></h1> -<p>with MessageWriter(&lsquo;my_file.txt&rsquo;) as xfile: -xfile.write(&lsquo;hello world&rsquo;)</p> -<h1 id="a-simple-file-writer-object-1">a simple file writer object<a class="td-heading-self-link" href="#a-simple-file-writer-object-1" aria-label="Heading self-link"></a></h1> -<p>:MessageWriter { -def <strong>init</strong>(self, file_name): -self.file_name = file_name</p> -<pre><code>def __enter__(self): - self.file = open(self.file_name, 'w') - return self.file - -def __exit__(self, *args): - self.file.close() -</code></pre> -<p>}</p> -<h1 id="using-with-statement-with-messagewriter-1">using with statement with MessageWriter<a class="td-heading-self-link" href="#using-with-statement-with-messagewriter-1" aria-label="Heading self-link"></a></h1> -<p>MessageWriter(&lsquo;my_file.txt&rsquo;) { -.write(&lsquo;hello world&rsquo;); -};</p> -<p>from contextlib import contextmanager</p> -<p>class MessageWriter(object): -def <strong>init</strong>(self, filename): -self.file_name = filename</p> -<pre><code>@contextmanager -def open_file(self): - try: - file = open(self.file_name, 'w') - yield file - finally: - file.close() -</code></pre> -<h1 id="usage">usage<a class="td-heading-self-link" href="#usage" aria-label="Heading self-link"></a></h1> -<p>message_writer = MessageWriter(&lsquo;hello.txt&rsquo;) -with message_writer.open_file() as my_file: -my_file.write(&lsquo;hello world&rsquo;)</p> -<p>:MessageWriter(object) { -def <strong>init</strong>(self, filename): -self.file_name = filename</p> -<pre><code>@contextmanager -def open_file(self): - try: - file = open(self.file_name, 'w') - yield file - finally: - file.close() -</code></pre> -<p>}</p> -<h1 id="usage-1">usage<a class="td-heading-self-link" href="#usage-1" aria-label="Heading self-link"></a></h1> -<p>message_writer = MessageWriter(&lsquo;hello.txt&rsquo;) -with message_writer.open_file() as my_file: -my_file.write(&lsquo;hello world&rsquo;)</p> -<h1 id="приложения">Приложения<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b8%d0%bb%d0%be%d0%b6%d0%b5%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h1> -<h2 id="предопределенные-макросы">Предопределенные макросы<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b5%d0%b4%d0%be%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%bd%d1%8b%d0%b5-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b" aria-label="Heading self-link"></a></h2> -<p>При работе парсера <em>NewLang</em> автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. -Данные предопределенные макросы можно использовать как обычные константы.</p> +<h2 id="predefined-macros">Predefined macros<a class="td-heading-self-link" href="#predefined-macros" aria-label="Heading self-link"></a></h2> +<p>When the <em>NewLang</em> parser is running, several reserved macros are automatically generated, +some of which correspond to preprocessor macros in C/C++. +These predefined macros can be used as regular constants.</p> <ul> <li> -<p>__FILE__ или __FILE_NAME__ - имя и полный путь текущего файла</p> +<p>__FILE__ or __FILE_NAME__ - name and full path of the current file</p> </li> <li> -<p>__LINE__ или __FILE_LINE__ - содержит номер текущей строки в файле</p> +<p>__LINE__ or __FILE_LINE__ - contains the number of the current line in the file</p> </li> <li> -<p>__FILE_TIMESTAMP__ - дату и время последней модификации текущего файла в строковом представлении</p> +<p>__FILE_TIMESTAMP__ - date and time of the last modification of the current file in string representation</p> </li> <li> -<p>__FILE_MD5__ - md5 хеш текущего файла в строковом виде</p> +<p>__FILE_MD5__ - md5 hash of the current file in string form</p> </li> <li> -<p>__COUNTER__ - целочисленный счетчик, который увеличивает свое значение при каждом обращении</p> +<p>__COUNTER__ - an integer counter that increases its value with each access</p> </li> <li> -<p>__DATE__ - дата начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)</p> +<p>__DATE__ - start date of the compiler launch (has the same value for all processed files)</p> </li> <li> -<p>__TIME__ - время начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)</p> +<p>__TIME__ - start time of the compiler launch (has the same value for all processed files)</p> </li> <li> -<p>__TIMESTAMP__ - дату и время начала запуска компилятора (например: &ldquo;Fri 19 Aug 13:32:58 2016&rdquo;)</p> +<p>__TIMESTAMP__ - date and time when the compiler started running (for example: &ldquo;Fri 19 Aug 13:32:58 2016&rdquo;)</p> </li> <li> -<p>__TIMESTAMP_ISO__ - дату и время начала запуска компилятора в формате ISO (например: &ldquo;2013-07-06T00:50:06Z&rdquo;)</p> +<p>__TIMESTAMP_ISO__ - date and time when the compiler started running in ISO format (for example: &ldquo;2013-07-06T00:50:06Z&rdquo;)</p> </li> <li> -<p>__NLC_VER__ - Страшая и младшая версия компилятора NewLang (8 битное число, по 4 бита на цифру)</p> +<p>__NLC_VER__ - Older and younger version of the NewLang compiler (8-bit number, 4 bits per digit)</p> </li> <li> -<p>__NLC_DATE_BUILD__ - текстовая строка с датой сборки компилятора NewLang (например, &ldquo;23.06.04 20:51:39&rdquo;)</p> +<p>__NLC_DATE_BUILD__ - text string with the build date of the NewLang compiler (for example, &ldquo;06/23/04 20:51:39&rdquo;)</p> </li> <li> -<p>__NLC_SOURCE_GIT__ - текстовая строка с идентификатором исходных файлов NewLang git репозитория, использованных при сборке компилятора (например, &ldquo;v0.3.0-fef8c371&rdquo;)</p> +<p>__NLC_SOURCE_GIT__ - text string with the identifier of the NewLang git repository source files used to build the compiler (for example, &ldquo;v0.3.0-fef8c371&rdquo;)</p> </li> <li> -<p>__NLC_SOURCE_BUILD__ - дата сборки и git идентификатор исходных файлов NewLang одной текстовой строкой (например, &ldquo;v0.3.0-fef8c371 23.06.04 20:51:39&rdquo;)</p> +<p>__NLC_SOURCE_BUILD__ - build date and git identifier of NewLang source files in one text line (for example, &ldquo;v0.3.0-fef8c371 06/23/04 20:51:39&rdquo;)</p> </li> </ul> diff --git a/docs/docs/syntax/index.html b/docs/docs/syntax/index.html index 817d085b..a3e35b00 100644 --- a/docs/docs/syntax/index.html +++ b/docs/docs/syntax/index.html @@ -141,7 +141,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -172,7 +172,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> @@ -258,12 +258,12 @@ <h1>Синтаксис</h1> </header> <ul> -<li>Операторы разделяются точкой с запятой «;».</li> -<li>Отступы и переводы строк игнорируются.</li> -<li>Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash.</li> -<li>Многострочные комментарии соответствуют стилю С/С++ и должны располагаться между символами /* и */. Многосточные комментарии могут быть вложенными.</li> -<li>Последовательность команд <a href="/docs/ops/block/">(блок кода)</a> заключаются в фигурные скобки &ldquo;<strong>{</strong>&rdquo; и &ldquo;<strong>}</strong>&rdquo;.</li> -<li>Большинство операторов являются выражениями и возвращают результат выполнения последней операции.</li> +<li>Operators are separated by a semicolon &ldquo;;&rdquo;.</li> +<li>Indentations and line breaks are ignored.</li> +<li>Single-line comments start with the symbol &ldquo;#&rdquo; until the end of the line, following the style of Python and Bash comments.</li> +<li>Multi-line comments follow the C/C++ style and should be enclosed between &ldquo;/*&rdquo; and &ldquo;*/&rdquo;. Multi-line comments can be <em>nested</em>.</li> +<li>Command sequences <a href="/docs/ops/block/">(code block)</a> are enclosed in curly braces &ldquo;<strong>{</strong>&rdquo; and &ldquo;<strong>}</strong>&rdquo;.</li> +<li>Most operators are expressions and return the result of the last operation.</li> </ul> <div class="section-index"> @@ -279,7 +279,7 @@ <h1>Синтаксис</h1> <li><a href="/docs/syntax/memory/">Управление памятью, ссылки и совместный доступ</a></li> - <li><a href="/docs/syntax/macros/">Макросы</a></li> + <li><a href="/docs/syntax/macros/">Macros</a></li> <li><a href="/docs/syntax/sysprop/">Системные свойства</a></li> diff --git a/docs/docs/syntax/index.xml b/docs/docs/syntax/index.xml index 549d9041..294f3b31 100644 --- a/docs/docs/syntax/index.xml +++ b/docs/docs/syntax/index.xml @@ -539,7 +539,7 @@ allowing class methods to be defined outside the body of the class simply by spe </item> <item> - <title>Docs: Макросы</title> + <title>Docs: Macros</title> <link>http://localhost:1313/docs/syntax/macros/</link> <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate> @@ -547,423 +547,98 @@ allowing class methods to be defined outside the body of the class simply by spe <description> - &lt;p&gt;Макросы в &lt;strong&gt;NewLang&lt;/strong&gt;, это один или несколько последовательных терминов, которые заменяются на другой термин -или на целую синтаксическую конструкцию (последовательность лексем).&lt;/p&gt; -&lt;p&gt;Макросы обработываются во время работы &lt;strong&gt;лексера&lt;/strong&gt;, т.е. перед передачей последовательности лексем в парсер, -что позволяет с их помощью изменять даже сам синтаксис языка, например, при реализации собственных диалектов DSL.&lt;/p&gt; -&lt;h3 id=&#34;определение-макросов&#34;&gt;Определение макросов&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Определение макросов аналогично &lt;a href=&#34;http://localhost:1313/docs/ops/create/&#34;&gt;определению&lt;/a&gt; других объектов и состоит из трех частей -&lt;strong&gt;&amp;lt;имя макроса&amp;gt; &amp;lt;оператор создания/присвоения&amp;gt; &amp;lt;тело макроса&amp;gt;&lt;/strong&gt; и завершающая точка с запятой &amp;ldquo;&lt;strong&gt;;&lt;/strong&gt;&amp;rdquo;, -т.е. применяются обычные операторы &lt;strong&gt;::=&lt;/strong&gt;, &lt;strong&gt;=&lt;/strong&gt; или &lt;strong&gt;:=&lt;/strong&gt; для создания нового или переопределения уже существующего объекта, -а имя макроса указывается между двумя символами &lt;strong&gt;&amp;quot;@@&amp;quot;&lt;/strong&gt; и может содержать одну или нескольких лексем (терминов).&lt;/p&gt; -&lt;p&gt;Все макросы относятся к глобальному пространству имен, поэтому первый термин в имени макроса должен быть уникальным, -иначе он будет прекрывать имена локальных и глобальных переменных при &lt;a href=&#34;http://localhost:1313/docs/syntax/naming/&#34;&gt;разрешении имен&lt;/a&gt;, -если они указаны в коде без квалификаторов.&lt;/p&gt; -&lt;p&gt;??????????????????????? -Чистые (гигиеничные) макросы, &lt;strong&gt;::-&lt;/strong&gt; &lt;strong&gt;:-&lt;/strong&gt;, аргумента и переммые в которых гарантиованно не пересекаются с пространством имен программы?????????????????&lt;/p&gt; -&lt;p&gt;Телом макроса могут быть корректное выражение языка, последовательность лексем (которые заключается в двойные собачки &lt;strong&gt;&amp;quot;@@&amp;quot;&lt;/strong&gt;, -т.е. &lt;strong&gt;&lt;code&gt;@@ лексема1 лексема1 @@&lt;/code&gt;&lt;/strong&gt;) или обычная текстовая строка (которую нужно указать между тройными собачками &lt;strong&gt;&amp;quot;@@@&amp;quot;&lt;/strong&gt;, т.е. &lt;strong&gt;&lt;code&gt;@@@ текстовая строка @@@&lt;/code&gt;&lt;/strong&gt;).&lt;/p&gt; -&lt;p&gt;В имени макроса, кроме первого термина, могут присутствовать один или несколько шаблонов. -&lt;em&gt;Шаблон&lt;/em&gt; — это термин, который при сопоставлении последовательности лексем с идентификатором макроса -может заменяться любым другим одиночным термином (т.е. фактически это сопоставление по образцу/шаблону).&lt;/p&gt; -&lt;p&gt;Для создания термина-шаблона в начале его идентификатора нужно поставить знак доллара (что соответствует квалификатору локальной переменой), -т.е. имя макроса &lt;code&gt;@@ FUNC $name @@&lt;/code&gt; будет соответствовать последовательности лексем как &lt;code&gt;FUNC my_func_name&lt;/code&gt;, так и &lt;code&gt;FUNC other_name_func&lt;/code&gt;.&lt;/p&gt; -&lt;p&gt;Для удаления макроса используется специальный синтаксис: &lt;code&gt;@@@@ name @@@@;&lt;/code&gt; или &lt;code&gt;@@@@ два термина @@@@;&lt;/code&gt;, -т.е. необходимо указать идентификатор макроса между четырмя символами &lt;strong&gt;&amp;quot;@@@@&amp;quot;&lt;/strong&gt;.&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Тело макроса из текстовой строки (как в препроцессоре С/С++)&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@macro_str@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@@ строка - тело макроса @@@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Строка для лексера&lt;/span&gt; + &lt;p&gt;Macros are also used to transform the original code of &lt;em&gt;NewLang&lt;/em&gt; into a more familiar syntax based on &lt;a href=&#34;http://localhost:1313/docs/syntax/dsl/&#34;&gt;keywords&lt;/a&gt;, +as such text is much easier to understand when reading the original code later.&lt;/p&gt; +&lt;p&gt;In &lt;strong&gt;NewLang&lt;/strong&gt;, macros are one or more consecutive terms that are replaced with another term or a whole syntactic construction (a sequence of lexemes).&lt;/p&gt; +&lt;p&gt;Macros are processed during the operation of the &lt;strong&gt;lexer&lt;/strong&gt;, i.e., before passing the sequence of lexemes to the parser, +allowing fragments of the language syntax to be modified using macros, for example, when implementing custom DSL dialects.&lt;/p&gt; +&lt;h3 id=&#34;defining-macros&#34;&gt;Defining Macros&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#defining-macros&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; +&lt;p&gt;The definition of macros is similar to the &lt;a href=&#34;http://localhost:1313/docs/ops/create/&#34;&gt;definition&lt;/a&gt; of other objects and consists of three parts +&lt;strong&gt;&lt;macro name&gt; &amp;lt;creation/assignment operator&amp;gt; &lt;macro body&gt;&lt;/strong&gt; and ends with a semicolon &amp;ldquo;&lt;strong&gt;;&lt;/strong&gt;&amp;rdquo;, i.e., +normal operators &lt;strong&gt;::=&lt;/strong&gt;(&lt;strong&gt;::-&lt;/strong&gt;), &lt;strong&gt;=&lt;/strong&gt;, or &lt;strong&gt;:=&lt;/strong&gt;(&lt;strong&gt;:-&lt;/strong&gt;) are used to create a new or redefine an existing object, +and the macro name is indicated between two symbols &lt;strong&gt;&amp;quot;@@&amp;quot;&lt;/strong&gt; and can contain one or more lexemes (terms).&lt;/p&gt; +&lt;p&gt;All macros belong to the global namespace, so the first term in the macro name must be unique, +otherwise it will override local and global variables during &lt;a href=&#34;http://localhost:1313/docs/syntax/naming/#name-lookup&#34;&gt;name lookup&lt;/a&gt; +if they are written in the program text without &lt;a href=&#34;http://localhost:1313/docs/syntax/naming/#sigil&#34;&gt;qualifiers (sigils)&lt;/a&gt;.&lt;/p&gt; +&lt;p&gt;Using the operators &lt;strong&gt;::-&lt;/strong&gt; and &lt;strong&gt;:-&lt;/strong&gt; creates pure (hygienic) macros, arguments and variables in which are guaranteed not to intersect with the program&amp;rsquo;s namespace.&lt;/p&gt; +&lt;p&gt;The body of a macro can be a valid language expression, a sequence of lexemes (enclosed in double at symbols &lt;strong&gt;&amp;quot;@@&amp;quot;&lt;/strong&gt;, +i.e. &lt;strong&gt;&lt;code&gt;@@ lexeme1 lexeme2 @@&lt;/code&gt;&lt;/strong&gt;), or a regular text string (which should be specified between triple at symbols &lt;strong&gt;&amp;quot;@@@&amp;quot;&lt;/strong&gt;, +i.e. &lt;strong&gt;&lt;code&gt;@@@ text string @@@&lt;/code&gt;&lt;/strong&gt;).&lt;/p&gt; +&lt;p&gt;In the macro name after the first term, one or more templates may be present. +A &lt;em&gt;template&lt;/em&gt; is a term that, when matching a sequence of lexemes with the macro identifier, +can be replaced by any other single term (effectively, this is pattern/template matching).&lt;/p&gt; +&lt;p&gt;To create a template term, a dollar sign should be placed at the beginning of its identifier (which corresponds to a qualifier of a local variable), +i.e. the macro name &lt;code&gt;@@ FUNC $name @@&lt;/code&gt; will correspond to the sequence of lexemes as &lt;code&gt;FUNC my_func_name&lt;/code&gt; as well as &lt;code&gt;FUNC other_name_func&lt;/code&gt;.&lt;/p&gt; +&lt;p&gt;To remove a macro, a special syntax is used: &lt;code&gt;@@@@ name @@@@;&lt;/code&gt; or &lt;code&gt;@@@@ two terms @@@@;&lt;/code&gt;, +i.e. you need to specify the macro identifier between four characters &lt;strong&gt;&amp;quot;@@@@&amp;quot;&lt;/strong&gt;.&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Macro body from a text string (as in C/C++ preprocessor)&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@macro_str&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@@&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;macro&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;body&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@@&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# String for the lexer&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Удаления макроса @macro_str&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@@@ macro_str @@@@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;аргументы-макросов-и-их-раскрытие&#34;&gt;Аргументы макросов и их раскрытие&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d1%8b-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2-%d0%b8-%d0%b8%d1%85-%d1%80%d0%b0%d1%81%d0%ba%d1%80%d1%8b%d1%82%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Макросы можно определять как с аргументами (параметрами в скобках), так и без них. -Если макрос был определен с аргументами, то их проверка будет выполнятся макропроцессором при определении и раскрытии макроса. -Если макрос был определен без аргументов, то их наличие макропроцессором игнорируется.&lt;/p&gt; -&lt;p&gt;Так как макропроцессор считает макросы с аргументами и без оных идентичными, то нельзя создать два макроса -с одинаковыми именами, один из которых будет с аргументами (скобками), а другой без них.&lt;/p&gt; -&lt;p&gt;Поэтому, если требуется использовать макрос в двух разных вариантах (с аргументами и без них), -тогда следует определять макрос без аргументов и в этом случае контроль параметров будет производить компилятор.&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@macro@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; term&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Макрос без аргументов&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Removing macro @macro_str&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@@@&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;macro_str&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@@@&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;args&#34;&gt;Macro Arguments and Expansion&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#args&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; +&lt;p&gt;Macros can be defined with arguments (parameters in parentheses) or without them. +If a macro was defined with arguments, their validation will be performed by the macro processor during definition and expansion of the macro. +If a macro was defined without arguments, the presence of arguments will be ignored by the macro processor.&lt;/p&gt; +&lt;p&gt;The macroprocessor considers macros with and without arguments identical, +so it is not possible to create two macros with the same name, one with arguments (in parentheses) and the other without.&lt;/p&gt; +&lt;p&gt;Therefore, if you need to use a macro in two different ways (with arguments and without), +you should define the macro without arguments, and in this case, the parameter control will be done by the compiler.&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@ macro @@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; term&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Macro without arguments&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; macro&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;args&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# ОК -&amp;gt; term(args);&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; macro&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# ОК -&amp;gt; term;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; macro&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;args&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# OK -&amp;gt; term(args);&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; macro&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# OK -&amp;gt; term;&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Но &lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; term&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# But&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@ call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt; @@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; term&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# ОК -&amp;gt; term();&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; call&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Ошибка (@call определен с аргументами) &lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Если при определении макроса указаны аргументы, то место для их вставки в теле макроса -записывается как имя локальной переменой, перед которой добавлен символ &lt;strong&gt;&amp;quot;@&amp;quot;&lt;/strong&gt;, т.е. &lt;strong&gt;@$arg&lt;/strong&gt;.&lt;/p&gt; -&lt;p&gt;Произвольное количество аргументов у макроса отмечается троеточием &lt;strong&gt;&amp;quot;&amp;hellip;&amp;quot;&lt;/strong&gt;, а место для их вставки отмечается в теле макроса лексемой &lt;strong&gt;&amp;quot;@$&amp;hellip;&amp;quot;&lt;/strong&gt;.&lt;/p&gt; -&lt;p&gt;Место для вставки числа реально переданных аргументов отмечается лексемой &lt;strong&gt;&amp;quot;@$#&amp;quot;&lt;/strong&gt;. -Если требуется вставить переданные аргументы в виде элементов словаря, -то место для вставки отмечается лексемой &lt;strong&gt;&amp;quot;@$*&amp;quot;&lt;/strong&gt;.&lt;/p&gt; -&lt;p&gt;По аналогии с препроцессором С/С++, для соединения двух лексем в одну, в теле макроса используется оператор &lt;strong&gt;&amp;quot;@##&amp;quot;&lt;/strong&gt;, -а для преобразование лексемы в текстову строку применяется операторы &lt;strong&gt;@#&lt;/strong&gt;, &lt;strong&gt;@#&amp;quot;&lt;/strong&gt; или &lt;strong&gt;@#&amp;rsquo;&lt;/strong&gt;, например, -&lt;code&gt;@@macro($arg)@@ := @@ func_ @## @$arg( @#&amp;quot; arg ) @;&lt;/code&gt;, тогда вызов &lt;code&gt;macro(name);&lt;/code&gt; будет преобразован в &lt;code&gt;func_name (&amp;quot;name&amp;quot;);&lt;/code&gt;&lt;/p&gt; - - -&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; -&lt;h4 id=&#34;ограничения-макропроцессора-в-текущей-версии&#34;&gt;Ограничения макропроцессора в текущей версии&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%b3%d1%80%d0%b0%d0%bd%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d0%bf%d1%80%d0%be%d1%86%d0%b5%d1%81%d1%81%d0%be%d1%80%d0%b0-%d0%b2-%d1%82%d0%b5%d0%ba%d1%83%d1%89%d0%b5%d0%b9-%d0%b2%d0%b5%d1%80%d1%81%d0%b8%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h4&gt; -&lt;p&gt;На текущий момент макросы реализованы в минимальном объеме для самых простых сценариев использования:&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;DSL для keyword based syntax (if, else, return, match, while и т.д.) - (1 термин с произвольными аргументами и без) - требуется сейчас !!!&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;&lt;em&gt;Парсер при обработке макросов может анализировать информацию о типах данных, если она указана.&lt;/em&gt; -&lt;em&gt;Но на текущий момент типы данных в макросах никак не обрабатываются и это одна из обязательных фич, которая будет реализована в будущем.&lt;/em&gt;&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Определения (func, class) - (несколько терминов с аргументами и без аргументов) - Реализация ООП и импорт С++ классов&lt;/li&gt; -&lt;li&gt;Модификации при определениях (override) - (несколько терминов и шаблоны с аргументами и без аргументов) - Реализация ООП и импорт С++ классов&lt;/li&gt; -&lt;/ul&gt; - -&lt;/div&gt; - -&lt;h1 id=&#34;макросы-без-аргументов-или-все-аргументы-сразу-&#34;&gt;МАКРОСЫ БЕЗ АРГУМЕНТОВ ИЛИ ВСЕ АРГУМЕНТЫ СРАЗУ !!!!!&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b1%d0%b5%d0%b7-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d0%b8%d0%bb%d0%b8-%d0%b2%d1%81%d0%b5-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d1%8b-%d1%81%d1%80%d0%b0%d0%b7%d1%83-&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;h1 id=&#34;анализа-аргументов-или-их-типов-не-производится-&#34;&gt;анализа аргументов или их типов не производится !!!&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b0%d0%bd%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d0%b8%d0%bb%d0%b8-%d0%b8%d1%85-%d1%82%d0%b8%d0%bf%d0%be%d0%b2-%d0%bd%d0%b5-%d0%bf%d1%80%d0%be%d0%b8%d0%b7%d0%b2%d0%be%d0%b4%d0%b8%d1%82%d1%81%d1%8f-&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;Lambda -@@ lambda $name(&amp;hellip;) @@ ::= @@ @$name( @$&amp;hellip; ) ::= ( _( @$&amp;hellip; ) ::= @&lt;strong&gt;PRAGMA_FINALIZE&lt;/strong&gt;( @), {, {+, {-, {* ) @@&lt;/p&gt; -&lt;h3 id=&#34;примеры-использования-макросов&#34;&gt;Примеры использования макросов&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80%d1%8b-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Обычные макросы (тело макроса корректное выражение)&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@macro@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; replace&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@macro2&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;arg&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt; call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;@&lt;span style=&#34;color:#000&#34;&gt;$arg&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()}&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# OK -&amp;gt; term();&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; call&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Error (@call is defined with arguments) &lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If arguments are specified when defining a macro, the place for their insertion in the body of the macro is written +as the name of a local variable with the symbol &lt;strong&gt;&amp;quot;@&amp;quot;&lt;/strong&gt; added before it, i.e. &lt;strong&gt;@$arg&lt;/strong&gt;.&lt;/p&gt; +&lt;p&gt;The place for inserting the number of actual arguments passed is marked by the lexeme &lt;strong&gt;&amp;quot;@$#&amp;quot;&lt;/strong&gt;. +If it is necessary to insert the passed arguments as a dictionary, the place for insertion is marked by the lexeme &lt;strong&gt;&amp;quot;@$*&amp;quot;&lt;/strong&gt;.&lt;/p&gt; +&lt;p&gt;If the macro takes an arbitrary number of arguments (the macro arguments are terminated by an ellipsis), +the place for their insertion in the body of the macro is marked by the lexeme &lt;strong&gt;&amp;quot;@$&amp;hellip;&amp;quot;&lt;/strong&gt;.&lt;/p&gt; +&lt;p&gt;Analogous to the C/C++ preprocessor, to concatenate two lexemes into one, the operator &lt;strong&gt;&amp;quot;@##&amp;quot;&lt;/strong&gt; is used in the body of the macro, +and to convert a lexeme into a text string, the operators &lt;strong&gt;@#&lt;/strong&gt;, &lt;strong&gt;@#&amp;quot;&lt;/strong&gt;, or &lt;strong&gt;@#&amp;rsquo;&lt;/strong&gt; are applied, for example, +&lt;code&gt;@@macro($arg)@@ := @@ func_ @## @$arg( @#&amp;quot; arg ) @;&lt;/code&gt;, then the call &lt;code&gt;macro(name);&lt;/code&gt; will be transformed into &lt;code&gt;func_name (&amp;quot;name&amp;quot;);&lt;/code&gt;&lt;/p&gt; +&lt;p&gt;Examples of using macros:&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Ordinary macros (the body of the macro is a correct expression)&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;macro&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;replace&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;();&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;macro2&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;arg&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;call&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;arg&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;call&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;()};&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Тело макросов из последовательности лексем&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@if&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;...&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@ &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;\$&lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;*&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;--&amp;gt; @@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Выражение может быть не полным&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@elif&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;...&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@ ,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;\$&lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;elif&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;*&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;--&amp;gt; @@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@else@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@ ,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;_&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;--&amp;gt; @@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# The body of the macros from a sequence of tokens&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# The expression may not be complete&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;elif&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,[&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,[&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Запись условного оператора с использованием &lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# определенных выше макросов&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt; condition &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;){&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ... -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;elif&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt; condition2 &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ... -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ... -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Зачем нужна трансформация синтаксиса? -Нативная поддержка других языков нужна чтобы не переписывать легаси код на этих языках.&lt;/p&gt; -&lt;p&gt;Чтобы можно было использовать существующие исходники как собственные требуется настройка работы -препроцессора и лексера под конкретный язык программирования (описание DSL). -Для &lt;strong&gt;С/С++&lt;/strong&gt; потребуется выделять лексером комментарии из-за пересечения синтаксиса (которые сейчас игнорируются). -Для &lt;strong&gt;Python&lt;/strong&gt; требуется выделять лексером отступы (которые сейчас тоже игнорируются), причем потребуется реализация не только синтаксиса, -но и зависимых пакетов с последующая трансляцией этого кода в С++, что в настоящий момент делать не целесообразно (cython ???).&lt;/p&gt; -&lt;p&gt;Но так как возможность трансформации кода с других языков программирования принципиальная возможна, -стоит над этим думать только после полноценного релиза NewLang и его перехода в прод.&lt;/p&gt; -&lt;p&gt;Для реализации DSL требуется передача команд в парсер для управления его работой (по аналогии с командой #pragma) -Но так как обработка таких команд должна происходить в лексере до передачи данных в парсер (анализатор), -то команды для макропроцессора должны быть в максимально простом виде и состоять из элементов, -которые лексер может самостоятельно идентифицировать, т.е. термины, строки и цифры (без выражений и именованных аргументов).&lt;/p&gt; -&lt;p&gt;После обработки такой команды она анализируется макропроцессором и удаляется из потока лексем, т.е. в парсер (анализатор) не передается. -Но в случае ошибки с синтаксисе, данные команды нужно уметь однозначно идентифировать и самый простой способ, -комбинация признака макроса и системного имени, т.е. что-то вроде&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; @__PRAGMA_DIAG__(push) - @__PRAGMA_DIAG__(ignored, &amp;#34;-Wundef&amp;#34;) - @__PRAGMA_DIAG__(warning, &amp;#34;-Wformat&amp;#34;) - @__PRAGMA_DIAG__(error &amp;#34;-Wuninitialized&amp;#34;) - @__PRAGMA_DIAG__(pop) - - #pragma message &amp;#34;Compiling &amp;#34; __FILE__ &amp;#34;...&amp;#34; - @__PRAGMA_MESSAGE__(&amp;#34;Compiling &amp;#34;, __FILE__, &amp;#34;...&amp;#34;) - - #pragma error &amp;#34;Error &amp;#34; __FILE__ &amp;#34;...&amp;#34; - @__PRAGMA_ERROR__(&amp;#34;Error &amp;#34;, __FILE__, &amp;#34;...&amp;#34;) - - -#define DO_PRAGMA(x) _Pragma (#x) -#define TODO(x) DO_PRAGMA(message (&amp;#34;TODO - &amp;#34; #x)) - -@@TODO( ... )@@ := @__PRAGMA_MESSAGE__(&amp;#34;TODO - &amp;#34;, @*) - -@TODO(Remember to fix this) # note: TODO - Remember to fix this - -\\.__lexer__ignore_space__ = 1; -\\.__lexer__ignore_indent__ = 1; -\\.__lexer__ignore_comment__ = 1; -\\.__lexer__ignore_crlf__ = 1; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Таким образом можно трансформировать условный оператор на питоне в синтаксис NewLang следующим макросом:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; -#pragma clang attribute push -#pragma clang diagnostic ignored &amp;#34;-Wundef&amp;#34; -#pragma clang diagnostic ignored &amp;#34;-Wunused-variable&amp;#34; - - -#elif __GNUC__ - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored &amp;#34;-Wuninitialized&amp;#34; - -#pragma GCC diagnostic ignored &amp;#34;-Wall&amp;#34; -#pragma GCC diagnostic ignored &amp;#34;-Wextra&amp;#34; - - @pragma warning(pop) - - @@ pragma warning(...) @@ := __PRAGMA_TERM_DIAG_WARNING__(); -@__PRAGMA_DIAG__(warning, pop); - -Обработка терминов в макропроцессоре в максимально простом виде. -Агрументы только термины, строки и цифры без вложенных выражений и именованных аргументов, -т.е. только элементы, которые может самостоятельно идентифицировать лексер. - -@warning(&amp;#34;--&amp;#34;) - @@ if ... : @@ := @@ [ @$* ]-&amp;gt; __TERM_BLOCK_INDENT__(&amp;#34;{&amp;#34;, force_semicolon=1) @@ - - if __name__ == &amp;#34;__main__&amp;#34;: - run1() - run2() - - [ __name__ == &amp;#34;__main__&amp;#34; ]-&amp;gt; { - run1(); - run2(); - }; - - -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ключ &amp;ndash;parser-syntax-only только текстовый парсинг исходного кода без загрузки модулей, раскрытия макросов и проверки имен.&lt;/p&gt; -&lt;p&gt;Ключ &amp;ndash;parser-no-macros - без раскрытия макросов -Ключ &amp;ndash;parser-no-module - без загрузки модулей (и мокросов, если они в них определяются) -Ключ &amp;ndash;parser-no-check-prototype - без проверки имен при обращении&lt;/p&gt; -&lt;p&gt;prototype -@&lt;strong&gt;PRAGMA_PROTOTYPE&lt;/strong&gt;(define) -@&lt;strong&gt;PRAGMA_PROTOTYPE&lt;/strong&gt;(implement)&lt;/p&gt; -&lt;p&gt;$$&lt;/p&gt; -&lt;p&gt;\$ - корень системы (система)&lt;/p&gt; -&lt;p&gt;$ - текущий модуль&lt;/p&gt; -&lt;h1 id=&#34;макросы-для-конвертора-проверки-в-python&#34;&gt;Макросы для конвертора проверки в Python&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b4%d0%bb%d1%8f-%d0%ba%d0%be%d0%bd%d0%b2%d0%b5%d1%80%d1%82%d0%be%d1%80%d0%b0-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b8-%d0%b2-python&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;h1 id=&#34;if-__name__--__main__&#34;&gt;if &lt;strong&gt;name&lt;/strong&gt; == &amp;ldquo;&lt;strong&gt;main&lt;/strong&gt;&amp;rdquo;:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#if-__name__--__main__&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;@@ &lt;strong&gt;name&lt;/strong&gt; @@ ::= @@ $. @&lt;strong&gt;PRAGMA_NO_MACRO&lt;/strong&gt;() &lt;strong&gt;name&lt;/strong&gt; @@ -@@ if $&amp;hellip; @: @@ ::= @@ [ @$&amp;hellip; ] &amp;ndash;&amp;gt; @@&lt;/p&gt; -&lt;p&gt;@if( $.&lt;strong&gt;name&lt;/strong&gt; == &amp;ldquo;&lt;strong&gt;main&lt;/strong&gt;&amp;rdquo; ) {&lt;/p&gt; -&lt;p&gt;}&lt;/p&gt; -&lt;p&gt;\каталог\модуль() - статический импорт модуля -\(&amp;ldquo;каталог\модуль&amp;rdquo;)() - динамический импорт модуля&lt;/p&gt; -&lt;p&gt;printf := :Pointer(&amp;lsquo;printf(format:FmtChar, &amp;hellip;):Int32&amp;rsquo;); -printf := %printf(format:FmtChar, &amp;hellip;):Int32;&lt;/p&gt; -&lt;h1 id=&#34;регистрация-прототипа-нативной-функции&#34;&gt;Регистрация прототипа нативной функции&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%80%d0%b5%d0%b3%d0%b8%d1%81%d1%82%d1%80%d0%b0%d1%86%d0%b8%d1%8f-%d0%bf%d1%80%d0%be%d1%82%d0%be%d1%82%d0%b8%d0%bf%d0%b0-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;@prototype -%puts(format:StrChar):Int32;&lt;/p&gt; -&lt;h1 id=&#34;импорт-нативной-функции-с-предварительной-проверкой-её-наличия-во-время-компиляции-статическая-линковка&#34;&gt;Импорт нативной функции с предварительной проверкой её наличия во время компиляции (статическая линковка)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b8%d0%bc%d0%bf%d0%be%d1%80%d1%82-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d1%81-%d0%bf%d1%80%d0%b5%d0%b4%d0%b2%d0%b0%d1%80%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d0%be%d0%b9-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%be%d0%b9-%d0%b5%d1%91-%d0%bd%d0%b0%d0%bb%d0%b8%d1%87%d0%b8%d1%8f-%d0%b2%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d1%8f-%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%86%d0%b8%d0%b8-%d1%81%d1%82%d0%b0%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bb%d0%b8%d0%bd%d0%ba%d0%be%d0%b2%d0%ba%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;puts2(format:StrChar):Int32 := %puts(format:StrChar):Int32;&lt;/p&gt; -&lt;h1 id=&#34;импорт-нативной-функции-по-её-прототипу-во-время-выполнения-динамическая-линковка&#34;&gt;Импорт нативной функции по её прототипу во время выполнения (динамическая линковка)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b8%d0%bc%d0%bf%d0%be%d1%80%d1%82-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d0%bf%d0%be-%d0%b5%d1%91-%d0%bf%d1%80%d0%be%d1%82%d0%be%d1%82%d0%b8%d0%bf%d1%83-%d0%b2%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d1%8f-%d0%b2%d1%8b%d0%bf%d0%be%d0%bb%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b4%d0%b8%d0%bd%d0%b0%d0%bc%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bb%d0%b8%d0%bd%d0%ba%d0%be%d0%b2%d0%ba%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;puts3(format:StrChar):Int32 := :Pointer(&amp;lsquo;puts(format:StrChar):Int32&amp;rsquo;);&lt;/p&gt; -&lt;p&gt;%puts(&amp;lsquo;Тест вывода строки&amp;rsquo;); # Линковка с нативной функцией во время компиляции и непосредственный вызов с оптимизацией передачи параметров -puts2(&amp;lsquo;Тест 2 вывода строки&amp;rsquo;); # Линковка с нативной функцией во время компиляции -puts3(&amp;lsquo;Тест 3 вывода строки&amp;rsquo;); # Линковка с нативной функцией во время выполнения при первом вызове puts3&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Парсинг исходного текста без раскрытия макросов и загрузки модулей&lt;/li&gt; -&lt;li&gt;Парсинг исходного текста с раскрытием макросов (требуется загрузка модулей для зависимых и переопределяемых макросов)&lt;/li&gt; -&lt;li&gt;Загружатся модули могут как в виде исходников (которые требуется парсить и компилировть/выполнять) -или в виде бинарников (в них должны быть список макросов, типов и имена объектов)&lt;/li&gt; -&lt;li&gt;После парсинга получается список &lt;strong&gt;имен&lt;/strong&gt; макросов, типов и объектов (TermPtr)&lt;/li&gt; -&lt;li&gt;После выполнения модуля - список &lt;strong&gt;имен&lt;/strong&gt; заполняется реальными объектами (ObjPtr).&lt;/li&gt; -&lt;/ul&gt; -&lt;h1 id=&#34;компиляция-файла&#34;&gt;Компиляция файла&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%86%d0%b8%d1%8f-%d1%84%d0%b0%d0%b9%d0%bb%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;ul&gt; -&lt;li&gt;Парсинг исходника для построения AST (без анализа имен, связей, загрузки модулей и пр. только исходые тексты с раскрытием макросов&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;/ul&gt; -&lt;h1 id=&#34;систематизация-реализации-макросов&#34;&gt;Систематизация реализации макросов&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0%d1%82%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d1%80%d0%b5%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d0%b8-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;последовательность лексем MACRO_SEQ мужду @@ @@ сохраняется в m_block, так как фрагменты блоков не могут быть идентификаторами&lt;/p&gt; -&lt;p&gt;Разбор макросов происходит в лексере. Определением макроса всегда является целая строка, -которая заканчивается точкой с запятой, а идентификатором макроса всегда выступает последовательность лексем:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@ id @@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; macro&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@ id @@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@ @@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@ id @@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@@ @@@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Хранилищем текущих максросов является объект класса MacroBuffer. -Последовательность лексем идентификатора (id) макроса должна сохраняется в отдельном поле термина и однозначно его идентифицирует. -Первый термин в идентификаторе хранится как ключ hashmap, а дальше происходит поиск полным перебором. -Этапы работы с макросами&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt; -&lt;p&gt;Входные термины из лексера получаются вызовом GetNextToken, внутри которой и происходит раскрытие макросов. -Внутренний буфер заполняется до окончания строки (выражения), т.е. до символа &amp;lsquo;;&amp;rsquo; или &lt;END&gt;, после чего производится -поиск макросов в объекте MacroBuffer для текущей последовательности лексем в буфере.&lt;/p&gt; -&lt;/li&gt; -&lt;li&gt; -&lt;p&gt;Если макрос найден, то соответствющая ему последоваетльность заменяется на тело макроса и происходит переход -на повторный анализ входного буфера.&lt;/p&gt; -&lt;/li&gt; -&lt;li&gt; -&lt;p&gt;Если макрос не найден, то данные передаются в парсер для дальнейшего синтаксическго анализа.&lt;/p&gt; -&lt;/li&gt; -&lt;li&gt; -&lt;p&gt;Для этого во входном потоке лексем (parser.y) во время оператората создания/присвоения вызывается функция проверки на макрос. -MacroBuffer::CheckMacroAndConvertDel($$), и после этого выходному значению присваивается результат выполнения driver.MacroEval($$), -и в дальнейшем этот макрос никак не обработывается.&lt;/p&gt; -&lt;/li&gt; -&lt;li&gt; -&lt;p&gt;Создание макросов, проверка на дубликаты и логические ошибки в определении происходит путем обращения к методам объекта MacroBuffer.&lt;/p&gt; -&lt;p&gt;/*&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Макросы хрянтся как фрагменты AST в виде объектов типа Term,&lt;/li&gt; -&lt;li&gt;так как создаются после обработки парсером по правилам стандратной грамматики.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Но анализ входных данных на предмет раскрытия макросов проиходит из потока (последовательности) лексем,&lt;/li&gt; -&lt;li&gt;т.е. &lt;strong&gt;ДО&lt;/strong&gt; обработки парсером, так как при раскрытии макросов может меняться грамматика выражений.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Функция \ref CompareMacro сравнивает входной буфер (последовательность лексем)&lt;/li&gt; -&lt;li&gt;на предмет возможного соответствия одному конкретному макросу.&lt;/li&gt; -&lt;li&gt;Сравниваются только ключевые словам без учета аргументов в скобках,&lt;/li&gt; -&lt;li&gt;но само наличие аргументов проверяется ??????????????????&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Проблема:&lt;/li&gt; -&lt;li&gt;К функции можно обратится с целью её вызова (указав после имени скобки),&lt;/li&gt; -&lt;li&gt;так и по имени без скобок (например для получения ссылки на объект).&lt;/li&gt; -&lt;li&gt;Так и к переменной можно обратиться только по имени,&lt;/li&gt; -&lt;li&gt;так и указав скобки после имени как к функции (при копировании объекта).&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Сделать один макрос под оба сценария (со скобками и без скобок) не получится, так как непонятно,&lt;/li&gt; -&lt;li&gt;что делать с аргументами при раскрытии тела макроса, когда они не указаны.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Но может быть следует переименовывать только одно имя без учета скобок,&lt;/li&gt; -&lt;li&gt;например, оставив такую возможность только для одиночных макросов.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;\name -&amp;gt; name или name (&amp;hellip;), hash: name&lt;/li&gt; -&lt;li&gt;но \name(&amp;hellip;) -&amp;gt; name(&amp;hellip;), а name - ошибка !!!! hash: name&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Или все же следует различать макросы со скобками и без скобок как два разных объекта???&lt;/li&gt; -&lt;li&gt;\name := name2; и \name(&amp;hellip;) := name2(&amp;hellip;); будут разными объектами&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Или добавить макросы-алиасы без аргументов только для переименования отдельных терминов?&lt;/li&gt; -&lt;li&gt;\alias :- name2; но как их отличать от обычных макросов в операции удаления?&lt;/li&gt; -&lt;li&gt;Или вообще не нужно отличать и оставить только один варинат (либо макрос, либо алиас)&lt;/li&gt; -&lt;li&gt;Тода вопрос со скобками закрывается сам собой, алиасы всегда без скобок,&lt;/li&gt; -&lt;li&gt;макросы со скбками или без скобок, но должно быть полное соответствие.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;@ name name2 @ -&amp;gt; name name2, но name name2(&amp;hellip;) - ошибка!!! (hash: name,name2)&lt;/li&gt; -&lt;li&gt;@ name name2(&amp;hellip;) @ -&amp;gt; name name2(&amp;hellip;), но name name2 - ошибка !!!! (hash: name,name2)&lt;/li&gt; -&lt;li&gt;@ name name2&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; @ -&amp;gt; name name2&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt;, но name name2 - ошибка !!!! ( hash: name,name2 )&lt;/li&gt; -&lt;li&gt;@ name $tmpl&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; name3@ -&amp;gt; name $tmpl&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Но!&lt;/li&gt; -&lt;li&gt;@ name name2 @ ::- -&amp;gt; name name2 - ок, но name name2(&amp;hellip;) - ок&lt;/li&gt; -&lt;li&gt;@ name $tmpl name3@ ::- -&amp;gt; name $tmpl&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; name3 - ок, name $tmpl(&amp;hellip;) name3[&amp;hellip;] - ок&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Для последовательности лексем требуется полное соответствие с учетом скобок ???&lt;/li&gt; -&lt;li&gt;и может ли быть несколько скобок одного типа (несколько крыглях, или несколько квардратных????&lt;/li&gt; -&lt;li&gt;&amp;lt;Может быть несколько скобок одного типа, например, при указании типа у аргументов или типа возвращаемого значения.&amp;gt;&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;@ name name2 @ -&amp;gt; name name2, но name name2(&amp;hellip;) - ошибка!!! (hash: name,name2)&lt;/li&gt; -&lt;li&gt;@ name name2(&amp;hellip;) @ -&amp;gt; name name2(&amp;hellip;), но name name2 - ошибка !!!! (hash: name,name2)&lt;/li&gt; -&lt;li&gt;@ name name2&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; @ -&amp;gt; name name2&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt;, но name name2 - ошибка !!!! ( hash: name,name2 )&lt;/li&gt; -&lt;li&gt;@ name $tmpl&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; name3@ -&amp;gt; name $tmpl&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Проблема скобок возникает из-за сценария замены одного термина на другой,&lt;/li&gt; -&lt;li&gt;который есть в препроцессоре С/С++, но отсутствует при реализации с использованием шаблонов.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;*/&lt;/p&gt; -&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;Макросы используются и для превращеня исходного кода &lt;em&gt;NewLang&lt;/em&gt; в более привычный синтаксис на основе &lt;a href=&#34;https://newlang.net/syntax_dsl.html&#34;&gt;ключевых слов&lt;/a&gt;, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода.&lt;/p&gt; -&lt;p&gt;&lt;a href=&#34;https://newlang.net/syntax_dsl.html&#34;&gt;Например:&lt;/a&gt;.&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; @@if(...)@@ ::= @@ [ \$* ]--&amp;gt; @@; - @@while(...)@@ ::= @@ [\$*] &amp;lt;-&amp;gt; @@; - @@return $arg@@::= @@ -- \$arg -- @@; - @@true@@ ::= 1; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Тогда цикл до 5:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;count:=1; -[ 1 ] &amp;lt;-&amp;gt; { - [count&amp;gt;5] --&amp;gt; { - -- 42 --; - }; - count+=1; -}; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;будет выглядеть более привычно&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;count:=1; -while( true ) { - if(count&amp;gt;5) { - return 42; - }; - count+=1; -}; -&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;идеи-на-будущее&#34;&gt;Идеи на будущее&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b8%d0%b4%d0%b5%d0%b8-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h3 id=&#34;символьное-программирование&#34;&gt;Символьное программирование&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d0%bc%d0%b2%d0%be%d0%bb%d1%8c%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;blockquote&gt; -&lt;p&gt;Символьное программирование, часто называемое декларативным программированием, представляет собой парадигму программирования, которая использует математическую логику, отношения и символы для представления знаний и помощи в решении проблем. Вместо того, чтобы сосредотачиваться на описании последовательности операций, необходимых для выполнения вычислений, как в императивном программировании, символическое программирование делает упор на выражении отношений и ограничений между структурами данных, уделяя особое внимание «что», а не «как».&lt;/p&gt; -&lt;p&gt;В контексте парадигм программирования символическое программирование часто противопоставляется процедурному или императивному программированию, где программы определяют пошаговые процедуры для достижения своих целей. В то время как императивное программирование фокусируется на описании потока управления с использованием таких конструкций, как циклы и условные выражения, для управления выполнением, символическое программирование сосредоточено на выражении фактов о проблеме и позволяет выполнению естественным образом выводить последующие последствия из предоставленной информации.&lt;/p&gt; -&lt;p&gt;Одним из основных преимуществ символьного программирования является его способность обеспечивать более высокий уровень абстракции, что упрощает анализ кода и снижает вероятность ошибок. Непосредственно выражая отношения и ограничения, символическое программирование позволяет разработчикам сосредоточиться на моделировании и спецификации проблем, позволяя базовой системе управлять реализацией и выполнением алгоритмов.&lt;/p&gt; -&lt;p&gt;Существует несколько языков программирования и сред, использующих парадигму символьного программирования, например Prolog, Lisp и Haskell. Например, Пролог — это язык логического программирования, который позволяет разработчикам выражать взаимосвязи и факты о проблемных областях, в то время как выполнение автоматически обосновывает и извлекает новые факты на основе исходной информации. В том же духе Лисп, функциональный язык программирования, использует символьные вычисления для манипулирования структурами данных и выполнения сложных операций над ними, используя краткий и математически обоснованный синтаксис. Haskell, еще один функциональный язык программирования, использует строгую типизацию и ленивые вычисления, чтобы обеспечить символическое рассуждение и облегчить эффективное создание программ.&lt;/p&gt; -&lt;p&gt;Символьное программирование может быть полезным в широком спектре проблемных областей, включая искусственный интеллект, экспертные системы, программирование логики ограничений и символьную математику, среди других. Более высокий уровень абстракции, обеспечиваемый декларативными языками программирования, облегчает разработку сложных систем, сводя к минимуму вероятность ошибки и улучшая удобство обслуживания. В частности, использование символьного программирования в искусственном интеллекте позволяет разработчикам создавать системы представления знаний и механизмы рассуждения, которые можно применять для обработки естественного языка, машинного обучения и автоматического доказательства теорем.&lt;/p&gt; -&lt;/blockquote&gt; -&lt;p&gt;Различие между символьным программированием и препроцессором&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Задача препроцессора - раскрыть(расширить) макрос, тогда как при символьном программировании нужно сокращать (сворачивать) выражения&lt;/li&gt; -&lt;li&gt;Препроцессор обрабатывает последовательности лексем (плоские данные), тогда как символьное программирование оперирует выражениями (деревом лексем)&lt;/li&gt; -&lt;li&gt;Макрос у препроцессора идентифицируется первым термином, и если макрос не может быть раскрыт, то возникает ошибка. В символьном программировани требуется точное соответствие всего выражения и только в этом случае производится сокращение выражения.&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;Предпосылки для реализации символьного программирования -Компилятор - интерепретатор с REPL и обработка AST как во время компиляции, так и во время выполнения. -Необходимо добавить конструкции для определения правил символьного программрования (чистые функции?) -Необходимо добавить конструкцию для вычисления выражений в символьном программировании.&lt;/p&gt; -&lt;p&gt;Wolfram -&lt;a href=&#34;https://habr.com/articles/772984/&#34;&gt;https://habr.com/articles/772984/&lt;/a&gt;&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;diffRules = { - Sin[x] -&amp;gt; Cos[x], - Cos[x] -&amp;gt; -Sin[x], - x^2 -&amp;gt; 2*x, - x -&amp;gt; 1, - Log[x] -&amp;gt; 1/x -}; -&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;diffRules := ( - Sin(x) @-&amp;gt; Cos(x), - Cos(x) @-&amp;gt; -Sin(x), - x^2 @-&amp;gt; 2*x, - x @-&amp;gt; 1, - Log(x) @-&amp;gt; 1\x, -); - -expr @-&amp;gt; Sin(x) - x^2 + Log(x); - -# И применим к нему правила дифференцирования - -#expr /. diffRules -#(* 1/x - 2 x + Cos[x] *) - -sym := SymEval(expr, diffRules); -res := Eval(sym, x=0.123); -&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;expr = a^2 + 3 * b^3 - c^4 + 2 * x^2 - x + 4*c + 3 - -И я хочу это выражение линеаризовать, т.е. отбросить все степени выше первой. Я могу сделать это напрямую, как в примерах выше: - -expr /. { - a^2 -&amp;gt; 0, - b^3 -&amp;gt; 0, - c^4 -&amp;gt; 0, - x^2 -&amp;gt; 0 -} -(* 3 + 4 c - x *) - -Но это слишком неудобно. Что если я не знаю ни точную степень, ни имя переменной? Как просто указать, что нужно заменить все места, где встречается возведение в степень на ноль? Это можно сделать при помощи шаблонов вот так: - -expr /. Power[_, _] -&amp;gt; 0 -(* 3 + 4 c - x *) - -Либо вот так: - -expr /. _ ^ _ -&amp;gt; 0 -(* 3 + 4 c - x *) -&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;:diffRules() := { - {@ Sin(x) @} ::- {@ Cos(x) @}; - Cos(x) @-&amp;gt; -Sin(x), - x^2 @-&amp;gt; 2*x, - x @-&amp;gt; 1, - Log(x) @-&amp;gt; 1\x, -}; - -expr @-&amp;gt; Sin(x) - x^2 + Log(x); - -# И применим к нему правила дифференцирования - -#expr /. diffRules -#(* 1/x - 2 x + Cos[x] *) - -sym := SymEval(expr, diffRules); -res := Eval(sym, x=0.123); -&lt;/code&gt;&lt;/pre&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Writing a conditional statement using&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# the macros defined above&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@if&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;condition&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;){&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@elif&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;condition2&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@else&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For example, a loop up to 5:&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;5&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;42&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;+=&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will look more familiar:&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@while&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;true&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@if&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;5&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@return&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;42&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; </description> </item> @@ -1596,235 +1271,145 @@ my_file.write(&amp;lsquo;hello world&amp;rsquo;)&lt;/p&gt; <description> - &lt;h2 id=&#34;dsl&#34;&gt;DSL&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#dsl&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h3 id=&#34;features-of-associative-memory&#34;&gt;Features of associative memory&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#features-of-associative-memory&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; + &lt;h3 id=&#34;features-of-associative-memory&#34;&gt;Features of associative memory&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#features-of-associative-memory&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;The syntax of the &lt;em&gt;NewLang&lt;/em&gt; language is based on strict rules without the use of keywords, and no matter how logical it may seem, association by keywords is much easier to remember, for example, &lt;strong&gt;if&lt;/strong&gt;, than the combination &lt;em&gt;minus minus right angle bracket&lt;/em&gt; &lt;strong&gt;&amp;ndash;&amp;gt;&lt;/strong&gt;. Because of this, it makes sense to use not a &amp;ldquo;pure&amp;rdquo; basic syntax, but a more familiar dialect with the use of keywords.&lt;/p&gt; -&lt;h3 id=&#34;syntax-based-on-keywords&#34;&gt;Syntax based on keywords&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#syntax-based-on-keywords&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;In the dsl.nlp file, there is a set of macros that expand the basic syntax of &lt;em&gt;NewLang&lt;/em&gt;, based on rules, -with a set of predefined keywords as in classical programming languages. -And if necessary, they can be adapted or supplemented for your own domain.&lt;/p&gt; -&lt;h2 id=&#34;константы&#34;&gt;Константы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%ba%d0%be%d0%bd%d1%81%d1%82%d0%b0%d0%bd%d1%82%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h3 id=&#34;логические&#34;&gt;Логические&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bb%d0%be%d0%b3%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; +&lt;p&gt;&lt;em&gt;NewLang&lt;/em&gt; already contains a set of macros that extend the basic rule-based syntax of &lt;em&gt;NewLang&lt;/em&gt;, +a set of predefined keywords as in classical programming languages, +which can be adapted or supplemented to suit your own subject area.&lt;/p&gt; +&lt;h3 id=&#34;constants&#34;&gt;Constants&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#constants&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; -&lt;li&gt;&lt;strong&gt;true&lt;/strong&gt; - 1&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;yes&lt;/strong&gt; - 1&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;false&lt;/strong&gt; - 0&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;no&lt;/strong&gt; - 0&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@true&lt;/em&gt; - 1&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@yes&lt;/em&gt; - 1&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@false&lt;/em&gt; - 0&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@no&lt;/em&gt; - 0&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@this&lt;/em&gt; или &lt;em&gt;@self&lt;/em&gt; - Current object&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@super&lt;/em&gt; - Parent object&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@latter&lt;/em&gt; or &lt;em&gt;@last&lt;/em&gt;- Result of the last operation&lt;/p&gt; +&lt;/li&gt; &lt;/ul&gt; -&lt;h3 id=&#34;системные-имена&#34;&gt;Системные имена&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%8b%d0%b5-%d0%b8%d0%bc%d0%b5%d0%bd%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; +&lt;h3 id=&#34;logical-operators&#34;&gt;Logical operators&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#logical-operators&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; -&lt;li&gt;&lt;strong&gt;this&lt;/strong&gt; - Текущий объект (&lt;strong&gt;$0&lt;/strong&gt;)&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;parent&lt;/strong&gt; - Родительский объект (&lt;strong&gt;$$&lt;/strong&gt;)&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;last&lt;/strong&gt; - Результат выполнения последнего оператора (&lt;strong&gt;$^&lt;/strong&gt;)&lt;/li&gt; +&lt;li&gt;&lt;em&gt;@and&lt;/em&gt; - Logical &lt;strong&gt;AND&lt;/strong&gt;&lt;/li&gt; +&lt;li&gt;&lt;em&gt;@or&lt;/em&gt; - Logical &lt;strong&gt;OR&lt;/strong&gt;&lt;/li&gt; +&lt;li&gt;&lt;em&gt;@xor&lt;/em&gt; - Logical &lt;strong&gt;Exclusive OR&lt;/strong&gt;&lt;/li&gt; +&lt;li&gt;&lt;em&gt;@not(value)&lt;/em&gt; - Logical negation&lt;/li&gt; &lt;/ul&gt; -&lt;p&gt;!!!!!!!!- &lt;strong&gt;args&lt;/strong&gt; - Все аргументы функции (&lt;strong&gt;$*&lt;/strong&gt;)&lt;/p&gt; -&lt;p&gt;!!!!!!!!- &lt;strong&gt;sys&lt;/strong&gt; - Системный контекст запущенной программы (&lt;strong&gt;@@&lt;/strong&gt;) -!!!!!!!!- &lt;strong&gt;current&lt;/strong&gt; - Текущий модуль (&lt;strong&gt;@$&lt;/strong&gt;) -!!!!!!!!- &lt;strong&gt;cmd&lt;/strong&gt; - Все аргументы выполняющегося приложения из командной строки (&lt;strong&gt;@*&lt;/strong&gt;)&lt;/p&gt; -&lt;p&gt;!!!!!!!!!!1### Типовые функции и проверки -!!!!!!!!!!- &lt;strong&gt;run(&amp;lsquo;filename&amp;rsquo;)&lt;/strong&gt; - Выполнить указанный файл (&lt;strong&gt;@@(&amp;lsquo;filename&amp;rsquo;)&lt;/strong&gt;) -!!!!!!!!!!- &lt;strong&gt;ifmain&lt;/strong&gt; - Проверка, если текущий модуль основной (&lt;strong&gt;[@$.$0] &amp;ndash;&amp;gt;&lt;/strong&gt; { &amp;hellip; }) -!!!!!!!!!!- &lt;strong&gt;ifload&lt;/strong&gt; - Проверка, если текущий модуль загружается впервые (&lt;strong&gt;[@$.&lt;strong&gt;load&lt;/strong&gt;] &amp;ndash;&amp;gt;&lt;/strong&gt; { &amp;hellip; })&lt;/p&gt; -&lt;h3 id=&#34;операторы&#34;&gt;Операторы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; +&lt;h3 id=&#34;operators&#34;&gt;Operators&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#operators&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;match(cond)&lt;/strong&gt; - Оператор &lt;a href=&#34;https://newlang.net/ops.html#%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B0-%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&#34;&gt;оценки выражения&lt;/a&gt;&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@if(&amp;hellip;)&lt;/em&gt; - First conditional statement&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;if(&amp;hellip;)&lt;/strong&gt; - Первый условный оператор (&lt;strong&gt;[$*]&amp;ndash;&amp;gt;&lt;/strong&gt; { &amp;hellip; })&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@elif(&amp;hellip;)&lt;/em&gt; - Second and all subsequent conditional statements&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;elif(&amp;hellip;)&lt;/strong&gt; - Второй и все последующие (&lt;strong&gt;,[$*]&amp;ndash;&amp;gt;&lt;/strong&gt; { &amp;hellip; })&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@else&lt;/em&gt; - Operator &lt;em&gt;otherwise&lt;/em&gt;&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;else&lt;/strong&gt; - Оператор &lt;em&gt;иначе&lt;/em&gt; (&lt;strong&gt;,[_]&amp;ndash;&amp;gt;&lt;/strong&gt; { &amp;hellip; })&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@while(&amp;hellip;)&lt;/em&gt; - Loop operator with precondition&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;while(cond)&lt;/strong&gt; - Оператор цикла с предусловием (&lt;strong&gt;[@$cond] &amp;lt;-&amp;gt;&lt;/strong&gt; { &amp;hellip; } )&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@dowhile(&amp;hellip;)&lt;/em&gt; - Loop operator with postcondition&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;dowhile(cond)&lt;/strong&gt; - Оператор цикла с постусловием ({ &amp;hellip; } &lt;strong&gt;&amp;lt;-&amp;gt;[@$cond]&lt;/strong&gt;)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@loop&lt;/em&gt; - Infinite loop operator&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;iter(obj, &amp;hellip; )&lt;/strong&gt; - Создание итератора ( &lt;strong&gt;@$obj&lt;/strong&gt; ? (@$*) )&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@break $label&lt;/em&gt; - Operator to break out of a named named block of code&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;next(obj, &amp;hellip; )&lt;/strong&gt; - Следующий элемент итератора ( &lt;strong&gt;@$obj&lt;/strong&gt; ! ($*) )&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@continue $label&lt;/em&gt; - Jump operator to the beginning of a named block of code&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;curr(obj, &amp;hellip; )&lt;/strong&gt; - Текущий элемент итератора ( &lt;strong&gt;@$obj&lt;/strong&gt; !? ($*) )&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@return( result )&lt;/em&gt; - Operator for returning a value and exiting a function&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;first(obj)&lt;/strong&gt; - Перейти на первый элемент итератора ( &lt;strong&gt;@$obj&lt;/strong&gt; !! )&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@throw( error )&lt;/em&gt; - Operator for creating an exception and returning an error&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;all(obj)&lt;/strong&gt; - Получить сразу все элементы итератора ( &lt;strong&gt;@$obj&lt;/strong&gt; ??)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@match( &amp;hellip; )&lt;/em&gt; - Expression evaluation operator&lt;/p&gt; &lt;/li&gt; -&lt;/ul&gt; -&lt;h3 id=&#34;прерывания&#34;&gt;Прерывания&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b5%d1%80%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;ul&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;return&lt;/strong&gt; - Положительное прерывание (&lt;strong&gt;++&lt;/strong&gt;)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@case( &amp;hellip; )&lt;/em&gt; - Pattern comparison operator&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;return(&amp;hellip;)&lt;/strong&gt;- Положительное прерывание с возвратом значения (&lt;strong&gt;++&lt;/strong&gt; @$value &lt;strong&gt;++&lt;/strong&gt;)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@default&lt;/em&gt; - Selection operator&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;error&lt;/strong&gt; - Отрицательное прерывание (&lt;strong&gt;--&lt;/strong&gt;)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@iter(obj, &amp;hellip; )&lt;/em&gt; - Creating an iterator&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;error(&amp;hellip;)&lt;/strong&gt; - Отрицательное прерывание с возвратом значения (&lt;strong&gt;--&lt;/strong&gt; @$value &lt;strong&gt;--&lt;/strong&gt;)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@next(obj, &amp;hellip; )&lt;/em&gt; - Get the next element of the iterator&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;break+&lt;/strong&gt; и &lt;strong&gt;break-&lt;/strong&gt; - Выход из цикла:&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@curr(obj, &amp;hellip; )&lt;/em&gt; - Get the current iterator element&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@first(obj)&lt;/em&gt; - Go to the first element of the iterator&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@all(obj)&lt;/em&gt; - Get all elements of the iterator at once&lt;/p&gt; &lt;/li&gt; &lt;/ul&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; while(...) {+ - ++ :Break ++ - +} - while(...) {- - -- :Break -- - -} -&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt; -&lt;li&gt;&lt;strong&gt;continue+&lt;/strong&gt; и &lt;strong&gt;continue-&lt;/strong&gt; - В начало цикла:&lt;/li&gt; -&lt;/ul&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; while(...) {+ - ++ :Continue ++ - +} - while(...) {- - -- :Continue -- - -} -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;obj { -.field = 1; -.prop(); -};&lt;/p&gt; -&lt;p&gt;#Python&lt;/p&gt; -&lt;h1 id=&#34;1-without-using-with-statement&#34;&gt;1) without using with statement&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#1-without-using-with-statement&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;file = open(&amp;lsquo;file_path&amp;rsquo;, &amp;lsquo;w&amp;rsquo;) -file.write(&amp;lsquo;hello world !&amp;rsquo;) -file.close()&lt;/p&gt; -&lt;h1 id=&#34;2-without-using-with-statement&#34;&gt;2) without using with statement&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#2-without-using-with-statement&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;file = open(&amp;lsquo;file_path&amp;rsquo;, &amp;lsquo;w&amp;rsquo;) -try: -file.write(&amp;lsquo;hello world&amp;rsquo;) -finally: -file.close()&lt;/p&gt; -&lt;p&gt;open(&amp;lsquo;file_path&amp;rsquo;, &amp;lsquo;w&amp;rsquo;) { -.write(&amp;lsquo;hello world !&amp;rsquo;); -.close(); -}&lt;/p&gt; -&lt;p&gt;Python3&lt;/p&gt; -&lt;h1 id=&#34;using-with-statement&#34;&gt;using with statement&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#using-with-statement&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;with open(&amp;lsquo;file_path&amp;rsquo;, &amp;lsquo;w&amp;rsquo;) as file: -file.write(&amp;lsquo;hello world !&amp;rsquo;)&lt;/p&gt; -&lt;h1 id=&#34;a-simple-file-writer-object&#34;&gt;a simple file writer object&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#a-simple-file-writer-object&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;class MessageWriter(object): -def &lt;strong&gt;init&lt;/strong&gt;(self, file_name): -self.file_name = file_name&lt;/p&gt; -&lt;pre&gt;&lt;code&gt;def __enter__(self): - self.file = open(self.file_name, &#39;w&#39;) - return self.file - -def __exit__(self, *args): - self.file.close() -&lt;/code&gt;&lt;/pre&gt; -&lt;h1 id=&#34;using-with-statement-with-messagewriter&#34;&gt;using with statement with MessageWriter&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#using-with-statement-with-messagewriter&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;with MessageWriter(&amp;lsquo;my_file.txt&amp;rsquo;) as xfile: -xfile.write(&amp;lsquo;hello world&amp;rsquo;)&lt;/p&gt; -&lt;h1 id=&#34;a-simple-file-writer-object-1&#34;&gt;a simple file writer object&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#a-simple-file-writer-object-1&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;:MessageWriter { -def &lt;strong&gt;init&lt;/strong&gt;(self, file_name): -self.file_name = file_name&lt;/p&gt; -&lt;pre&gt;&lt;code&gt;def __enter__(self): - self.file = open(self.file_name, &#39;w&#39;) - return self.file - -def __exit__(self, *args): - self.file.close() -&lt;/code&gt;&lt;/pre&gt; -&lt;p&gt;}&lt;/p&gt; -&lt;h1 id=&#34;using-with-statement-with-messagewriter-1&#34;&gt;using with statement with MessageWriter&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#using-with-statement-with-messagewriter-1&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;MessageWriter(&amp;lsquo;my_file.txt&amp;rsquo;) { -.write(&amp;lsquo;hello world&amp;rsquo;); -};&lt;/p&gt; -&lt;p&gt;from contextlib import contextmanager&lt;/p&gt; -&lt;p&gt;class MessageWriter(object): -def &lt;strong&gt;init&lt;/strong&gt;(self, filename): -self.file_name = filename&lt;/p&gt; -&lt;pre&gt;&lt;code&gt;@contextmanager -def open_file(self): - try: - file = open(self.file_name, &#39;w&#39;) - yield file - finally: - file.close() -&lt;/code&gt;&lt;/pre&gt; -&lt;h1 id=&#34;usage&#34;&gt;usage&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#usage&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;message_writer = MessageWriter(&amp;lsquo;hello.txt&amp;rsquo;) -with message_writer.open_file() as my_file: -my_file.write(&amp;lsquo;hello world&amp;rsquo;)&lt;/p&gt; -&lt;p&gt;:MessageWriter(object) { -def &lt;strong&gt;init&lt;/strong&gt;(self, filename): -self.file_name = filename&lt;/p&gt; -&lt;pre&gt;&lt;code&gt;@contextmanager -def open_file(self): - try: - file = open(self.file_name, &#39;w&#39;) - yield file - finally: - file.close() -&lt;/code&gt;&lt;/pre&gt; -&lt;p&gt;}&lt;/p&gt; -&lt;h1 id=&#34;usage-1&#34;&gt;usage&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#usage-1&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;message_writer = MessageWriter(&amp;lsquo;hello.txt&amp;rsquo;) -with message_writer.open_file() as my_file: -my_file.write(&amp;lsquo;hello world&amp;rsquo;)&lt;/p&gt; -&lt;h1 id=&#34;приложения&#34;&gt;Приложения&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b8%d0%bb%d0%be%d0%b6%d0%b5%d0%bd%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;h2 id=&#34;предопределенные-макросы&#34;&gt;Предопределенные макросы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b5%d0%b4%d0%be%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%bd%d1%8b%d0%b5-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;При работе парсера &lt;em&gt;NewLang&lt;/em&gt; автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. -Данные предопределенные макросы можно использовать как обычные константы.&lt;/p&gt; +&lt;h2 id=&#34;predefined-macros&#34;&gt;Predefined macros&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#predefined-macros&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; +&lt;p&gt;When the &lt;em&gt;NewLang&lt;/em&gt; parser is running, several reserved macros are automatically generated, +some of which correspond to preprocessor macros in C/C++. +These predefined macros can be used as regular constants.&lt;/p&gt; &lt;ul&gt; &lt;li&gt; -&lt;p&gt;__FILE__ или __FILE_NAME__ - имя и полный путь текущего файла&lt;/p&gt; +&lt;p&gt;__FILE__ or __FILE_NAME__ - name and full path of the current file&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__LINE__ или __FILE_LINE__ - содержит номер текущей строки в файле&lt;/p&gt; +&lt;p&gt;__LINE__ or __FILE_LINE__ - contains the number of the current line in the file&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__FILE_TIMESTAMP__ - дату и время последней модификации текущего файла в строковом представлении&lt;/p&gt; +&lt;p&gt;__FILE_TIMESTAMP__ - date and time of the last modification of the current file in string representation&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__FILE_MD5__ - md5 хеш текущего файла в строковом виде&lt;/p&gt; +&lt;p&gt;__FILE_MD5__ - md5 hash of the current file in string form&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__COUNTER__ - целочисленный счетчик, который увеличивает свое значение при каждом обращении&lt;/p&gt; +&lt;p&gt;__COUNTER__ - an integer counter that increases its value with each access&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__DATE__ - дата начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)&lt;/p&gt; +&lt;p&gt;__DATE__ - start date of the compiler launch (has the same value for all processed files)&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__TIME__ - время начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)&lt;/p&gt; +&lt;p&gt;__TIME__ - start time of the compiler launch (has the same value for all processed files)&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__TIMESTAMP__ - дату и время начала запуска компилятора (например: &amp;ldquo;Fri 19 Aug 13:32:58 2016&amp;rdquo;)&lt;/p&gt; +&lt;p&gt;__TIMESTAMP__ - date and time when the compiler started running (for example: &amp;ldquo;Fri 19 Aug 13:32:58 2016&amp;rdquo;)&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__TIMESTAMP_ISO__ - дату и время начала запуска компилятора в формате ISO (например: &amp;ldquo;2013-07-06T00:50:06Z&amp;rdquo;)&lt;/p&gt; +&lt;p&gt;__TIMESTAMP_ISO__ - date and time when the compiler started running in ISO format (for example: &amp;ldquo;2013-07-06T00:50:06Z&amp;rdquo;)&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__NLC_VER__ - Страшая и младшая версия компилятора NewLang (8 битное число, по 4 бита на цифру)&lt;/p&gt; +&lt;p&gt;__NLC_VER__ - Older and younger version of the NewLang compiler (8-bit number, 4 bits per digit)&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__NLC_DATE_BUILD__ - текстовая строка с датой сборки компилятора NewLang (например, &amp;ldquo;23.06.04 20:51:39&amp;rdquo;)&lt;/p&gt; +&lt;p&gt;__NLC_DATE_BUILD__ - text string with the build date of the NewLang compiler (for example, &amp;ldquo;06/23/04 20:51:39&amp;rdquo;)&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__NLC_SOURCE_GIT__ - текстовая строка с идентификатором исходных файлов NewLang git репозитория, использованных при сборке компилятора (например, &amp;ldquo;v0.3.0-fef8c371&amp;rdquo;)&lt;/p&gt; +&lt;p&gt;__NLC_SOURCE_GIT__ - text string with the identifier of the NewLang git repository source files used to build the compiler (for example, &amp;ldquo;v0.3.0-fef8c371&amp;rdquo;)&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;__NLC_SOURCE_BUILD__ - дата сборки и git идентификатор исходных файлов NewLang одной текстовой строкой (например, &amp;ldquo;v0.3.0-fef8c371 23.06.04 20:51:39&amp;rdquo;)&lt;/p&gt; +&lt;p&gt;__NLC_SOURCE_BUILD__ - build date and git identifier of NewLang source files in one text line (for example, &amp;ldquo;v0.3.0-fef8c371 06/23/04 20:51:39&amp;rdquo;)&lt;/p&gt; &lt;/li&gt; &lt;/ul&gt; diff --git a/docs/docs/syntax/macros/index.html b/docs/docs/syntax/macros/index.html index 1b9dbd69..f60807c8 100644 --- a/docs/docs/syntax/macros/index.html +++ b/docs/docs/syntax/macros/index.html @@ -17,28 +17,28 @@ <link rel="icon" type="image/png" href="/favicons/android-144x144.png" sizes="144x144"> <link rel="icon" type="image/png" href="/favicons/android-192x192.png" sizes="192x192"> -<title>Макросы | NewLang</title> -<meta name="description" content="Макросы в NewLang, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем). -Макросы обработываются во время работы лексера, т.е. перед передачей последовательности лексем в парсер, что позволяет с их помощью изменять даже сам синтаксис языка, например, при реализации собственных диалектов DSL. -Определение макросов Определение макросов аналогично определению других объектов и состоит из трех частей &amp;lt;имя макроса&amp;gt; &amp;lt;оператор создания/присвоения&amp;gt; &amp;lt;тело макроса&amp;gt; и завершающая точка с запятой &amp;ldquo;;&amp;rdquo;, т."> -<meta property="og:title" content="Макросы" /> -<meta property="og:description" content="Макросы в NewLang, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем). -Макросы обработываются во время работы лексера, т.е. перед передачей последовательности лексем в парсер, что позволяет с их помощью изменять даже сам синтаксис языка, например, при реализации собственных диалектов DSL. -Определение макросов Определение макросов аналогично определению других объектов и состоит из трех частей &lt;имя макроса&gt; &lt;оператор создания/присвоения&gt; &lt;тело макроса&gt; и завершающая точка с запятой &ldquo;;&rdquo;, т." /> +<title>Macros | NewLang</title> +<meta name="description" content="Macros are also used to transform the original code of NewLang into a more familiar syntax based on keywords, as such text is much easier to understand when reading the original code later. +In NewLang, macros are one or more consecutive terms that are replaced with another term or a whole syntactic construction (a sequence of lexemes). +Macros are processed during the operation of the lexer, i.e., before passing the sequence of lexemes to the parser, allowing fragments of the language syntax to be modified using macros, for example, when implementing custom DSL dialects."> +<meta property="og:title" content="Macros" /> +<meta property="og:description" content="Macros are also used to transform the original code of NewLang into a more familiar syntax based on keywords, as such text is much easier to understand when reading the original code later. +In NewLang, macros are one or more consecutive terms that are replaced with another term or a whole syntactic construction (a sequence of lexemes). +Macros are processed during the operation of the lexer, i.e., before passing the sequence of lexemes to the parser, allowing fragments of the language syntax to be modified using macros, for example, when implementing custom DSL dialects." /> <meta property="og:type" content="article" /> <meta property="og:url" content="http://localhost:1313/docs/syntax/macros/" /><meta property="article:section" content="docs" /> -<meta property="article:modified_time" content="2024-03-22T23:57:08+03:00" /><meta property="og:site_name" content="NewLang" /> -<meta itemprop="name" content="Макросы"> -<meta itemprop="description" content="Макросы в NewLang, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем). -Макросы обработываются во время работы лексера, т.е. перед передачей последовательности лексем в парсер, что позволяет с их помощью изменять даже сам синтаксис языка, например, при реализации собственных диалектов DSL. -Определение макросов Определение макросов аналогично определению других объектов и состоит из трех частей &lt;имя макроса&gt; &lt;оператор создания/присвоения&gt; &lt;тело макроса&gt; и завершающая точка с запятой &ldquo;;&rdquo;, т."> -<meta itemprop="dateModified" content="2024-03-22T23:57:08+03:00" /> -<meta itemprop="wordCount" content="3011"> -<meta itemprop="keywords" content="" /><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Макросы"/> -<meta name="twitter:description" content="Макросы в NewLang, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем). -Макросы обработываются во время работы лексера, т.е. перед передачей последовательности лексем в парсер, что позволяет с их помощью изменять даже сам синтаксис языка, например, при реализации собственных диалектов DSL. -Определение макросов Определение макросов аналогично определению других объектов и состоит из трех частей &lt;имя макроса&gt; &lt;оператор создания/присвоения&gt; &lt;тело макроса&gt; и завершающая точка с запятой &ldquo;;&rdquo;, т."/> +<meta property="article:modified_time" content="2024-03-23T22:03:23+03:00" /><meta property="og:site_name" content="NewLang" /> +<meta itemprop="name" content="Macros"> +<meta itemprop="description" content="Macros are also used to transform the original code of NewLang into a more familiar syntax based on keywords, as such text is much easier to understand when reading the original code later. +In NewLang, macros are one or more consecutive terms that are replaced with another term or a whole syntactic construction (a sequence of lexemes). +Macros are processed during the operation of the lexer, i.e., before passing the sequence of lexemes to the parser, allowing fragments of the language syntax to be modified using macros, for example, when implementing custom DSL dialects."> +<meta itemprop="dateModified" content="2024-03-23T22:03:23+03:00" /> +<meta itemprop="wordCount" content="902"> +<meta itemprop="keywords" content="" /><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Macros"/> +<meta name="twitter:description" content="Macros are also used to transform the original code of NewLang into a more familiar syntax based on keywords, as such text is much easier to understand when reading the original code later. +In NewLang, macros are one or more consecutive terms that are replaced with another term or a whole syntactic construction (a sequence of lexemes). +Macros are processed during the operation of the lexer, i.e., before passing the sequence of lexemes to the parser, allowing fragments of the language syntax to be modified using macros, for example, when implementing custom DSL dialects."/> @@ -148,7 +148,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child active-path" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="td-sidebar-nav-active-item">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="td-sidebar-nav-active-item">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -179,7 +179,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> @@ -235,24 +235,8 @@ <ul> <li> <ul> - <li><a href="#определение-макросов">Определение макросов</a></li> - <li><a href="#аргументы-макросов-и-их-раскрытие">Аргументы макросов и их раскрытие</a></li> - </ul> - </li> - </ul> - - <ul> - <li> - <ul> - <li><a href="#примеры-использования-макросов">Примеры использования макросов</a></li> - </ul> - </li> - </ul> - - <ul> - <li><a href="#идеи-на-будущее">Идеи на будущее</a> - <ul> - <li><a href="#символьное-программирование">Символьное программирование</a></li> + <li><a href="#defining-macros">Defining Macros</a></li> + <li><a href="#args">Macro Arguments and Expansion</a></li> </ul> </li> </ul> @@ -284,433 +268,108 @@ <h5 class="taxonomy-title">Tag Cloud</h5> <li class="breadcrumb-item"> <a href="/docs/syntax/">Синтаксис</a></li> <li class="breadcrumb-item active" aria-current="page"> - Макросы</li> + Macros</li> </ol> </nav> <div class="td-content"> - <h1>Макросы</h1> + <h1>Macros</h1> <header class="article-meta"> </header> - <p>Макросы в <strong>NewLang</strong>, это один или несколько последовательных терминов, которые заменяются на другой термин -или на целую синтаксическую конструкцию (последовательность лексем).</p> -<p>Макросы обработываются во время работы <strong>лексера</strong>, т.е. перед передачей последовательности лексем в парсер, -что позволяет с их помощью изменять даже сам синтаксис языка, например, при реализации собственных диалектов DSL.</p> -<h3 id="определение-макросов">Определение макросов<a class="td-heading-self-link" href="#%d0%be%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2" aria-label="Heading self-link"></a></h3> -<p>Определение макросов аналогично <a href="/docs/ops/create/">определению</a> других объектов и состоит из трех частей -<strong>&lt;имя макроса&gt; &lt;оператор создания/присвоения&gt; &lt;тело макроса&gt;</strong> и завершающая точка с запятой &ldquo;<strong>;</strong>&rdquo;, -т.е. применяются обычные операторы <strong>::=</strong>, <strong>=</strong> или <strong>:=</strong> для создания нового или переопределения уже существующего объекта, -а имя макроса указывается между двумя символами <strong>&quot;@@&quot;</strong> и может содержать одну или нескольких лексем (терминов).</p> -<p>Все макросы относятся к глобальному пространству имен, поэтому первый термин в имени макроса должен быть уникальным, -иначе он будет прекрывать имена локальных и глобальных переменных при <a href="/docs/syntax/naming/">разрешении имен</a>, -если они указаны в коде без квалификаторов.</p> -<p>??????????????????????? -Чистые (гигиеничные) макросы, <strong>::-</strong> <strong>:-</strong>, аргумента и переммые в которых гарантиованно не пересекаются с пространством имен программы?????????????????</p> -<p>Телом макроса могут быть корректное выражение языка, последовательность лексем (которые заключается в двойные собачки <strong>&quot;@@&quot;</strong>, -т.е. <strong><code>@@ лексема1 лексема1 @@</code></strong>) или обычная текстовая строка (которую нужно указать между тройными собачками <strong>&quot;@@@&quot;</strong>, т.е. <strong><code>@@@ текстовая строка @@@</code></strong>).</p> -<p>В имени макроса, кроме первого термина, могут присутствовать один или несколько шаблонов. -<em>Шаблон</em> — это термин, который при сопоставлении последовательности лексем с идентификатором макроса -может заменяться любым другим одиночным термином (т.е. фактически это сопоставление по образцу/шаблону).</p> -<p>Для создания термина-шаблона в начале его идентификатора нужно поставить знак доллара (что соответствует квалификатору локальной переменой), -т.е. имя макроса <code>@@ FUNC $name @@</code> будет соответствовать последовательности лексем как <code>FUNC my_func_name</code>, так и <code>FUNC other_name_func</code>.</p> -<p>Для удаления макроса используется специальный синтаксис: <code>@@@@ name @@@@;</code> или <code>@@@@ два термина @@@@;</code>, -т.е. необходимо указать идентификатор макроса между четырмя символами <strong>&quot;@@@@&quot;</strong>.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Тело макроса из текстовой строки (как в препроцессоре С/С++)</span> -</span></span><span style="display:flex;"><span> @@macro_str@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@@ строка - тело макроса @@@<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Строка для лексера</span> + <p>Macros are also used to transform the original code of <em>NewLang</em> into a more familiar syntax based on <a href="/docs/syntax/dsl/">keywords</a>, +as such text is much easier to understand when reading the original code later.</p> +<p>In <strong>NewLang</strong>, macros are one or more consecutive terms that are replaced with another term or a whole syntactic construction (a sequence of lexemes).</p> +<p>Macros are processed during the operation of the <strong>lexer</strong>, i.e., before passing the sequence of lexemes to the parser, +allowing fragments of the language syntax to be modified using macros, for example, when implementing custom DSL dialects.</p> +<h3 id="defining-macros">Defining Macros<a class="td-heading-self-link" href="#defining-macros" aria-label="Heading self-link"></a></h3> +<p>The definition of macros is similar to the <a href="/docs/ops/create/">definition</a> of other objects and consists of three parts +<strong><macro name> &lt;creation/assignment operator&gt; <macro body></strong> and ends with a semicolon &ldquo;<strong>;</strong>&rdquo;, i.e., +normal operators <strong>::=</strong>(<strong>::-</strong>), <strong>=</strong>, or <strong>:=</strong>(<strong>:-</strong>) are used to create a new or redefine an existing object, +and the macro name is indicated between two symbols <strong>&quot;@@&quot;</strong> and can contain one or more lexemes (terms).</p> +<p>All macros belong to the global namespace, so the first term in the macro name must be unique, +otherwise it will override local and global variables during <a href="/docs/syntax/naming/#name-lookup">name lookup</a> +if they are written in the program text without <a href="/docs/syntax/naming/#sigil">qualifiers (sigils)</a>.</p> +<p>Using the operators <strong>::-</strong> and <strong>:-</strong> creates pure (hygienic) macros, arguments and variables in which are guaranteed not to intersect with the program&rsquo;s namespace.</p> +<p>The body of a macro can be a valid language expression, a sequence of lexemes (enclosed in double at symbols <strong>&quot;@@&quot;</strong>, +i.e. <strong><code>@@ lexeme1 lexeme2 @@</code></strong>), or a regular text string (which should be specified between triple at symbols <strong>&quot;@@@&quot;</strong>, +i.e. <strong><code>@@@ text string @@@</code></strong>).</p> +<p>In the macro name after the first term, one or more templates may be present. +A <em>template</em> is a term that, when matching a sequence of lexemes with the macro identifier, +can be replaced by any other single term (effectively, this is pattern/template matching).</p> +<p>To create a template term, a dollar sign should be placed at the beginning of its identifier (which corresponds to a qualifier of a local variable), +i.e. the macro name <code>@@ FUNC $name @@</code> will correspond to the sequence of lexemes as <code>FUNC my_func_name</code> as well as <code>FUNC other_name_func</code>.</p> +<p>To remove a macro, a special syntax is used: <code>@@@@ name @@@@;</code> or <code>@@@@ two terms @@@@;</code>, +i.e. you need to specify the macro identifier between four characters <strong>&quot;@@@@&quot;</strong>.</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Macro body from a text string (as in C/C++ preprocessor)</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#5c35cc;font-weight:bold">@macro_str</span><span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@@</span> <span style="color:#000">string</span> <span style="color:#ce5c00;font-weight:bold">-</span> <span style="color:#000">macro</span> <span style="color:#000">body</span> <span style="color:#ce5c00;font-weight:bold">@@@</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># String for the lexer</span> </span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Удаления макроса @macro_str</span> -</span></span><span style="display:flex;"><span> @@@@ macro_str @@@@<span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><h3 id="аргументы-макросов-и-их-раскрытие">Аргументы макросов и их раскрытие<a class="td-heading-self-link" href="#%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d1%8b-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2-%d0%b8-%d0%b8%d1%85-%d1%80%d0%b0%d1%81%d0%ba%d1%80%d1%8b%d1%82%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> -<p>Макросы можно определять как с аргументами (параметрами в скобках), так и без них. -Если макрос был определен с аргументами, то их проверка будет выполнятся макропроцессором при определении и раскрытии макроса. -Если макрос был определен без аргументов, то их наличие макропроцессором игнорируется.</p> -<p>Так как макропроцессор считает макросы с аргументами и без оных идентичными, то нельзя создать два макроса -с одинаковыми именами, один из которых будет с аргументами (скобками), а другой без них.</p> -<p>Поэтому, если требуется использовать макрос в двух разных вариантах (с аргументами и без них), -тогда следует определять макрос без аргументов и в этом случае контроль параметров будет производить компилятор.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> @@macro@@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Макрос без аргументов</span> +</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Removing macro @macro_str</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@@@</span> <span style="color:#000">macro_str</span> <span style="color:#ce5c00;font-weight:bold">@@@@</span><span style="color:#000;font-weight:bold">;</span> +</span></span></code></pre></div><h3 id="args">Macro Arguments and Expansion<a class="td-heading-self-link" href="#args" aria-label="Heading self-link"></a></h3> +<p>Macros can be defined with arguments (parameters in parentheses) or without them. +If a macro was defined with arguments, their validation will be performed by the macro processor during definition and expansion of the macro. +If a macro was defined without arguments, the presence of arguments will be ignored by the macro processor.</p> +<p>The macroprocessor considers macros with and without arguments identical, +so it is not possible to create two macros with the same name, one with arguments (in parentheses) and the other without.</p> +<p>Therefore, if you need to use a macro in two different ways (with arguments and without), +you should define the macro without arguments, and in this case, the parameter control will be done by the compiler.</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> @@ macro @@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Macro without arguments</span> </span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> macro<span style="color:#ce5c00;font-weight:bold">(</span>args<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># ОК -&gt; term(args);</span> -</span></span><span style="display:flex;"><span> macro<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># ОК -&gt; term;</span> +</span></span><span style="display:flex;"><span> macro<span style="color:#ce5c00;font-weight:bold">(</span>args<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># OK -&gt; term(args);</span> +</span></span><span style="display:flex;"><span> macro<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># OK -&gt; term;</span> </span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Но </span> -</span></span><span style="display:flex;"><span> @@call<span style="color:#ce5c00;font-weight:bold">()</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># But</span> +</span></span><span style="display:flex;"><span> @@ call<span style="color:#ce5c00;font-weight:bold">()</span> @@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> </span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> call<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># ОК -&gt; term();</span> -</span></span><span style="display:flex;"><span> call<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Ошибка (@call определен с аргументами) </span> -</span></span></code></pre></div><p>Если при определении макроса указаны аргументы, то место для их вставки в теле макроса -записывается как имя локальной переменой, перед которой добавлен символ <strong>&quot;@&quot;</strong>, т.е. <strong>@$arg</strong>.</p> -<p>Произвольное количество аргументов у макроса отмечается троеточием <strong>&quot;&hellip;&quot;</strong>, а место для их вставки отмечается в теле макроса лексемой <strong>&quot;@$&hellip;&quot;</strong>.</p> -<p>Место для вставки числа реально переданных аргументов отмечается лексемой <strong>&quot;@$#&quot;</strong>. -Если требуется вставить переданные аргументы в виде элементов словаря, -то место для вставки отмечается лексемой <strong>&quot;@$*&quot;</strong>.</p> -<p>По аналогии с препроцессором С/С++, для соединения двух лексем в одну, в теле макроса используется оператор <strong>&quot;@##&quot;</strong>, -а для преобразование лексемы в текстову строку применяется операторы <strong>@#</strong>, <strong>@#&quot;</strong> или <strong>@#&rsquo;</strong>, например, -<code>@@macro($arg)@@ := @@ func_ @## @$arg( @#&quot; arg ) @;</code>, тогда вызов <code>macro(name);</code> будет преобразован в <code>func_name (&quot;name&quot;);</code></p> - - -<div class="pageinfo pageinfo-primary"> -<h4 id="ограничения-макропроцессора-в-текущей-версии">Ограничения макропроцессора в текущей версии<a class="td-heading-self-link" href="#%d0%be%d0%b3%d1%80%d0%b0%d0%bd%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d0%bf%d1%80%d0%be%d1%86%d0%b5%d1%81%d1%81%d0%be%d1%80%d0%b0-%d0%b2-%d1%82%d0%b5%d0%ba%d1%83%d1%89%d0%b5%d0%b9-%d0%b2%d0%b5%d1%80%d1%81%d0%b8%d0%b8" aria-label="Heading self-link"></a></h4> -<p>На текущий момент макросы реализованы в минимальном объеме для самых простых сценариев использования:</p> -<ul> -<li>DSL для keyword based syntax (if, else, return, match, while и т.д.) - (1 термин с произвольными аргументами и без) - требуется сейчас !!!</li> -</ul> -<p><em>Парсер при обработке макросов может анализировать информацию о типах данных, если она указана.</em> -<em>Но на текущий момент типы данных в макросах никак не обрабатываются и это одна из обязательных фич, которая будет реализована в будущем.</em></p> -<ul> -<li>Определения (func, class) - (несколько терминов с аргументами и без аргументов) - Реализация ООП и импорт С++ классов</li> -<li>Модификации при определениях (override) - (несколько терминов и шаблоны с аргументами и без аргументов) - Реализация ООП и импорт С++ классов</li> -</ul> - -</div> - -<h1 id="макросы-без-аргументов-или-все-аргументы-сразу-">МАКРОСЫ БЕЗ АРГУМЕНТОВ ИЛИ ВСЕ АРГУМЕНТЫ СРАЗУ !!!!!<a class="td-heading-self-link" href="#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b1%d0%b5%d0%b7-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d0%b8%d0%bb%d0%b8-%d0%b2%d1%81%d0%b5-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d1%8b-%d1%81%d1%80%d0%b0%d0%b7%d1%83-" aria-label="Heading self-link"></a></h1> -<h1 id="анализа-аргументов-или-их-типов-не-производится-">анализа аргументов или их типов не производится !!!<a class="td-heading-self-link" href="#%d0%b0%d0%bd%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d0%b8%d0%bb%d0%b8-%d0%b8%d1%85-%d1%82%d0%b8%d0%bf%d0%be%d0%b2-%d0%bd%d0%b5-%d0%bf%d1%80%d0%be%d0%b8%d0%b7%d0%b2%d0%be%d0%b4%d0%b8%d1%82%d1%81%d1%8f-" aria-label="Heading self-link"></a></h1> -<p>Lambda -@@ lambda $name(&hellip;) @@ ::= @@ @$name( @$&hellip; ) ::= ( _( @$&hellip; ) ::= @<strong>PRAGMA_FINALIZE</strong>( @), {, {+, {-, {* ) @@</p> -<h3 id="примеры-использования-макросов">Примеры использования макросов<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80%d1%8b-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2" aria-label="Heading self-link"></a></h3> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Обычные макросы (тело макроса корректное выражение)</span> -</span></span><span style="display:flex;"><span> @@macro@@ :<span style="color:#ce5c00;font-weight:bold">=</span> replace<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@macro2<span style="color:#ce5c00;font-weight:bold">(</span>arg<span style="color:#ce5c00;font-weight:bold">)</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">{</span> call<span style="color:#ce5c00;font-weight:bold">(</span>@<span style="color:#000">$arg</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> call<span style="color:#ce5c00;font-weight:bold">()}</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> call<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># OK -&gt; term();</span> +</span></span><span style="display:flex;"><span> call<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Error (@call is defined with arguments) </span> +</span></span></code></pre></div><p>If arguments are specified when defining a macro, the place for their insertion in the body of the macro is written +as the name of a local variable with the symbol <strong>&quot;@&quot;</strong> added before it, i.e. <strong>@$arg</strong>.</p> +<p>The place for inserting the number of actual arguments passed is marked by the lexeme <strong>&quot;@$#&quot;</strong>. +If it is necessary to insert the passed arguments as a dictionary, the place for insertion is marked by the lexeme <strong>&quot;@$*&quot;</strong>.</p> +<p>If the macro takes an arbitrary number of arguments (the macro arguments are terminated by an ellipsis), +the place for their insertion in the body of the macro is marked by the lexeme <strong>&quot;@$&hellip;&quot;</strong>.</p> +<p>Analogous to the C/C++ preprocessor, to concatenate two lexemes into one, the operator <strong>&quot;@##&quot;</strong> is used in the body of the macro, +and to convert a lexeme into a text string, the operators <strong>@#</strong>, <strong>@#&quot;</strong>, or <strong>@#&rsquo;</strong> are applied, for example, +<code>@@macro($arg)@@ := @@ func_ @## @$arg( @#&quot; arg ) @;</code>, then the call <code>macro(name);</code> will be transformed into <code>func_name (&quot;name&quot;);</code></p> +<p>Examples of using macros:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Ordinary macros (the body of the macro is a correct expression)</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000">macro</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000">replace</span><span style="color:#000;font-weight:bold">();</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000">macro2</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">arg</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000;font-weight:bold">{</span> <span style="color:#000">call</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#a40000">$</span><span style="color:#000">arg</span><span style="color:#000;font-weight:bold">);</span> <span style="color:#000">call</span><span style="color:#000;font-weight:bold">()};</span> </span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Тело макросов из последовательности лексем</span> -</span></span><span style="display:flex;"><span> @@if<span style="color:#ce5c00;font-weight:bold">(</span>...<span style="color:#ce5c00;font-weight:bold">)</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ <span style="color:#ce5c00;font-weight:bold">[</span> <span style="color:#4e9a06">\$</span><span style="color:#204a87;font-weight:bold">if</span><span style="color:#ce5c00;font-weight:bold">(</span>*<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">]</span>--&gt; @@<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Выражение может быть не полным</span> -</span></span><span style="display:flex;"><span> @@elif<span style="color:#ce5c00;font-weight:bold">(</span>...<span style="color:#ce5c00;font-weight:bold">)</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ ,<span style="color:#ce5c00;font-weight:bold">[</span> <span style="color:#4e9a06">\$</span><span style="color:#204a87;font-weight:bold">elif</span><span style="color:#ce5c00;font-weight:bold">(</span>*<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">]</span>--&gt; @@<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@else@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ ,<span style="color:#ce5c00;font-weight:bold">[</span>_<span style="color:#ce5c00;font-weight:bold">]</span>--&gt; @@<span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># The body of the macros from a sequence of tokens</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#204a87;font-weight:bold">if</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000;font-weight:bold">[</span> <span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#a40000">$</span><span style="color:#ce5c00;font-weight:bold">...</span> <span style="color:#000;font-weight:bold">]</span><span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#ce5c00;font-weight:bold">@@</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># The expression may not be complete</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#204a87;font-weight:bold">elif</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000;font-weight:bold">,[</span> <span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#a40000">$</span><span style="color:#ce5c00;font-weight:bold">...</span> <span style="color:#000;font-weight:bold">]</span><span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#ce5c00;font-weight:bold">@@</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000;font-weight:bold">,[</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">]</span><span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#ce5c00;font-weight:bold">@@</span><span style="color:#000;font-weight:bold">;</span> </span></span><span style="display:flex;"><span> -</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Запись условного оператора с использованием </span> -</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># определенных выше макросов</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">if</span><span style="color:#ce5c00;font-weight:bold">(</span> condition <span style="color:#ce5c00;font-weight:bold">){</span> -</span></span><span style="display:flex;"><span> ... -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">elif</span><span style="color:#ce5c00;font-weight:bold">(</span> condition2 <span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> ... -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#ce5c00;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> ... -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>Зачем нужна трансформация синтаксиса? -Нативная поддержка других языков нужна чтобы не переписывать легаси код на этих языках.</p> -<p>Чтобы можно было использовать существующие исходники как собственные требуется настройка работы -препроцессора и лексера под конкретный язык программирования (описание DSL). -Для <strong>С/С++</strong> потребуется выделять лексером комментарии из-за пересечения синтаксиса (которые сейчас игнорируются). -Для <strong>Python</strong> требуется выделять лексером отступы (которые сейчас тоже игнорируются), причем потребуется реализация не только синтаксиса, -но и зависимых пакетов с последующая трансляцией этого кода в С++, что в настоящий момент делать не целесообразно (cython ???).</p> -<p>Но так как возможность трансформации кода с других языков программирования принципиальная возможна, -стоит над этим думать только после полноценного релиза NewLang и его перехода в прод.</p> -<p>Для реализации DSL требуется передача команд в парсер для управления его работой (по аналогии с командой #pragma) -Но так как обработка таких команд должна происходить в лексере до передачи данных в парсер (анализатор), -то команды для макропроцессора должны быть в максимально простом виде и состоять из элементов, -которые лексер может самостоятельно идентифицировать, т.е. термины, строки и цифры (без выражений и именованных аргументов).</p> -<p>После обработки такой команды она анализируется макропроцессором и удаляется из потока лексем, т.е. в парсер (анализатор) не передается. -Но в случае ошибки с синтаксисе, данные команды нужно уметь однозначно идентифировать и самый простой способ, -комбинация признака макроса и системного имени, т.е. что-то вроде</p> -<pre tabindex="0"><code> @__PRAGMA_DIAG__(push) - @__PRAGMA_DIAG__(ignored, &#34;-Wundef&#34;) - @__PRAGMA_DIAG__(warning, &#34;-Wformat&#34;) - @__PRAGMA_DIAG__(error &#34;-Wuninitialized&#34;) - @__PRAGMA_DIAG__(pop) - - #pragma message &#34;Compiling &#34; __FILE__ &#34;...&#34; - @__PRAGMA_MESSAGE__(&#34;Compiling &#34;, __FILE__, &#34;...&#34;) - - #pragma error &#34;Error &#34; __FILE__ &#34;...&#34; - @__PRAGMA_ERROR__(&#34;Error &#34;, __FILE__, &#34;...&#34;) - - -#define DO_PRAGMA(x) _Pragma (#x) -#define TODO(x) DO_PRAGMA(message (&#34;TODO - &#34; #x)) - -@@TODO( ... )@@ := @__PRAGMA_MESSAGE__(&#34;TODO - &#34;, @*) - -@TODO(Remember to fix this) # note: TODO - Remember to fix this - -\\.__lexer__ignore_space__ = 1; -\\.__lexer__ignore_indent__ = 1; -\\.__lexer__ignore_comment__ = 1; -\\.__lexer__ignore_crlf__ = 1; -</code></pre><p>Таким образом можно трансформировать условный оператор на питоне в синтаксис NewLang следующим макросом:</p> -<pre tabindex="0"><code> -#pragma clang attribute push -#pragma clang diagnostic ignored &#34;-Wundef&#34; -#pragma clang diagnostic ignored &#34;-Wunused-variable&#34; - - -#elif __GNUC__ - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored &#34;-Wuninitialized&#34; - -#pragma GCC diagnostic ignored &#34;-Wall&#34; -#pragma GCC diagnostic ignored &#34;-Wextra&#34; - - @pragma warning(pop) - - @@ pragma warning(...) @@ := __PRAGMA_TERM_DIAG_WARNING__(); -@__PRAGMA_DIAG__(warning, pop); - -Обработка терминов в макропроцессоре в максимально простом виде. -Агрументы только термины, строки и цифры без вложенных выражений и именованных аргументов, -т.е. только элементы, которые может самостоятельно идентифицировать лексер. - -@warning(&#34;--&#34;) - @@ if ... : @@ := @@ [ @$* ]-&gt; __TERM_BLOCK_INDENT__(&#34;{&#34;, force_semicolon=1) @@ - - if __name__ == &#34;__main__&#34;: - run1() - run2() - - [ __name__ == &#34;__main__&#34; ]-&gt; { - run1(); - run2(); - }; - - -</code></pre><p>Ключ &ndash;parser-syntax-only только текстовый парсинг исходного кода без загрузки модулей, раскрытия макросов и проверки имен.</p> -<p>Ключ &ndash;parser-no-macros - без раскрытия макросов -Ключ &ndash;parser-no-module - без загрузки модулей (и мокросов, если они в них определяются) -Ключ &ndash;parser-no-check-prototype - без проверки имен при обращении</p> -<p>prototype -@<strong>PRAGMA_PROTOTYPE</strong>(define) -@<strong>PRAGMA_PROTOTYPE</strong>(implement)</p> -<p>$$</p> -<p>\$ - корень системы (система)</p> -<p>$ - текущий модуль</p> -<h1 id="макросы-для-конвертора-проверки-в-python">Макросы для конвертора проверки в Python<a class="td-heading-self-link" href="#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b4%d0%bb%d1%8f-%d0%ba%d0%be%d0%bd%d0%b2%d0%b5%d1%80%d1%82%d0%be%d1%80%d0%b0-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b8-%d0%b2-python" aria-label="Heading self-link"></a></h1> -<h1 id="if-__name__--__main__">if <strong>name</strong> == &ldquo;<strong>main</strong>&rdquo;:<a class="td-heading-self-link" href="#if-__name__--__main__" aria-label="Heading self-link"></a></h1> -<p>@@ <strong>name</strong> @@ ::= @@ $. @<strong>PRAGMA_NO_MACRO</strong>() <strong>name</strong> @@ -@@ if $&hellip; @: @@ ::= @@ [ @$&hellip; ] &ndash;&gt; @@</p> -<p>@if( $.<strong>name</strong> == &ldquo;<strong>main</strong>&rdquo; ) {</p> -<p>}</p> -<p>\каталог\модуль() - статический импорт модуля -\(&ldquo;каталог\модуль&rdquo;)() - динамический импорт модуля</p> -<p>printf := :Pointer(&lsquo;printf(format:FmtChar, &hellip;):Int32&rsquo;); -printf := %printf(format:FmtChar, &hellip;):Int32;</p> -<h1 id="регистрация-прототипа-нативной-функции">Регистрация прототипа нативной функции<a class="td-heading-self-link" href="#%d1%80%d0%b5%d0%b3%d0%b8%d1%81%d1%82%d1%80%d0%b0%d1%86%d0%b8%d1%8f-%d0%bf%d1%80%d0%be%d1%82%d0%be%d1%82%d0%b8%d0%bf%d0%b0-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h1> -<p>@prototype -%puts(format:StrChar):Int32;</p> -<h1 id="импорт-нативной-функции-с-предварительной-проверкой-её-наличия-во-время-компиляции-статическая-линковка">Импорт нативной функции с предварительной проверкой её наличия во время компиляции (статическая линковка)<a class="td-heading-self-link" href="#%d0%b8%d0%bc%d0%bf%d0%be%d1%80%d1%82-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d1%81-%d0%bf%d1%80%d0%b5%d0%b4%d0%b2%d0%b0%d1%80%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d0%be%d0%b9-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%be%d0%b9-%d0%b5%d1%91-%d0%bd%d0%b0%d0%bb%d0%b8%d1%87%d0%b8%d1%8f-%d0%b2%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d1%8f-%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%86%d0%b8%d0%b8-%d1%81%d1%82%d0%b0%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bb%d0%b8%d0%bd%d0%ba%d0%be%d0%b2%d0%ba%d0%b0" aria-label="Heading self-link"></a></h1> -<p>puts2(format:StrChar):Int32 := %puts(format:StrChar):Int32;</p> -<h1 id="импорт-нативной-функции-по-её-прототипу-во-время-выполнения-динамическая-линковка">Импорт нативной функции по её прототипу во время выполнения (динамическая линковка)<a class="td-heading-self-link" href="#%d0%b8%d0%bc%d0%bf%d0%be%d1%80%d1%82-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d0%bf%d0%be-%d0%b5%d1%91-%d0%bf%d1%80%d0%be%d1%82%d0%be%d1%82%d0%b8%d0%bf%d1%83-%d0%b2%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d1%8f-%d0%b2%d1%8b%d0%bf%d0%be%d0%bb%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b4%d0%b8%d0%bd%d0%b0%d0%bc%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bb%d0%b8%d0%bd%d0%ba%d0%be%d0%b2%d0%ba%d0%b0" aria-label="Heading self-link"></a></h1> -<p>puts3(format:StrChar):Int32 := :Pointer(&lsquo;puts(format:StrChar):Int32&rsquo;);</p> -<p>%puts(&lsquo;Тест вывода строки&rsquo;); # Линковка с нативной функцией во время компиляции и непосредственный вызов с оптимизацией передачи параметров -puts2(&lsquo;Тест 2 вывода строки&rsquo;); # Линковка с нативной функцией во время компиляции -puts3(&lsquo;Тест 3 вывода строки&rsquo;); # Линковка с нативной функцией во время выполнения при первом вызове puts3</p> -<ul> -<li>Парсинг исходного текста без раскрытия макросов и загрузки модулей</li> -<li>Парсинг исходного текста с раскрытием макросов (требуется загрузка модулей для зависимых и переопределяемых макросов)</li> -<li>Загружатся модули могут как в виде исходников (которые требуется парсить и компилировть/выполнять) -или в виде бинарников (в них должны быть список макросов, типов и имена объектов)</li> -<li>После парсинга получается список <strong>имен</strong> макросов, типов и объектов (TermPtr)</li> -<li>После выполнения модуля - список <strong>имен</strong> заполняется реальными объектами (ObjPtr).</li> -</ul> -<h1 id="компиляция-файла">Компиляция файла<a class="td-heading-self-link" href="#%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%86%d0%b8%d1%8f-%d1%84%d0%b0%d0%b9%d0%bb%d0%b0" aria-label="Heading self-link"></a></h1> -<ul> -<li>Парсинг исходника для построения AST (без анализа имен, связей, загрузки модулей и пр. только исходые тексты с раскрытием макросов</li> -<li></li> -</ul> -<h1 id="систематизация-реализации-макросов">Систематизация реализации макросов<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0%d1%82%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d1%80%d0%b5%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d0%b8-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2" aria-label="Heading self-link"></a></h1> -<p>последовательность лексем MACRO_SEQ мужду @@ @@ сохраняется в m_block, так как фрагменты блоков не могут быть идентификаторами</p> -<p>Разбор макросов происходит в лексере. Определением макроса всегда является целая строка, -которая заканчивается точкой с запятой, а идентификатором макроса всегда выступает последовательность лексем:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> @@ id @@ :<span style="color:#ce5c00;font-weight:bold">=</span> macro<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@ id @@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ @@<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@ id @@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@@ @@@<span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>Хранилищем текущих максросов является объект класса MacroBuffer. -Последовательность лексем идентификатора (id) макроса должна сохраняется в отдельном поле термина и однозначно его идентифицирует. -Первый термин в идентификаторе хранится как ключ hashmap, а дальше происходит поиск полным перебором. -Этапы работы с макросами</p> -<ul> -<li> -<p>Входные термины из лексера получаются вызовом GetNextToken, внутри которой и происходит раскрытие макросов. -Внутренний буфер заполняется до окончания строки (выражения), т.е. до символа &lsquo;;&rsquo; или <END>, после чего производится -поиск макросов в объекте MacroBuffer для текущей последовательности лексем в буфере.</p> -</li> -<li> -<p>Если макрос найден, то соответствющая ему последоваетльность заменяется на тело макроса и происходит переход -на повторный анализ входного буфера.</p> -</li> -<li> -<p>Если макрос не найден, то данные передаются в парсер для дальнейшего синтаксическго анализа.</p> -</li> -<li> -<p>Для этого во входном потоке лексем (parser.y) во время оператората создания/присвоения вызывается функция проверки на макрос. -MacroBuffer::CheckMacroAndConvertDel($$), и после этого выходному значению присваивается результат выполнения driver.MacroEval($$), -и в дальнейшем этот макрос никак не обработывается.</p> -</li> -<li> -<p>Создание макросов, проверка на дубликаты и логические ошибки в определении происходит путем обращения к методам объекта MacroBuffer.</p> -<p>/*</p> -<ul> -<li>Макросы хрянтся как фрагменты AST в виде объектов типа Term,</li> -<li>так как создаются после обработки парсером по правилам стандратной грамматики.</li> -<li></li> -<li>Но анализ входных данных на предмет раскрытия макросов проиходит из потока (последовательности) лексем,</li> -<li>т.е. <strong>ДО</strong> обработки парсером, так как при раскрытии макросов может меняться грамматика выражений.</li> -<li></li> -<li>Функция \ref CompareMacro сравнивает входной буфер (последовательность лексем)</li> -<li>на предмет возможного соответствия одному конкретному макросу.</li> -<li>Сравниваются только ключевые словам без учета аргументов в скобках,</li> -<li>но само наличие аргументов проверяется ??????????????????</li> -<li></li> -<li>Проблема:</li> -<li>К функции можно обратится с целью её вызова (указав после имени скобки),</li> -<li>так и по имени без скобок (например для получения ссылки на объект).</li> -<li>Так и к переменной можно обратиться только по имени,</li> -<li>так и указав скобки после имени как к функции (при копировании объекта).</li> -<li></li> -<li>Сделать один макрос под оба сценария (со скобками и без скобок) не получится, так как непонятно,</li> -<li>что делать с аргументами при раскрытии тела макроса, когда они не указаны.</li> -<li></li> -<li>Но может быть следует переименовывать только одно имя без учета скобок,</li> -<li>например, оставив такую возможность только для одиночных макросов.</li> -<li></li> -<li>\name -&gt; name или name (&hellip;), hash: name</li> -<li>но \name(&hellip;) -&gt; name(&hellip;), а name - ошибка !!!! hash: name</li> -<li></li> -<li>Или все же следует различать макросы со скобками и без скобок как два разных объекта???</li> -<li>\name := name2; и \name(&hellip;) := name2(&hellip;); будут разными объектами</li> -<li></li> -<li>Или добавить макросы-алиасы без аргументов только для переименования отдельных терминов?</li> -<li>\alias :- name2; но как их отличать от обычных макросов в операции удаления?</li> -<li>Или вообще не нужно отличать и оставить только один варинат (либо макрос, либо алиас)</li> -<li>Тода вопрос со скобками закрывается сам собой, алиасы всегда без скобок,</li> -<li>макросы со скбками или без скобок, но должно быть полное соответствие.</li> -<li></li> -<li>@ name name2 @ -&gt; name name2, но name name2(&hellip;) - ошибка!!! (hash: name,name2)</li> -<li>@ name name2(&hellip;) @ -&gt; name name2(&hellip;), но name name2 - ошибка !!!! (hash: name,name2)</li> -<li>@ name name2<a href="...">&hellip;</a> @ -&gt; name name2<a href="...">&hellip;</a>, но name name2 - ошибка !!!! ( hash: name,name2 )</li> -<li>@ name $tmpl<a href="...">&hellip;</a> name3@ -&gt; name $tmpl<a href="...">&hellip;</a> name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )</li> -<li></li> -<li>Но!</li> -<li>@ name name2 @ ::- -&gt; name name2 - ок, но name name2(&hellip;) - ок</li> -<li>@ name $tmpl name3@ ::- -&gt; name $tmpl<a href="...">&hellip;</a> name3 - ок, name $tmpl(&hellip;) name3[&hellip;] - ок</li> -<li></li> -<li></li> -<li></li> -<li>Для последовательности лексем требуется полное соответствие с учетом скобок ???</li> -<li>и может ли быть несколько скобок одного типа (несколько крыглях, или несколько квардратных????</li> -<li>&lt;Может быть несколько скобок одного типа, например, при указании типа у аргументов или типа возвращаемого значения.&gt;</li> -<li></li> -<li>@ name name2 @ -&gt; name name2, но name name2(&hellip;) - ошибка!!! (hash: name,name2)</li> -<li>@ name name2(&hellip;) @ -&gt; name name2(&hellip;), но name name2 - ошибка !!!! (hash: name,name2)</li> -<li>@ name name2<a href="...">&hellip;</a> @ -&gt; name name2<a href="...">&hellip;</a>, но name name2 - ошибка !!!! ( hash: name,name2 )</li> -<li>@ name $tmpl<a href="...">&hellip;</a> name3@ -&gt; name $tmpl<a href="...">&hellip;</a> name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )</li> -<li></li> -<li>Проблема скобок возникает из-за сценария замены одного термина на другой,</li> -<li>который есть в препроцессоре С/С++, но отсутствует при реализации с использованием шаблонов.</li> -<li></li> -<li></li> -</ul> -<p>*/</p> -</li> -</ul> -<p>Макросы используются и для превращеня исходного кода <em>NewLang</em> в более привычный синтаксис на основе <a href="https://newlang.net/syntax_dsl.html">ключевых слов</a>, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода.</p> -<p><a href="https://newlang.net/syntax_dsl.html">Например:</a>.</p> -<pre tabindex="0"><code> @@if(...)@@ ::= @@ [ \$* ]--&gt; @@; - @@while(...)@@ ::= @@ [\$*] &lt;-&gt; @@; - @@return $arg@@::= @@ -- \$arg -- @@; - @@true@@ ::= 1; -</code></pre><p>Тогда цикл до 5:</p> -<pre tabindex="0"><code>count:=1; -[ 1 ] &lt;-&gt; { - [count&gt;5] --&gt; { - -- 42 --; - }; - count+=1; -}; -</code></pre><p>будет выглядеть более привычно</p> -<pre tabindex="0"><code>count:=1; -while( true ) { - if(count&gt;5) { - return 42; - }; - count+=1; -}; -</code></pre><h2 id="идеи-на-будущее">Идеи на будущее<a class="td-heading-self-link" href="#%d0%b8%d0%b4%d0%b5%d0%b8-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5" aria-label="Heading self-link"></a></h2> -<h3 id="символьное-программирование">Символьное программирование<a class="td-heading-self-link" href="#%d1%81%d0%b8%d0%bc%d0%b2%d0%be%d0%bb%d1%8c%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> -<blockquote> -<p>Символьное программирование, часто называемое декларативным программированием, представляет собой парадигму программирования, которая использует математическую логику, отношения и символы для представления знаний и помощи в решении проблем. Вместо того, чтобы сосредотачиваться на описании последовательности операций, необходимых для выполнения вычислений, как в императивном программировании, символическое программирование делает упор на выражении отношений и ограничений между структурами данных, уделяя особое внимание «что», а не «как».</p> -<p>В контексте парадигм программирования символическое программирование часто противопоставляется процедурному или императивному программированию, где программы определяют пошаговые процедуры для достижения своих целей. В то время как императивное программирование фокусируется на описании потока управления с использованием таких конструкций, как циклы и условные выражения, для управления выполнением, символическое программирование сосредоточено на выражении фактов о проблеме и позволяет выполнению естественным образом выводить последующие последствия из предоставленной информации.</p> -<p>Одним из основных преимуществ символьного программирования является его способность обеспечивать более высокий уровень абстракции, что упрощает анализ кода и снижает вероятность ошибок. Непосредственно выражая отношения и ограничения, символическое программирование позволяет разработчикам сосредоточиться на моделировании и спецификации проблем, позволяя базовой системе управлять реализацией и выполнением алгоритмов.</p> -<p>Существует несколько языков программирования и сред, использующих парадигму символьного программирования, например Prolog, Lisp и Haskell. Например, Пролог — это язык логического программирования, который позволяет разработчикам выражать взаимосвязи и факты о проблемных областях, в то время как выполнение автоматически обосновывает и извлекает новые факты на основе исходной информации. В том же духе Лисп, функциональный язык программирования, использует символьные вычисления для манипулирования структурами данных и выполнения сложных операций над ними, используя краткий и математически обоснованный синтаксис. Haskell, еще один функциональный язык программирования, использует строгую типизацию и ленивые вычисления, чтобы обеспечить символическое рассуждение и облегчить эффективное создание программ.</p> -<p>Символьное программирование может быть полезным в широком спектре проблемных областей, включая искусственный интеллект, экспертные системы, программирование логики ограничений и символьную математику, среди других. Более высокий уровень абстракции, обеспечиваемый декларативными языками программирования, облегчает разработку сложных систем, сводя к минимуму вероятность ошибки и улучшая удобство обслуживания. В частности, использование символьного программирования в искусственном интеллекте позволяет разработчикам создавать системы представления знаний и механизмы рассуждения, которые можно применять для обработки естественного языка, машинного обучения и автоматического доказательства теорем.</p> -</blockquote> -<p>Различие между символьным программированием и препроцессором</p> -<ul> -<li>Задача препроцессора - раскрыть(расширить) макрос, тогда как при символьном программировании нужно сокращать (сворачивать) выражения</li> -<li>Препроцессор обрабатывает последовательности лексем (плоские данные), тогда как символьное программирование оперирует выражениями (деревом лексем)</li> -<li>Макрос у препроцессора идентифицируется первым термином, и если макрос не может быть раскрыт, то возникает ошибка. В символьном программировани требуется точное соответствие всего выражения и только в этом случае производится сокращение выражения.</li> -</ul> -<p>Предпосылки для реализации символьного программирования -Компилятор - интерепретатор с REPL и обработка AST как во время компиляции, так и во время выполнения. -Необходимо добавить конструкции для определения правил символьного программрования (чистые функции?) -Необходимо добавить конструкцию для вычисления выражений в символьном программировании.</p> -<p>Wolfram -<a href="https://habr.com/articles/772984/">https://habr.com/articles/772984/</a></p> -<pre tabindex="0"><code>diffRules = { - Sin[x] -&gt; Cos[x], - Cos[x] -&gt; -Sin[x], - x^2 -&gt; 2*x, - x -&gt; 1, - Log[x] -&gt; 1/x -}; -</code></pre><pre tabindex="0"><code>diffRules := ( - Sin(x) @-&gt; Cos(x), - Cos(x) @-&gt; -Sin(x), - x^2 @-&gt; 2*x, - x @-&gt; 1, - Log(x) @-&gt; 1\x, -); - -expr @-&gt; Sin(x) - x^2 + Log(x); - -# И применим к нему правила дифференцирования - -#expr /. diffRules -#(* 1/x - 2 x + Cos[x] *) - -sym := SymEval(expr, diffRules); -res := Eval(sym, x=0.123); -</code></pre><pre tabindex="0"><code>expr = a^2 + 3 * b^3 - c^4 + 2 * x^2 - x + 4*c + 3 - -И я хочу это выражение линеаризовать, т.е. отбросить все степени выше первой. Я могу сделать это напрямую, как в примерах выше: - -expr /. { - a^2 -&gt; 0, - b^3 -&gt; 0, - c^4 -&gt; 0, - x^2 -&gt; 0 -} -(* 3 + 4 c - x *) - -Но это слишком неудобно. Что если я не знаю ни точную степень, ни имя переменной? Как просто указать, что нужно заменить все места, где встречается возведение в степень на ноль? Это можно сделать при помощи шаблонов вот так: - -expr /. Power[_, _] -&gt; 0 -(* 3 + 4 c - x *) - -Либо вот так: - -expr /. _ ^ _ -&gt; 0 -(* 3 + 4 c - x *) -</code></pre><pre tabindex="0"><code>:diffRules() := { - {@ Sin(x) @} ::- {@ Cos(x) @}; - Cos(x) @-&gt; -Sin(x), - x^2 @-&gt; 2*x, - x @-&gt; 1, - Log(x) @-&gt; 1\x, -}; - -expr @-&gt; Sin(x) - x^2 + Log(x); - -# И применим к нему правила дифференцирования - -#expr /. diffRules -#(* 1/x - 2 x + Cos[x] *) - -sym := SymEval(expr, diffRules); -res := Eval(sym, x=0.123); -</code></pre> +</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Writing a conditional statement using</span> +</span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># the macros defined above</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@if</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">condition</span> <span style="color:#000;font-weight:bold">){</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">...</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> <span style="color:#5c35cc;font-weight:bold">@elif</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">condition2</span> <span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">...</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> <span style="color:#5c35cc;font-weight:bold">@else</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">...</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span></code></pre></div><p>For example, a loop up to 5:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">[</span> <span style="color:#0000cf;font-weight:bold">1</span> <span style="color:#000;font-weight:bold">]</span> <span style="color:#ce5c00;font-weight:bold">&lt;-&gt;</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">[</span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#0000cf;font-weight:bold">5</span> <span style="color:#000;font-weight:bold">]</span> <span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">--</span> <span style="color:#0000cf;font-weight:bold">42</span> <span style="color:#ce5c00;font-weight:bold">--</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span><span style="display:flex;"><span> <span style="color:#000">count</span><span style="color:#ce5c00;font-weight:bold">+=</span><span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span></code></pre></div><p>This will look more familiar:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@while</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">true</span> <span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@if</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#0000cf;font-weight:bold">5</span> <span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@return</span> <span style="color:#0000cf;font-weight:bold">42</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span><span style="display:flex;"><span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">+=</span> <span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span></code></pre></div> </div> diff --git a/docs/docs/syntax/memory/index.html b/docs/docs/syntax/memory/index.html index 91386b1f..4197e916 100644 --- a/docs/docs/syntax/memory/index.html +++ b/docs/docs/syntax/memory/index.html @@ -152,7 +152,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child active-path" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="td-sidebar-nav-active-item">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -183,7 +183,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/syntax/modules/index.html b/docs/docs/syntax/modules/index.html index 0617692f..f19c7d33 100644 --- a/docs/docs/syntax/modules/index.html +++ b/docs/docs/syntax/modules/index.html @@ -144,7 +144,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -175,7 +175,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/syntax/namespace/index.html b/docs/docs/syntax/namespace/index.html index bb8de3fb..a3c62c0f 100644 --- a/docs/docs/syntax/namespace/index.html +++ b/docs/docs/syntax/namespace/index.html @@ -148,7 +148,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -179,7 +179,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/syntax/naming/index.html b/docs/docs/syntax/naming/index.html index 756e554b..dbfc18ed 100644 --- a/docs/docs/syntax/naming/index.html +++ b/docs/docs/syntax/naming/index.html @@ -140,7 +140,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -171,7 +171,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/syntax/pragmas/index.html b/docs/docs/syntax/pragmas/index.html index 84c22814..e457eae0 100644 --- a/docs/docs/syntax/pragmas/index.html +++ b/docs/docs/syntax/pragmas/index.html @@ -156,7 +156,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child active-path" id="m-docssyntaxpragmas-li"> @@ -187,7 +187,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/syntax/sysmacro/index.html b/docs/docs/syntax/sysmacro/index.html index 4f231cfb..936069a3 100644 --- a/docs/docs/syntax/sysmacro/index.html +++ b/docs/docs/syntax/sysmacro/index.html @@ -144,7 +144,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -175,7 +175,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/syntax/sysprop/index.html b/docs/docs/syntax/sysprop/index.html index 401b5ecf..b82c4f03 100644 --- a/docs/docs/syntax/sysprop/index.html +++ b/docs/docs/syntax/sysprop/index.html @@ -152,7 +152,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child active-path" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="td-sidebar-nav-active-item">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -183,7 +183,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/types/_print/index.html b/docs/docs/types/_print/index.html index b3cc369f..606aa5b6 100644 --- a/docs/docs/types/_print/index.html +++ b/docs/docs/types/_print/index.html @@ -191,7 +191,7 @@ <h1 class="title">Типы данных</h1> -<li>9: <a href="#pg-cf08b42ee4f3746e6fd20919aa6660c8">Нативные типы</a></li> +<li>9: <a href="#pg-cf08b42ee4f3746e6fd20919aa6660c8">Native Data Types</a></li> @@ -943,22 +943,35 @@ <h3 id="еще-пример-возможностей-для-расширения <div class="td-content" style="page-break-before: always"> - <h1 id="pg-cf08b42ee4f3746e6fd20919aa6660c8">9 - Нативные типы</h1> - - <h2 id="нативные-типы-данных">Нативные типы данных<a class="td-heading-self-link" href="#%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85" aria-label="Heading self-link"></a></h2> -<p>Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &ldquo;<strong>%</strong>&rdquo;. -В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат.</p> -<h3 id="pointer--указатель-на-системную-область-памяти-или-нативную-функцию">:Pointer — указатель на системную область памяти или нативную функцию<a class="td-heading-self-link" href="#pointer--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%83%d1%8e-%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8-%d0%b8%d0%bb%d0%b8-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%83%d1%8e-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8e" aria-label="Heading self-link"></a></h3> -<p>Так как любой программе приходится взаимодействовать с внешним миром, т -о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, -и для этих целей служит тип <em>:Pointer</em>. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. -Но можно вывести его значение, например для отладки.</p> -<h3 id="plain--указатель-на-представление-данных-в-бинарном-виде">:Plain — указатель на представление данных в бинарном виде<a class="td-heading-self-link" href="#plain--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d0%bf%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%be%d0%bc-%d0%b2%d0%b8%d0%b4%d0%b5" aria-label="Heading self-link"></a></h3> -<p>Для взаимодействия с внешними библиотеками требуется еще и обмен данными. -И для этих целей служит тип данных <em>:Plain</em> — который также является указателем, но на двоичное представление данных в области памяти. -Конечно, если их можно представить в виде одного фрагмента.</p> -<h3 id="перечисление-структура-и-объединение">Перечисление, структура и объединение<a class="td-heading-self-link" href="#%d0%bf%d0%b5%d1%80%d0%b5%d1%87%d0%b8%d1%81%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d0%b8-%d0%be%d0%b1%d1%8a%d0%b5%d0%b4%d0%b8%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> -<p><em>:Enum</em>, <em>:Struct</em> и <em>:Union</em> — это такие же <a href="http://localhost:1313/docs/types/dicts/#%D0%BF%D0%B5%D1%80%D0%B5%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D0%B0-%D0%B8-%D0%BE%D0%B1%D1%8A%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5">словари</a>, только на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера. Эти типы данных так же относятся к группе <em>:Plain</em> и могут быть представлены в двоичном виде в одной области машинной памяти.</p> + <h1 id="pg-cf08b42ee4f3746e6fd20919aa6660c8">9 - Native Data Types</h1> + + <p>Native (machine) data can be variables or functions, and the names of native objects start with the percent symbol &ldquo;<strong>%</strong>&rdquo;.</p> +<p>In the case of variables, these are binary data located in a single continuous area of machine memory at a specific address and have a strictly defined format.</p> +<p>To use existing libraries, you need to import the native object, thereby creating an object NewLang, +but with an implementation in another language, for example, in C/C++.</p> +<p>The syntax for importing native objects is the same as for <a href="/docs/ops/create/">creating</a> regular language objects, +only the name of the native object needs to be specified as the right operand in the creation operator.</p> +<p>When importing a native object, it is necessary to always specify the variable types, +as well as the types of arguments and return values for functions.</p> +<p>If the data types of the created object and the native object match (i.e., no type conversion is required), +then the native object name can be specified with an ellipsis, +which means that the data types will replicate those specified at the left operand.</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#000">Plain</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#000">fopen</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">filename</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">StrChar</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">modes</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">StrChar</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">FILE</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fopen</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">fclose</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">f</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fclose</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">fflush</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">f</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fflush</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">fprintf</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">f</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#204a87">format</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FmtChar</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fprintf</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#000">fremove</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">filename</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">String</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">remove</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">frename</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">old</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">String</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">new</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">String</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">rename</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span></code></pre></div> + +<div class="pageinfo pageinfo-primary"> +<p>The following description is under development.</p> + +</div> + </div> diff --git a/docs/docs/types/class/index.html b/docs/docs/types/class/index.html index 200c3f53..eee9d907 100644 --- a/docs/docs/types/class/index.html +++ b/docs/docs/types/class/index.html @@ -148,7 +148,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -179,7 +179,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/types/convert/index.html b/docs/docs/types/convert/index.html index d0af1219..ee55d614 100644 --- a/docs/docs/types/convert/index.html +++ b/docs/docs/types/convert/index.html @@ -152,7 +152,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -183,7 +183,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child active-path" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="td-sidebar-nav-active-item">Преобразование типов</span></a> </li> diff --git a/docs/docs/types/dicts/index.html b/docs/docs/types/dicts/index.html index 48061ffa..b340906f 100644 --- a/docs/docs/types/dicts/index.html +++ b/docs/docs/types/dicts/index.html @@ -152,7 +152,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -183,7 +183,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/types/funcs/index.html b/docs/docs/types/funcs/index.html index cd381285..ca9e7406 100644 --- a/docs/docs/types/funcs/index.html +++ b/docs/docs/types/funcs/index.html @@ -148,7 +148,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -179,7 +179,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/types/generics/index.html b/docs/docs/types/generics/index.html index fe63436c..4bc8a60c 100644 --- a/docs/docs/types/generics/index.html +++ b/docs/docs/types/generics/index.html @@ -148,7 +148,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -179,7 +179,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/types/index.html b/docs/docs/types/index.html index c3baede0..f61fa982 100644 --- a/docs/docs/types/index.html +++ b/docs/docs/types/index.html @@ -137,7 +137,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -168,7 +168,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> @@ -313,7 +313,7 @@ <h2 id="-в-том-числе-и-конструктор-классовdocstypesc <li><a href="/docs/types/other/">Другие типы данных</a></li> - <li><a href="/docs/types/native/">Нативные типы</a></li> + <li><a href="/docs/types/native/">Native Data Types</a></li> <li><a href="/docs/types/convert/">Преобразование типов</a></li> </ul> diff --git a/docs/docs/types/index.xml b/docs/docs/types/index.xml index 78d64c3a..a4c5b0a4 100644 --- a/docs/docs/types/index.xml +++ b/docs/docs/types/index.xml @@ -665,7 +665,7 @@ Number 5 from the thread!&lt;/p&gt; </item> <item> - <title>Docs: Нативные типы</title> + <title>Docs: Native Data Types</title> <link>http://localhost:1313/docs/types/native/</link> <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate> @@ -673,20 +673,33 @@ Number 5 from the thread!&lt;/p&gt; <description> - &lt;h2 id=&#34;нативные-типы-данных&#34;&gt;Нативные типы данных&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &amp;ldquo;&lt;strong&gt;%&lt;/strong&gt;&amp;rdquo;. -В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат.&lt;/p&gt; -&lt;h3 id=&#34;pointer--указатель-на-системную-область-памяти-или-нативную-функцию&#34;&gt;:Pointer — указатель на системную область памяти или нативную функцию&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#pointer--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%83%d1%8e-%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8-%d0%b8%d0%bb%d0%b8-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%83%d1%8e-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8e&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Так как любой программе приходится взаимодействовать с внешним миром, т -о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, -и для этих целей служит тип &lt;em&gt;:Pointer&lt;/em&gt;. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. -Но можно вывести его значение, например для отладки.&lt;/p&gt; -&lt;h3 id=&#34;plain--указатель-на-представление-данных-в-бинарном-виде&#34;&gt;:Plain — указатель на представление данных в бинарном виде&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#plain--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d0%bf%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%be%d0%bc-%d0%b2%d0%b8%d0%b4%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Для взаимодействия с внешними библиотеками требуется еще и обмен данными. -И для этих целей служит тип данных &lt;em&gt;:Plain&lt;/em&gt; — который также является указателем, но на двоичное представление данных в области памяти. -Конечно, если их можно представить в виде одного фрагмента.&lt;/p&gt; -&lt;h3 id=&#34;перечисление-структура-и-объединение&#34;&gt;Перечисление, структура и объединение&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d0%b5%d1%80%d0%b5%d1%87%d0%b8%d1%81%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d0%b8-%d0%be%d0%b1%d1%8a%d0%b5%d0%b4%d0%b8%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;&lt;em&gt;:Enum&lt;/em&gt;, &lt;em&gt;:Struct&lt;/em&gt; и &lt;em&gt;:Union&lt;/em&gt; — это такие же &lt;a href=&#34;http://localhost:1313/docs/types/dicts/#%D0%BF%D0%B5%D1%80%D0%B5%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D0%B0-%D0%B8-%D0%BE%D0%B1%D1%8A%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5&#34;&gt;словари&lt;/a&gt;, только на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера. Эти типы данных так же относятся к группе &lt;em&gt;:Plain&lt;/em&gt; и могут быть представлены в двоичном виде в одной области машинной памяти.&lt;/p&gt; + &lt;p&gt;Native (machine) data can be variables or functions, and the names of native objects start with the percent symbol &amp;ldquo;&lt;strong&gt;%&lt;/strong&gt;&amp;rdquo;.&lt;/p&gt; +&lt;p&gt;In the case of variables, these are binary data located in a single continuous area of machine memory at a specific address and have a strictly defined format.&lt;/p&gt; +&lt;p&gt;To use existing libraries, you need to import the native object, thereby creating an object NewLang, +but with an implementation in another language, for example, in C/C++.&lt;/p&gt; +&lt;p&gt;The syntax for importing native objects is the same as for &lt;a href=&#34;http://localhost:1313/docs/ops/create/&#34;&gt;creating&lt;/a&gt; regular language objects, +only the name of the native object needs to be specified as the right operand in the creation operator.&lt;/p&gt; +&lt;p&gt;When importing a native object, it is necessary to always specify the variable types, +as well as the types of arguments and return values for functions.&lt;/p&gt; +&lt;p&gt;If the data types of the created object and the native object match (i.e., no type conversion is required), +then the native object name can be specified with an ellipsis, +which means that the data types will replicate those specified at the left operand.&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Plain&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fopen&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;filename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;StrChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;modes&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;StrChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fopen&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fclose&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fclose&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fflush&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fflush&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fprintf&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#204a87&#34;&gt;format&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FmtChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fprintf&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fremove&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;filename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;remove&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;frename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;old&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;new&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;rename&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; + +&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; +&lt;p&gt;The following description is under development.&lt;/p&gt; + +&lt;/div&gt; + </description> </item> diff --git a/docs/docs/types/iter/index.html b/docs/docs/types/iter/index.html index f9c0fa15..78597604 100644 --- a/docs/docs/types/iter/index.html +++ b/docs/docs/types/iter/index.html @@ -148,7 +148,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -179,7 +179,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/types/native/index.html b/docs/docs/types/native/index.html index a22a6c49..2a4f76d5 100644 --- a/docs/docs/types/native/index.html +++ b/docs/docs/types/native/index.html @@ -17,24 +17,28 @@ <link rel="icon" type="image/png" href="/favicons/android-144x144.png" sizes="144x144"> <link rel="icon" type="image/png" href="/favicons/android-192x192.png" sizes="192x192"> -<title>Нативные типы | NewLang</title> -<meta name="description" content="Нативные типы данных Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &amp;ldquo;%&amp;rdquo;. В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат. -:Pointer — указатель на системную область памяти или нативную функцию Так как любой программе приходится взаимодействовать с внешним миром, т о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип :Pointer."> -<meta property="og:title" content="Нативные типы" /> -<meta property="og:description" content="Нативные типы данных Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &ldquo;%&rdquo;. В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат. -:Pointer — указатель на системную область памяти или нативную функцию Так как любой программе приходится взаимодействовать с внешним миром, т о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип :Pointer." /> +<title>Native Data Types | NewLang</title> +<meta name="description" content="Native (machine) data can be variables or functions, and the names of native objects start with the percent symbol &amp;ldquo;%&amp;rdquo;. +In the case of variables, these are binary data located in a single continuous area of machine memory at a specific address and have a strictly defined format. +To use existing libraries, you need to import the native object, thereby creating an object NewLang, but with an implementation in another language, for example, in C/C&#43;&#43;."> +<meta property="og:title" content="Native Data Types" /> +<meta property="og:description" content="Native (machine) data can be variables or functions, and the names of native objects start with the percent symbol &ldquo;%&rdquo;. +In the case of variables, these are binary data located in a single continuous area of machine memory at a specific address and have a strictly defined format. +To use existing libraries, you need to import the native object, thereby creating an object NewLang, but with an implementation in another language, for example, in C/C&#43;&#43;." /> <meta property="og:type" content="article" /> <meta property="og:url" content="http://localhost:1313/docs/types/native/" /><meta property="article:section" content="docs" /> -<meta property="article:modified_time" content="2024-03-22T23:57:08+03:00" /><meta property="og:site_name" content="NewLang" /> -<meta itemprop="name" content="Нативные типы"> -<meta itemprop="description" content="Нативные типы данных Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &ldquo;%&rdquo;. В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат. -:Pointer — указатель на системную область памяти или нативную функцию Так как любой программе приходится взаимодействовать с внешним миром, т о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип :Pointer."> -<meta itemprop="dateModified" content="2024-03-22T23:57:08+03:00" /> -<meta itemprop="wordCount" content="214"> -<meta itemprop="keywords" content="типы данных,системые типы,коллекции," /><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Нативные типы"/> -<meta name="twitter:description" content="Нативные типы данных Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &ldquo;%&rdquo;. В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат. -:Pointer — указатель на системную область памяти или нативную функцию Так как любой программе приходится взаимодействовать с внешним миром, т о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип :Pointer."/> +<meta property="article:modified_time" content="2024-03-23T22:03:23+03:00" /><meta property="og:site_name" content="NewLang" /> +<meta itemprop="name" content="Native Data Types"> +<meta itemprop="description" content="Native (machine) data can be variables or functions, and the names of native objects start with the percent symbol &ldquo;%&rdquo;. +In the case of variables, these are binary data located in a single continuous area of machine memory at a specific address and have a strictly defined format. +To use existing libraries, you need to import the native object, thereby creating an object NewLang, but with an implementation in another language, for example, in C/C&#43;&#43;."> +<meta itemprop="dateModified" content="2024-03-23T22:03:23+03:00" /> +<meta itemprop="wordCount" content="210"> +<meta itemprop="keywords" content="типы данных,системые типы,коллекции," /><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Native Data Types"/> +<meta name="twitter:description" content="Native (machine) data can be variables or functions, and the names of native objects start with the percent symbol &ldquo;%&rdquo;. +In the case of variables, these are binary data located in a single continuous area of machine memory at a specific address and have a strictly defined format. +To use existing libraries, you need to import the native object, thereby creating an object NewLang, but with an implementation in another language, for example, in C/C&#43;&#43;."/> @@ -144,7 +148,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -175,7 +179,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child active-path" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="td-sidebar-nav-active-item">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="td-sidebar-nav-active-item">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> @@ -226,20 +230,7 @@ </div> - <div class="td-toc"> - <nav id="TableOfContents"> - <ul> - <li><a href="#нативные-типы-данных">Нативные типы данных</a> - <ul> - <li><a href="#pointer--указатель-на-системную-область-памяти-или-нативную-функцию">:Pointer — указатель на системную область памяти или нативную функцию</a></li> - <li><a href="#plain--указатель-на-представление-данных-в-бинарном-виде">:Plain — указатель на представление данных в бинарном виде</a></li> - <li><a href="#перечисление-структура-и-объединение">Перечисление, структура и объединение</a></li> - </ul> - </li> - </ul> -</nav> - </div> - + <div class="taxonomy taxonomy-terms-cloud taxo-tags"> <h5 class="taxonomy-title">Tag Cloud</h5> <ul class="taxonomy-terms"> @@ -265,12 +256,12 @@ <h5 class="taxonomy-title">Tag Cloud</h5> <li class="breadcrumb-item"> <a href="/docs/types/">Типы данных</a></li> <li class="breadcrumb-item active" aria-current="page"> - Нативные типы</li> + Native Data Types</li> </ol> </nav> <div class="td-content"> - <h1>Нативные типы</h1> + <h1>Native Data Types</h1> <header class="article-meta"> <div class="taxonomy taxonomy-terms-article taxo-tags"> @@ -283,20 +274,33 @@ <h5 class="taxonomy-title">Tags:</h5> </div> </header> - <h2 id="нативные-типы-данных">Нативные типы данных<a class="td-heading-self-link" href="#%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85" aria-label="Heading self-link"></a></h2> -<p>Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &ldquo;<strong>%</strong>&rdquo;. -В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат.</p> -<h3 id="pointer--указатель-на-системную-область-памяти-или-нативную-функцию">:Pointer — указатель на системную область памяти или нативную функцию<a class="td-heading-self-link" href="#pointer--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%83%d1%8e-%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8-%d0%b8%d0%bb%d0%b8-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%83%d1%8e-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8e" aria-label="Heading self-link"></a></h3> -<p>Так как любой программе приходится взаимодействовать с внешним миром, т -о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, -и для этих целей служит тип <em>:Pointer</em>. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. -Но можно вывести его значение, например для отладки.</p> -<h3 id="plain--указатель-на-представление-данных-в-бинарном-виде">:Plain — указатель на представление данных в бинарном виде<a class="td-heading-self-link" href="#plain--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d0%bf%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%be%d0%bc-%d0%b2%d0%b8%d0%b4%d0%b5" aria-label="Heading self-link"></a></h3> -<p>Для взаимодействия с внешними библиотеками требуется еще и обмен данными. -И для этих целей служит тип данных <em>:Plain</em> — который также является указателем, но на двоичное представление данных в области памяти. -Конечно, если их можно представить в виде одного фрагмента.</p> -<h3 id="перечисление-структура-и-объединение">Перечисление, структура и объединение<a class="td-heading-self-link" href="#%d0%bf%d0%b5%d1%80%d0%b5%d1%87%d0%b8%d1%81%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d0%b8-%d0%be%d0%b1%d1%8a%d0%b5%d0%b4%d0%b8%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> -<p><em>:Enum</em>, <em>:Struct</em> и <em>:Union</em> — это такие же <a href="http://localhost:1313/docs/types/dicts/#%D0%BF%D0%B5%D1%80%D0%B5%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D0%B0-%D0%B8-%D0%BE%D0%B1%D1%8A%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5">словари</a>, только на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера. Эти типы данных так же относятся к группе <em>:Plain</em> и могут быть представлены в двоичном виде в одной области машинной памяти.</p> + <p>Native (machine) data can be variables or functions, and the names of native objects start with the percent symbol &ldquo;<strong>%</strong>&rdquo;.</p> +<p>In the case of variables, these are binary data located in a single continuous area of machine memory at a specific address and have a strictly defined format.</p> +<p>To use existing libraries, you need to import the native object, thereby creating an object NewLang, +but with an implementation in another language, for example, in C/C++.</p> +<p>The syntax for importing native objects is the same as for <a href="/docs/ops/create/">creating</a> regular language objects, +only the name of the native object needs to be specified as the right operand in the creation operator.</p> +<p>When importing a native object, it is necessary to always specify the variable types, +as well as the types of arguments and return values for functions.</p> +<p>If the data types of the created object and the native object match (i.e., no type conversion is required), +then the native object name can be specified with an ellipsis, +which means that the data types will replicate those specified at the left operand.</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#000">Plain</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#000">fopen</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">filename</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">StrChar</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">modes</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">StrChar</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">FILE</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fopen</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">fclose</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">f</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fclose</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">fflush</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">f</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fflush</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">fprintf</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">f</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#204a87">format</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FmtChar</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fprintf</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#000">fremove</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">filename</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">String</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">remove</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">frename</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">old</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">String</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">new</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">String</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">rename</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span></code></pre></div> + +<div class="pageinfo pageinfo-primary"> +<p>The following description is under development.</p> + +</div> + </div> diff --git a/docs/docs/types/numbers/index.html b/docs/docs/types/numbers/index.html index b442527a..645f2fc1 100644 --- a/docs/docs/types/numbers/index.html +++ b/docs/docs/types/numbers/index.html @@ -140,7 +140,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -171,7 +171,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/types/other/index.html b/docs/docs/types/other/index.html index bdc284a1..081a509f 100644 --- a/docs/docs/types/other/index.html +++ b/docs/docs/types/other/index.html @@ -148,7 +148,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -179,7 +179,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child active-path" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="td-sidebar-nav-active-item">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/docs/types/strings/index.html b/docs/docs/types/strings/index.html index 35ba5a3d..1a98ea70 100644 --- a/docs/docs/types/strings/index.html +++ b/docs/docs/types/strings/index.html @@ -144,7 +144,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmemory-li"> <a href="/docs/syntax/memory/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmemory"><span class="">Управление памятью, ссылки и совместный доступ</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxmacros-li"> - <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Макросы</span></a> + <a href="/docs/syntax/macros/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxmacros"><span class="">Macros</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxsysprop-li"> <a href="/docs/syntax/sysprop/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docssyntaxsysprop"><span class="">Системные свойства</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docssyntaxpragmas-li"> @@ -175,7 +175,7 @@ </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesother-li"> <a href="/docs/types/other/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesother"><span class="">Другие типы данных</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesnative-li"> - <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Нативные типы</span></a> + <a href="/docs/types/native/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesnative"><span class="">Native Data Types</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-docstypesconvert-li"> <a href="/docs/types/convert/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-docstypesconvert"><span class="">Преобразование типов</span></a> </li> diff --git a/docs/en/sitemap.xml b/docs/en/sitemap.xml index dfa84852..47b1cb66 100644 --- a/docs/en/sitemap.xml +++ b/docs/en/sitemap.xml @@ -3,7 +3,7 @@ xmlns:xhtml="http://www.w3.org/1999/xhtml"> <url> <loc>http://localhost:1313/docs/syntax/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="ru" @@ -146,7 +146,7 @@ /> </url><url> <loc>http://localhost:1313/docs/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="ru" @@ -198,7 +198,7 @@ /> </url><url> <loc>http://localhost:1313/playground/</loc> - <lastmod>2024-03-23T12:49:56+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="ru" @@ -301,30 +301,30 @@ href="http://localhost:1313/docs/types/funcs/" /> </url><url> - <loc>http://localhost:1313/docs/types/iter/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> + <loc>http://localhost:1313/docs/syntax/macros/</loc> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="ru" - href="http://localhost:1313/ru/docs/types/iter/" + href="http://localhost:1313/ru/docs/syntax/macros/" /> <xhtml:link rel="alternate" hreflang="en" - href="http://localhost:1313/docs/types/iter/" + href="http://localhost:1313/docs/syntax/macros/" /> </url><url> - <loc>http://localhost:1313/docs/syntax/macros/</loc> + <loc>http://localhost:1313/docs/types/iter/</loc> <lastmod>2024-03-22T23:57:08+03:00</lastmod> <xhtml:link rel="alternate" hreflang="ru" - href="http://localhost:1313/ru/docs/syntax/macros/" + href="http://localhost:1313/ru/docs/types/iter/" /> <xhtml:link rel="alternate" hreflang="en" - href="http://localhost:1313/docs/syntax/macros/" + href="http://localhost:1313/docs/types/iter/" /> </url><url> <loc>http://localhost:1313/docs/types/other/</loc> @@ -341,7 +341,7 @@ /> </url><url> <loc>http://localhost:1313/docs/types/native/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="ru" @@ -419,7 +419,7 @@ /> </url><url> <loc>http://localhost:1313/docs/syntax/dsl/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="ru" @@ -495,19 +495,6 @@ hreflang="en" href="http://localhost:1313/blog/release-v0.4/" /> - </url><url> - <loc>http://localhost:1313/blog/parser-nuances/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/parser-nuances/" - /> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/parser-nuances/" - /> </url><url> <loc>http://localhost:1313/blog/dsl-domain-specific-language-implementation-with-macros/</loc> <lastmod>2024-03-22T23:57:08+03:00</lastmod> @@ -521,136 +508,6 @@ hreflang="en" href="http://localhost:1313/blog/dsl-domain-specific-language-implementation-with-macros/" /> - </url><url> - <loc>http://localhost:1313/blog/release-v0.3/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/release-v0.3/" - /> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/release-v0.3/" - /> - </url><url> - <loc>http://localhost:1313/blog/release-v0.2/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/release-v0.2/" - /> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/release-v0.2/" - /> - </url><url> - <loc>http://localhost:1313/blog/release-v0.1/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/release-v0.1/" - /> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/release-v0.1/" - /> - </url><url> - <loc>http://localhost:1313/blog/newlang/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/newlang/" - /> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/newlang/" - /> - </url><url> - <loc>http://localhost:1313/blog/prog-styles-same-time/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/prog-styles-same-time/" - /> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/prog-styles-same-time/" - /> - </url><url> - <loc>http://localhost:1313/blog/unusual-prog/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/unusual-prog/" - /> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/unusual-prog/" - /> - </url><url> - <loc>http://localhost:1313/blog/complex-prog/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/complex-prog/" - /> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/complex-prog/" - /> - </url><url> - <loc>http://localhost:1313/blog/lang-final/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/lang-final/" - /> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/lang-final/" - /> - </url><url> - <loc>http://localhost:1313/blog/logic-prog/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/logic-prog/" - /> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/logic-prog/" - /> - </url><url> - <loc>http://localhost:1313/blog/inter-prog/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/inter-prog/" - /> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/inter-prog/" - /> </url><url> <loc>http://localhost:1313/categories/</loc> <xhtml:link @@ -665,7 +522,7 @@ /> </url><url> <loc>http://localhost:1313/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="ru" @@ -691,7 +548,7 @@ /> </url><url> <loc>http://localhost:1313/tags/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="ru" @@ -717,7 +574,7 @@ /> </url><url> <loc>http://localhost:1313/tags/%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="ru" @@ -743,7 +600,7 @@ /> </url><url> <loc>http://localhost:1313/tags/%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="ru" @@ -756,7 +613,7 @@ /> </url><url> <loc>http://localhost:1313/tags/%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="ru" diff --git a/docs/index.html b/docs/index.html index a92c4951..b737c51d 100644 --- a/docs/index.html +++ b/docs/index.html @@ -110,7 +110,7 @@ <div class="col-12"> <div class="container td-overlay__inner"> <div class="text-center"> - <h1 class="display-1 mt-0 mt-md-5 pb-4">Добро пожаловать на сайт проекта NewLang!</h1> + <h1 class="display-1 mt-0 mt-md-5 pb-4">Welcome to the NewLang project website!</h1> <div class="pt-3 lead"> @@ -156,14 +156,14 @@ <h1 class="display-1 mt-0 mt-md-5 pb-4">Добро пожаловать на с -<p class="lead"><em>NewLang</em> — это язык программирования высокого уровня общего назначения c базовым синтаксисом на основе грамматических правил. - С помощью макросов препроцесора, базовый синтаксис легко преобразуется в DSL на основе ключевых слов.</p> +<p class="lead"><em>NewLang</em> — NewLang is a general-purpose high-level programming language with a syntax based on a strict system of grammatical rules. +<br>But with the help of preprocessor macros, the syntax is turned into DSL based on keywords..</p> -<p class="lead">Тензорные вычисления и рациональные числа не ограниченной точности поддерживаются - на уровне синтаксиса языка и базовых типов данных без использования дополнительных библиотек.</p> +<p class="lead">Tensor calculations and rationals of unlimited precision are supported at the level of language syntax and basic + data types without the use of additional libraries.</p> -<p class="lead">Модель управления памятью на основе владения не трубет использования сборщика мусора - и исключет основные ошибки еще на этапе компиляции исходного текста программы.</p> +<p class="lead">The ownership-based memory management model does not require the use of + a garbage collector and eliminates major errors at the stage of compiling the source code of the program.</p> </div> @@ -181,48 +181,49 @@ <h1 class="display-1 mt-0 mt-md-5 pb-4">Добро пожаловать на с <h3> - Основные свойства и особенности языка: +The main properties and features: </h3> <ul> - <li>возможность работы как в режиме интерпретатора, так и компилятора<b>*</b> - </li> +<li>the ability to work both in interpreter and compiler mode<b>*</b> +</li> - <li>динамическая и статическая типизация с возможностью указания типов в явном виде - </li> +<li>dynamic and static typing with the ability to specify types explicitly +</li> - <li>статическая типизация является условно-строгой - <em>(автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных. - Например, целое число может быть автоматически преобразовано в вещественное или рациональное, но не наоборот)</em> - </li> +<li>static typing is conditionally strong (there is no automatic type casting, but conversion between some data types is allowed. + For example, an integer can be automatically converted to real or rational, but not vice versa) +</li> - <li>автоматическое управление памятью без сборщика мусора на основе владения<b>*</b> - </li> +<li>automatic memory management without garbage collector<b>*</b> +</li> - <li>ООП* в виде явного наследования классов и «утиная типизация» - </li> +<li>bject-oriented programming in the form of explicit class inheritance and "duck typing"<b>*</b> +</li> - <li>на уровне синтаксиса поддерживается несколько типов функций (обычные и чистые функции без побочных эффектов) - </li> +<li>several types of functions (regular and pure functions without side effects) are supported at the syntax level of the language +</li> - <li>необязательные и именованные параметры функций - </li> +<li>optional and named function arguments +</li> - <li>простая интеграция с уже существующими программными библиотеками - (в том числе импорт нативных переменных, функций и классов* из С/С++.) - </li> +<li>direct insertion of C/C++ code is possible<b>*</b> +</li> - <li>имеется <a href="https://ru.wikipedia.org/wiki/REPL">REPL (read-eval-print loop — «цикл: чтение — вычисление — вывод»)</a> - </li> - - <li>символьные вычисления<b>**</b> - </li> +<li>easy integration with existing software libraries (including import of native variables, functions and classes* from C/C++). +</li> + +<li>there is a <a href="https://en.wikipedia.org/wiki/REPL">REPL (read-eval-print loop)</a> +</li> + +<li>symbolic calculations<b>**</b> +</li> </ul> <hr> -<b>*</b>) Данные возможности запланированы к реализации +<b>*</b>) These features are planned for implementation when the compiler is created. <br> -<b>**</b>) Символьные вычисления поддерживаются на уровне синтаксиса, но не реализованы +<b>**</b>) Symbolic calculations are supported at the syntax level, but not implemented. </div> @@ -237,59 +238,53 @@ <h3> -<h2>Зачем нужен <em>NewLang</em>? +<h2>Why do we need <em>NewLang</em>? </h2> <p> - У всех современных языков программирования происходит постоянное <a href="/blog/complex-prog/">развитие (усложнение) синтаксиса</a> по мере выхода новых версий.<br> - Это является своего рода платой за появление новых возможностей языка и воспринимается пользователями как естественное явление. +All modern programming languages have a constant <a href="/blog/complex-prog/">development (complication) of syntax</a> as new versions are released.<br> +This is a kind of payment for the emergence of new features and is perceived by users as a natural process. <p> <p> - Но одновременно является и серьезной проблемой, так как с выходом новых версий языка в него добавляются новые ключевые слова и синтаксические конструкции, - что неизбежно повышает порог входа для всех новых пользователей. -<p> -<p> - Еще одним следствием этого процесса становится постоянное увеличение сложности разработки и поддержки уже созданных программных продуктов, - когда старый программный код дорабатывается с применением уже новых стандартов и постоянным увеличением старого легаси кода. +But at the same time it is also a serious problem, since with the release of versions new keywords and syntactic constructions are added, +which inevitably raises the entry threshold for new users. </p> <p> - У <em>NewLang</em> сложность языковых конструкций ограничена естественным образом - за счет разделения синтаксиса языка на несколько частей, что упрощает его изучение и использование. +Another consequence of this process is the constant increase in the complexity of developing and supporting already created software products, +when the old code is being finalized using the already new standards. </p> <p> - <em>Основной (базовый) синтаксис</em> — на системе строгих <a href="/docs/syntax/">грамматических правил</a>. +<em>NewLang</em> naturally limits the complexity of language constructs by splitting the syntax of the language into two parts, +making it easier to learn and use. </p> -<p> - <em>Синтаксис DSL (domain-specific language)</em> — хотя базовый синтаксис самодостаточен и полснотью покрывает все возможные сценарии использования, - но его применение разработчиками напрямую не всегда эффекстивно с точки зрения последующего чтения исходноиков. - <br> - Поэтому более правильным вариантом написания исходного кода программы будет применение <a href="/docs/syntax/dsl/">предметно-ориентированного языка</a>, - который реализуется с помощью макросов препроцессора и превращает базовый синтаксис на основе <a href="/docs/syntax/">грамматических правил</a> - в синтаксис на основе <a href="/docs/syntax/dsl/">ключевых слов</a>. -</p> <p> - <em>Расширенный синтаксис</em> — программные вставки на языке реализации (С/С++), когда основного или DSL синтаксиса становится недостаточно. +<em>Basic syntax</em> - for writing programs in object-oriented (imperative) and declarative styles, +which is based not on reserved keywords, but on a system of strict <a href="/docs/syntax/">grammar rules</a>. +It is possible to extend the basic syntax through the use of macros.<br> + +<em>Extended syntax</em> - program inserts in the implementation language (C / C ++), when the main syntax becomes insufficient. </p> + <br> <p> - Еще одно неудобство современных языков в том, что большинство из них были созданы еще до начала эпохи машинного обучения, - поэтому тензорные вычисления у них выполнены в виде отдельных библиотек. - Это же касается и вычислений с неограниченной точностью, которые также требуют использования дополнительных библиотечных функций. +Another disadvantage of modern languages is that most of them were created before the era of machine learning, +therefore, tensor calculations are performed in the form of separate libraries.<br> +The same applies to calculations with unlimited precision, which also require the use of additional library functions. </p> <p> - У <em>NewLang</em> тензорные вычисления и рациональные числа неограниченной точности доступны «из коробки». - Они поддерживаются на уровне синтаксиса для удобной записи литералов, - а простые арифметические типы данных являются скалярами (тензорами нулевой размерности). - <br> - <br> - Реализация тензорных вычислений сделана на базе библиотеки <a href="https://pytorch.org/">libtorch</a>, - а рациональные числа с использованием <a href="https://github.com/openssl/openssl/blob/master/crypto/bn/README.pod">OpenSSL</a>. +<em>NewLang</em> has tensor calculus and unlimited-precision rationals out of the box.<br> + +They are supported at the syntax level for writing literals of the corresponding types, +and simple arithmetic data types are scalars (tensors of dimension zero).<br> + +The implementation of tensor calculations is based on the library <a href="https://pytorch.org/">libtorch</a>, +and rational numbers using <a href="https://github.com/openssl/openssl/blob/master/crypto/bn/README.pod">OpenSSL</a>. </p> @@ -305,48 +300,46 @@ <h2>Зачем нужен <em>NewLang</em>? -<h4>Пример скрипта Hello world! на NewLang</h4> +<h4>Hello world script example in NewLang</h4> <br> <code> <pre> - #!../output/nlc --eval - - hello(str) := { - # Импорт и вызов функции printf стандартной библиотеки - printf(format:FmtChar, ...):Int32 := %printf...; - printf('call: %s', $str); - $str; - }; - hello('Привет, мир!'); + #!../output/nlc + + printf('Hello, world!'); </pre> </code> -Вывод: +Output: <code><pre> - call: Привет, мир! - Привет, мир! - </pre></code> + Hello, world! + 14 +</pre></code> -<h4>Пример вычисления факториала 40 на NewLang (базовый синтаксис)</h4> +<h4>An example of calculating factorial 40 on NewLang (base syntax)</h4> <br> <code> <pre> - #!../output/nlc --eval + #!../output/nlc + + ### Example of calculating factorial of 40 using basic syntax - fact := 1\1; # Рациональное число 1 (без ограничения точности) - mult := 40..1..-1?; # Итератор из диапазона для множителей от 40 до 2 - [mult ?!] <-> { # Цикл, пока не закончатся данные итератора - fact *= mult !; # Получить текущий множитель и перейти на следующий элемент итератора - }; + fact := 1\1; # Rational number 1 (no precision limit) + mult := 40..1..-1?; # Iterator from range for factors from 40 to 2 + [mult ?!] <-> { # Loop until the iterator data runs out + fact *= mult !; # Get the current multiplier and move to the next iterator element + }; - fact # Вывести итоговый результат + @assert(fact == 815915283247897734345611269596115894272000000000\1); + + fact # Return final result </pre> </code> -Вывод: +Output: <code> <pre> 815915283247897734345611269596115894272000000000\1 @@ -354,25 +347,30 @@ <h4>Пример вычисления факториала 40 на NewLang (ба </code> -<h4>Тот же код с использованием DSL синтаксиса</h4> + +<h4>Same code using <a href="/docs/syntax/dsl/">DSL syntax</a></h4> <br> <code> <pre> - #!../output/nlc --eval + #!../output/nlc + + ### Example of calculating factorial 40 using DSL syntax + + fact := 1\1; # Rational number 1 (no precision limit) + mult := @iter( 40..1..-1 ); # Iterator from range for factors from 40 to 2 + @while( @curr(mult)) { # Loop until the iterator data runs out + fact *= @next(mult); # Get the current multiplier and move to the next iterator element + }; - fact := 1\1; - mult := iter( 40..1..-1 ); - while( curr(mult) ) { - fact *= next(mult); - }; + @assert(fact == 815915283247897734345611269596115894272000000000\1); - fact; + fact # Return final result </pre> </code> -Вывод: +Output: <code> <pre> 815915283247897734345611269596115894272000000000\1 @@ -386,14 +384,14 @@ <h4>Тот же код с использованием DSL синтаксиса< <div class="col"> <div class="container"> -<a class="btn btn-lg btn-primary me-3 mb-4" href="/docs/examples/"> - Еще примеры кода<i class="fas fa-arrow-alt-circle-right ms-2"></i> +<a class="btn btn-lg btn-primary me-3 mb-4" href="/playground/"> + More code examples<i class="fas fa-arrow-alt-circle-right ms-2"></i> </a> <a class="btn btn-lg btn-primary me-3 mb-4" href="/docs/syntax/"> - Описание синтаксиса<i class="fas fa-arrow-alt-circle-right ms-2"></i> + Syntax description<i class="fas fa-arrow-alt-circle-right ms-2"></i> </a> <a class="btn btn-lg btn-primary me-3 mb-4" href="/docs/"> - Вся документация<i class="fas fa-arrow-alt-circle-right ms-2"></i> + All documentation<i class="fas fa-arrow-alt-circle-right ms-2"></i> </a> <a class="btn btn-lg btn-secondary me-3 mb-4" href="/blog/"> Articles<i class="fas fa-arrow-alt-circle-right ms-2 "></i> diff --git a/docs/index.xml b/docs/index.xml index 4c6b043c..11e416e8 100644 --- a/docs/index.xml +++ b/docs/index.xml @@ -14,7 +14,7 @@ <item> - <title>Blog: Релиз языка программрования NewLang 0.4</title> + <title>Blog: Release of the programming language NewLang 0.4</title> <link>http://localhost:1313/blog/release-v0.4/</link> <pubDate>Tue, 06 Jun 2023 00:00:00 +0000</pubDate> @@ -22,111 +22,26 @@ <description> - &lt;p&gt;&lt;img alt=&#34;КДПВ&#34; src=&#34;http://localhost:1313/blog/langs.jpeg&#34;&gt;&lt;/p&gt; - - -&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; -&lt;p&gt;Внимание!!!&lt;/p&gt; -&lt;p&gt;&amp;ldquo;nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии.&lt;/p&gt; -&lt;p&gt;Актуальную версию синтаксиса языка можно посмотреть &lt;a href=&#34;http://localhost:1313/docs/&#34;&gt;тут&lt;/a&gt;.&lt;/p&gt; - -&lt;/div&gt; - -&lt;p&gt;ssssssssssssssssssssssssssssssssssssssssssssss&lt;/p&gt; - - </description> - </item> - - <item> - <title>Blog: Нюансы разработки парсера для своего языка программирования</title> - <link>http://localhost:1313/blog/parser-nuances/</link> - <pubDate>Wed, 29 Mar 2023 00:00:00 +0000</pubDate> - - <guid>http://localhost:1313/blog/parser-nuances/</guid> - <description> - - - &lt;p&gt;&lt;img alt=&#34;КДПВ&#34; src=&#34;http://localhost:1313/blog/langs.jpeg&#34;&gt;&lt;/p&gt; -&lt;p&gt;Недавно прочитал на Хабре статью &lt;a href=&#34;https://habr.com/post/723400/&#34;&gt;Свой язык, или как я устал от ассемблера и С&lt;/a&gt;, и невольно взглядом зацепился за один абзац:&lt;/p&gt; -&lt;blockquote&gt; -&lt;p&gt;Я решил не сильно париться, поэтому использовал библиотеку parglare. Она очень легкая и удобная, всем рекомендую. Для описания синтаксиса парсер принимает строку в соответствующем формате, использует регулярные выражения (не надо осуждать регулярки, они всесильны!).&lt;/p&gt; -&lt;/blockquote&gt; -&lt;p&gt;В результате решил опубликовать статью на основе своих старых записей еще с тех времен, когда идея &lt;a href=&#34;https://newlang.net/&#34;&gt;NewLang&lt;/a&gt; до конца еще не выкристаллизовалась, но уже хотелось писать реальный код и тестировать разные концепции.&lt;/p&gt; -&lt;p&gt;Ведь в жизни практически любого программиста может наступить момент, когда ему в голову приходит светлая идея - разработать свой собственный язык программирования. Может быть и не ради захвата мира, наравне с C/C++, Python или хотя бы PHP, а в качестве личного пет-проекта, с которым он, длинными зимними вечерами будет оттачивать собственное мастерство.&lt;/p&gt; -&lt;p&gt;А так как у любого языка (не только программирования), все начинается с анализа его грамматики, то самой первой задачей создателя будет выбор инструментов для синтаксического анализа исходного текста.&lt;/p&gt; -&lt;p&gt;Это история — заметки на память о муках выбора связки лексер-парсер для разбора грамматики NewLang. А так же попытка описать и систематизировать выводы об особенностях разных анализаторов с которыми пришлось поработать при выборе парсера для разбора грамматики у своего языка программирования.&lt;/p&gt; -&lt;h3 id=&#34;используемые-термины&#34;&gt;Используемые термины.&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d0%b5%d0%bc%d1%8b%d0%b5-%d1%82%d0%b5%d1%80%d0%bc%d0%b8%d0%bd%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Чтобы было понятно, о чем в дальнейшем пойдет речь.&lt;/p&gt; -&lt;blockquote&gt; -&lt;p&gt;Лексер — компьютерная программа или библиотека, в задачи которой входит разделить входной поток данных на отдельные, не связанные между собой отдельные фрагменты, которые принято называть токенами или лексемами.&lt;/p&gt; -&lt;p&gt;Парсер — на основе последовательности токенов выполняется синтаксический анализ, например строит абстрактное синтаксическое дерево (AST).&lt;/p&gt; -&lt;/blockquote&gt; -&lt;h2 id=&#34;заход--1---flex--bison&#34;&gt;Заход № 1 - Flex + Bison&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b7%d0%b0%d1%85%d0%be%d0%b4--1---flex--bison&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;&lt;a href=&#34;https://github.com/westes/flex&#34;&gt;GitHub - westes/flex: The Fast Lexical Analyzer - scanner generator for lexing in C and C++&lt;/a&gt; -&lt;a href=&#34;https://www.gnu.org/software/bison/&#34;&gt;Bison - GNU Project - Free Software Foundation&lt;/a&gt;&lt;/p&gt; -&lt;p&gt;После прочтения умных книжек я начал с классики Flex + Bison. Это старые и давно отработанные приложения с широчайшими возможностями по настройке с помощью которых можно описать синтаксис и получить исходные файлы лексера и парсера для языка практически с любой грамматикой.&lt;/p&gt; -&lt;p&gt;К сожалению, у этих старичков очень большой порог входа и тяжелая наследственность. Чего только стоит определение собственного класса лексера через &lt;code&gt;#define&lt;/code&gt;, а так же отсутствие нормальной поддержки С++. Вынужденные танцы с бубном для пасинга отдельной строки, когда не требуется анализировать файл целиком и прочие не всегда очевидные проблемы и разные не понятные условности.&lt;/p&gt; -&lt;p&gt;Другими словами, через несколько недель безуспешных мучений я решил посмотреть альтернативы, а так как начальный файл лексики после экспериментов с Flex + Bison кое-как уже был сделан, то следующая связка была Flex + lemon.&lt;/p&gt; -&lt;h2 id=&#34;заход--2---flex--lemon&#34;&gt;Заход № 2 - Flex + Lemon&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b7%d0%b0%d1%85%d0%be%d0%b4--2---flex--lemon&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;&lt;a href=&#34;https://www.sqlite.org/lemon.html&#34;&gt;The Lemon LALR(1) Parser Generator&lt;/a&gt;&lt;/p&gt; -&lt;p&gt;Тут все оказалось до примитивности просто и понятно. Реально очень быстрый старт с боевыми примерами, очень наглядный и понятный способ записи правил (по сравнению с Bison). Все хорошо кроме одного, хорошее быстро заканчивается, если приходится анализировать более одной строки.&lt;/p&gt; -&lt;p&gt;По сути, Lemon с Bison, это как Инь и Янь. Lemon простой и удобный для работы с одной строкой (для этого он и создавался), а Bison супер-пупер-мега комбайн для парсинга файлов любых размеров.&lt;/p&gt; -&lt;p&gt;Поэтому, поиски связки лексер + парсер продолжились и после прочтения очередной статьи, что парсеры языков можно делать на регулярках, решил посмотреть, что есть в этом направлении:&lt;/p&gt; -&lt;h2 id=&#34;заход--3-парсер-на-регулярках-re2c&#34;&gt;Заход № 3 парсер на регулярках re2c&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b7%d0%b0%d1%85%d0%be%d0%b4--3-%d0%bf%d0%b0%d1%80%d1%81%d0%b5%d1%80-%d0%bd%d0%b0-%d1%80%d0%b5%d0%b3%d1%83%d0%bb%d1%8f%d1%80%d0%ba%d0%b0%d1%85-re2c&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Из описания &lt;a href=&#34;https://re2c.org/&#34;&gt;re2c&lt;/a&gt;:&lt;/p&gt; -&lt;blockquote&gt; -&lt;p&gt;По сути, на этой штуке можно писать лексические анализаторы прямо на коленке за несколько минут.&lt;/p&gt; -&lt;/blockquote&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;/*!re2c -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt; re2c:define:YYPEEK = &amp;#34;*cursor&amp;#34;; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt; re2c:define:YYSKIP = &amp;#34;++cursor;&amp;#34;; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt; re2c:define:YYBACKUP = &amp;#34;marker = cursor;&amp;#34;; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt; re2c:define:YYRESTORE = &amp;#34;cursor = marker;&amp;#34;; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt; re2c:define:YYBACKUPCTX = &amp;#34;ctxmarker = cursor;&amp;#34;; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt; re2c:define:YYRESTORECTX = &amp;#34;cursor = ctxmarker;&amp;#34;; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt; re2c:define:YYRESTORETAG = &amp;#34;cursor = ${tag};&amp;#34;; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt; re2c:define:YYLESSTHAN = &amp;#34;limit - cursor &amp;lt; @@{len}&amp;#34;; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt; re2c:define:YYSTAGP = &amp;#34;@@{tag} = cursor;&amp;#34;; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt; re2c:define:YYSTAGN = &amp;#34;@@{tag} = NULL;&amp;#34;; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt; re2c:define:YYSHIFT = &amp;#34;cursor += @@{shift};&amp;#34;; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt; re2c:define:YYSHIFTSTAG = &amp;#34;@@{tag} += @@{shift};&amp;#34;; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt; */&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Показалось, что это самый удобный способ указания шаблонов для парсера! Достаточно описать в комментариях нужные шаблоны, напустить на исходный файл компилятор регулярок и все готово! Но нет, действительно, это только показалось.&lt;/p&gt; -&lt;p&gt;Ведь для простеньких парсеров или регулярных выражений &lt;strong&gt;re2c&lt;/strong&gt; может быть и действительно хорош, но отлаживать синтаксис большого языка на регулярках слишком хлопотное занятие.&lt;/p&gt; -&lt;p&gt;После этого решил с ним не заморачиваться и посмотреть альтернативы классическим лексерам и парсерам.&lt;/p&gt; -&lt;h2 id=&#34;заход--4---flex-flexcpp--bisoncpp&#34;&gt;Заход № 4 - flex (flexcpp) + bisoncpp&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b7%d0%b0%d1%85%d0%be%d0%b4--4---flex-flexcpp--bisoncpp&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Тогда как у традиционных flex + bison поддержка С++ реализована &lt;del&gt;через одно место&lt;/del&gt; на уровне - работает и не трогай, то решил посмотреть их альтернативную реализация &lt;a href=&#34;https://gitlab.com/fbb-git/flexcpp&#34;&gt;flexcpp&lt;/a&gt; + &lt;a href=&#34;https://gitlab.com/fbb-git/bisoncpp&#34;&gt;bisoncpp&lt;/a&gt; с нативной поддержкой С++.&lt;/p&gt; -&lt;p&gt;Первое впечатление было, то что доктор прописал!&lt;/p&gt; -&lt;p&gt;Синтаксис записи лексики хоть немного и отличается от классической, но это не принципиально. Зато есть нативная и логичная поддержка С++ без оберток и выкрутасов, и как дополнительный плюс - более удобный синтаксис указания правил в парсере. Но и тут не обошлось без шероховатостей.&lt;/p&gt; -&lt;p&gt;В шаблонах правил bisoncpp не поддерживает юникод (хотя сам лексер-парсер с ним справляется на ура), и совсем не понятная ситуация с поддержкой. Как я понял, разработчиком является вроде бы один человек, но пообщаться с ним насчет ошибок при обработке русских символов так и не получилось.*&lt;/p&gt; -&lt;p&gt;Потом еще одно непонятное поведение вылезло в другом месте. В результате решил отказаться от недружелюбной поддержки и посмотреть, какие есть еще варианты парсеров.&lt;/p&gt; -&lt;hr&gt; -&lt;p&gt;*) Через два года мой тикет был закрыт с комментарием, что поддерживаются только ascii символы.&lt;/p&gt; -&lt;h2 id=&#34;заход--5---неродной-парсер-antlr&#34;&gt;Заход № 5 - неродной парсер ANTLR&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b7%d0%b0%d1%85%d0%be%d0%b4--5---%d0%bd%d0%b5%d1%80%d0%be%d0%b4%d0%bd%d0%be%d0%b9-%d0%bf%d0%b0%d1%80%d1%81%d0%b5%d1%80-antlr&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;От использования &lt;a href=&#34;https://www.antlr.org/&#34;&gt;ANTLR&lt;/a&gt; (от англ. ANother Tool for Language Recognition — «ещё одно средство распознавания языков») — генератора нисходящих анализаторов для формальных языков, я решил сразу отказать из-за того, что он написан на Java,.&lt;/p&gt; -&lt;p&gt;В этом нет никаких религиозных предпочтений, так как я искал генератор парсеров, который можно было бы сделать встроенным прямо в среду выполнения, а в случае с ANTLR и JRE это было бы затруднительно.&lt;/p&gt; -&lt;p&gt;Таким образом я опять вернулся к старичкам Flex и Bison, с которых все и начиналось.&lt;/p&gt; -&lt;h2 id=&#34;заход--6-последний---возвращение-к-flex--bison&#34;&gt;Заход № 6, последний - возвращение к Flex + Bison&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b7%d0%b0%d1%85%d0%be%d0%b4--6-%d0%bf%d0%be%d1%81%d0%bb%d0%b5%d0%b4%d0%bd%d0%b8%d0%b9---%d0%b2%d0%be%d0%b7%d0%b2%d1%80%d0%b0%d1%89%d0%b5%d0%bd%d0%b8%d0%b5-%d0%ba-flex--bison&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Все описанные выше эксперименты заняли в общем итоге несколько месяцев, в результате которых были написаны килобайты исходного кода и тестовых примеров, прочитано десятки статей и как результат - возврат к изначальной связке Flex + Bison, но уже с солидным багажом опыта в применении различных вариантов лексеров-парсеров.&lt;/p&gt; -&lt;p&gt;Но самое главное, с пониманием того, что же в результате хочется получить, и очень большой базой тестовых примеров синтаксиса.&lt;/p&gt; -&lt;h2 id=&#34;выводы-на-память&#34;&gt;Выводы на память&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b2%d1%8b%d0%b2%d0%be%d0%b4%d1%8b-%d0%bd%d0%b0-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d1%8c&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;В итоге для себя решил следующее: если нужен простенький шаблонизатор, то идеальный вариант &lt;strong&gt;re2c&lt;/strong&gt; (если почему-то не подходит &lt;strong&gt;regexp&lt;/strong&gt;). Если требуется анализировать синтаксис сложнее обычных регулярок, но в одну строку, то идеальной будет связка flex+lemon, а если нужна серьезная артиллерия, то тут однозначно flex + bison.&lt;/p&gt; -&lt;p&gt;От связки flexcpp + bisoncpp отказался совсем. Что с поддержкой — не понятно, синтаксис от классики отличается не очень сильно (хотя тоже нужно ломать голову), а обход выявленных косяков не стоят того синтаксического сахара.&lt;/p&gt; -&lt;p&gt;И по итогам множества экспериментов с разными вариантами синтаксиса удалось сформулировать пару важных архитектурных моментов, которые могут очень сильно упростить жизнь создателям языком программирования:&lt;/p&gt; -&lt;h2 id=&#34;стратегия-обработки-ошибок-синтаксиса&#34;&gt;Стратегия обработки ошибок синтаксиса&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d1%82%d1%80%d0%b0%d1%82%d0%b5%d0%b3%d0%b8%d1%8f-%d0%be%d0%b1%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b8-%d0%be%d1%88%d0%b8%d0%b1%d0%be%d0%ba-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Обычно принято обрабатывать синтаксические ошибки непосредственно в парсере и для этого есть определенный резон — в этом случае нет необходимости в каких либо дальнейших действиях, нужна только полностью описанная корректная грамматика.&lt;/p&gt; -&lt;p&gt;Но если грамматика языка очень сложная (привет C++), и её описание становится сложной задачей, то можно отказался и от анализа ошибок синтаксиса непосредственно в парсере! То есть, лучше сделать максимально широкую лексику (даже с теми вариантами, которые являются для языка ошибочными), но ловить эти ошибки уже при анализе AST!&lt;/p&gt; -&lt;p&gt;В этом случае, поддерживать описание грамматики языка становится значительно проще (меньше синтаксических правил, проще их формальное описание и т.д.), а самое главное, при описании грамматики не нужно думать про lval или rval, где можно указывать ссылку, а где нет — т. е. можно указывать все и везде, а вот анализ допустимости использования конкретных терминов будет выполняться позднее при анализе AST.&lt;/p&gt; -&lt;p&gt;&lt;em&gt;Отказа от полного анализа грамматики языка на уровне лексера — парсера и перенос проверки корректности синтаксических конструкций на этап разбора синтаксического дерева позволяет в разы, если не на порядки сократить и значительно упростить описание грамматических правил!&lt;/em&gt;&lt;/p&gt; -&lt;p&gt;Подобное допущение очень полезно на начальном этапе создания языка (можно сосредоточиться на общей концепции, вместо постоянных правок в грамматике), а так же значительно упростить в будущем поддержку и/или расширение синтаксиса.&lt;/p&gt; -&lt;h2 id=&#34;макросы-и-модификация-грамматики-в-runtime&#34;&gt;Макросы и модификация грамматики в Runtime&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b8-%d0%bc%d0%be%d0%b4%d0%b8%d1%84%d0%b8%d0%ba%d0%b0%d1%86%d0%b8%d1%8f-%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b0%d1%82%d0%b8%d0%ba%d0%b8-%d0%b2-runtime&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Какими бы мощными не были flex+bison, но у этой связки есть одна архитектурная проблема. Логика flex и bison построена на конечных автоматах и изменить грамматику языка во время выполнения приложения невозможно, тем более Bison сам вызывает лексер для получения очередной порции данных и ему очень непросто подсунуть измененные данные прямо во время работы. А так хотелось сделать возможность раскрытия макросов и модификации синтаксиса за один проход анализатора!&lt;/p&gt; -&lt;p&gt;Для этого пришлось переделать логику работы flex+bison, чтобы парсер получал данные из лексера не напрямую из yylex, а через функцию — прокси. Эта промежуточная функция, складывает считанные лексемы во внутренний буфер. Данные в буфере анализируется на предмет наличия макросов и только после их раскрытия, лексемы отдаются в парсер из вершины буфера по одной за раз. Подробнее о макросах NewLang можно почитать &lt;a href=&#34;http://localhost:1313/blog/2023/03/01/%D0%B2%D0%B0%D1%80%D0%B8%D0%B0%D0%BD%D1%82-%D1%80%D0%B5%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8-dsl-domain-specific-language-%D1%81-%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E-%D0%BC%D0%B0%D0%BA%D1%80%D0%BE%D1%81%D0%BE%D0%B2/&#34;&gt;тут&lt;/a&gt;.&lt;/p&gt; -&lt;h2 id=&#34;самое-главное-при-разработке-грамматики&#34;&gt;Самое главное при разработке грамматики!&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b0%d0%bc%d0%be%d0%b5-%d0%b3%d0%bb%d0%b0%d0%b2%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%b8-%d1%80%d0%b0%d0%b7%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b5-%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b0%d1%82%d0%b8%d0%ba%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Но самый важный совет мне подсказал друг, который некогда участвовал в проекте по разработке парсера для языка программирования. И в правильности его совета - &lt;strong&gt;пиши тесты для грамматики&lt;/strong&gt; - я убеждался уже множество раз. Даже так, &lt;strong&gt;ПИШИ ТЕСТЫ ДЛЯ ГРАММАТИКИ&lt;/strong&gt;.&lt;/p&gt; -&lt;p&gt;Тесты для грамматики языка гораздо более важная вещь, чем любой из используемых инструментов. Только тесты позволяют убедиться в том, что новая фича в языке не сломала старые наработки. А если все же сломала, то в первую очередь нужно добавить новый тест, который бы фиксировал сломавшийся сценарий и только после этого можно будет со спокойной душой продолжать эксперименты с новыми грамматическими конструкциями.&lt;/p&gt; -&lt;p&gt;И удачи всем языкописателям!&lt;/p&gt; -&lt;p&gt;&lt;a href=&#34;https://habr.com/companies/timeweb/articles/724146/&#34;&gt;Ссылка на первую публикаци&lt;/a&gt;&lt;/p&gt; + &lt;h2 id=&#34;new-features-and-changes-in-the-syntax-of-newlang&#34;&gt;New features and changes in the syntax of NewLang&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#new-features-and-changes-in-the-syntax-of-newlang&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; +&lt;ul&gt; +&lt;li&gt;Reworked the definition of object types using &lt;a href=&#34;https://newlang.net/docs/syntax/naming/&#34;&gt;prefix naming (sigils)&lt;/a&gt;&lt;/li&gt; +&lt;li&gt;Interrupting the execution flow and returning can now be done for &lt;a href=&#34;https://newlang.net/docs/ops/throw/&#34;&gt;named code blocks&lt;/a&gt;.&lt;/li&gt; +&lt;li&gt;Simplified the syntax for importing &lt;a href=&#34;https://newlang.net/docs/types/native/&#34;&gt;native variables and functions (C/C++)&lt;/a&gt;&lt;/li&gt; +&lt;li&gt;Stabilized the syntax for &lt;a href=&#34;https://newlang.net/docs/ops/create/#comprehensions&#34;&gt;initializing tensor, dictionary, and function argument values&lt;/a&gt; with initial data.&lt;/li&gt; +&lt;li&gt;Added built-in macros for writing code using keywords in a &lt;a href=&#34;https://newlang.net/docs/syntax/dsl/&#34;&gt;DSL style&lt;/a&gt;&lt;/li&gt; +&lt;/ul&gt; +&lt;h2 id=&#34;new-compiler-features-nlc&#34;&gt;New compiler features (nlc)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#new-compiler-features-nlc&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; +&lt;ul&gt; +&lt;li&gt;Completely redesigned the macroprocessor.&lt;/li&gt; +&lt;li&gt;Reworked the compiler architecture with division into parser, macroprocessor, syntax analyzer, interpreter, and code generator.&lt;/li&gt; +&lt;/ul&gt; +&lt;h2 id=&#34;miscellaneous&#34;&gt;Miscellaneous&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#miscellaneous&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; +&lt;ul&gt; +&lt;li&gt;The documentation &lt;a href=&#34;http://newlang.net&#34;&gt;website&lt;/a&gt; has been translated to &lt;a href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt; and made bilingual.&lt;/li&gt; +&lt;li&gt;Instead of binary builds, a section &lt;a href=&#34;https://newlang.net/playground/&#34;&gt;Playground and example code&lt;/a&gt; has been added to the website for small experiments.&lt;/li&gt; +&lt;li&gt;Transition to clang-16 has been completed (transition to clang-17 and newer is planned after full implementation of coroutines and support for extended floating-point number formats).&lt;/li&gt; +&lt;li&gt;The number of project contributors has increased to more than one!&lt;/li&gt; +&lt;/ul&gt; </description> </item> @@ -140,9 +55,17 @@ <description> - &lt;p&gt;&lt;a href=&#34;https://habr.com/articles/720416/&#34;&gt;https://habr.com/articles/720416/&lt;/a&gt;&lt;/p&gt; -&lt;p&gt;&lt;img alt=&#34;image&#34; src=&#34;https://habrastorage.org/webt/r9/4d/tu/r94dtuimvtiiuntx5xpunndaetq.jpeg&#34;&gt; -&lt;a href=&#34;https://habr.com/company/timeweb/blog/719332/&#34;&gt;This is a translation of my own article&lt;/a&gt;&lt;/p&gt; + + +&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; +&lt;p&gt;Attention!!!&lt;/p&gt; +&lt;p&gt;This article contains a description of the NewLnag syntax of the previous version.&lt;/p&gt; +&lt;p&gt;Publication source &lt;a href=&#34;https://habr.com/articles/720416/&#34;&gt;https://habr.com/articles/720416/&lt;/a&gt;&lt;/p&gt; + +&lt;/div&gt; + +&lt;p&gt;&lt;img alt=&#34;image&#34; src=&#34;https://habrastorage.org/webt/r9/4d/tu/r94dtuimvtiiuntx5xpunndaetq.jpeg&#34;&gt;&lt;/p&gt; +&lt;p&gt;&lt;a href=&#34;https://habr.com/company/timeweb/blog/719332/&#34;&gt;This is a translation of my own article&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The release of &lt;strong&gt;&lt;a href=&#34;https://newlang.net/&#34;&gt;NewLang&lt;/a&gt;&lt;/strong&gt; language with a brand new &amp;ldquo;feature&amp;rdquo; is coming, a remodeled version of the preprocessor that allows you to extend the language syntax to create different DSL dialects using macros.&lt;/p&gt; &lt;h3 id=&#34;what-is-it-about&#34;&gt;What is it about?&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#what-is-it-about&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; &lt;blockquote&gt; @@ -291,2106 +214,5 @@ while( true ) { </description> </item> - <item> - <title>Blog: Релиз языка программрования NewLang 0.3</title> - <link>http://localhost:1313/blog/release-v0.3/</link> - <pubDate>Mon, 07 Nov 2022 00:00:00 +0000</pubDate> - - <guid>http://localhost:1313/blog/release-v0.3/</guid> - <description> - - - &lt;p&gt;&lt;img alt=&#34;КДПВ&#34; src=&#34;http://localhost:1313/blog/langs.jpeg&#34;&gt;&lt;/p&gt; - - -&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; -&lt;p&gt;Внимание!!!&lt;/p&gt; -&lt;p&gt;Данная статья содержит описание синтаксиса NewLnag предыдущей версии.&lt;/p&gt; -&lt;p&gt;Актуальную версию синтаксиса языка можно посмотреть &lt;a href=&#34;http://localhost:1313/docs/&#34;&gt;тут&lt;/a&gt;.&lt;/p&gt; - -&lt;/div&gt; - -&lt;p&gt;NewLang — это язык программирования высокого уровня общего назначения. Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан на строгой системе грамматических правил. За счет использования макросов, синтаксис языка легко расширяется до более привычного вида на основе ключевых слов.&lt;/p&gt; -&lt;p&gt;NewLang находится в процессе активного развития. Это третий публичный &lt;a href=&#34;https://github.com/rsashka/newlang/releases/tag/v0.3.0&#34;&gt;релиз&lt;/a&gt; в который добавлены новые существенные возможности по сравнению с предыдущей версией.&lt;/p&gt; -&lt;h2 id=&#34;зачем-нужен-newlang&#34;&gt;Зачем нужен &lt;em&gt;NewLang&lt;/em&gt;?&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b7%d0%b0%d1%87%d0%b5%d0%bc-%d0%bd%d1%83%d0%b6%d0%b5%d0%bd-newlang&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;У всех современных языков программирования происходит постоянное развитие (усложнение) синтаксиса по мере выхода новых версий. Это является своего рода платой за появление новых возможностей и воспринимается пользователями как естественное явление.&lt;/p&gt; -&lt;p&gt;Но одновременно является и серьезной проблемой, так как с выходом версий добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки и поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.&lt;/p&gt; -&lt;p&gt;У &lt;em&gt;NewLang&lt;/em&gt; сложность языковых конструкций ограничена естественным образом за счет разделения синтаксиса языка на две части - это упрощает его изучение и использование.&lt;/p&gt; -&lt;p&gt;&lt;em&gt;Основной синтаксис&lt;/em&gt; — для написания программ в объектно-ориентированном (императивном) и декларативном стилях, который основан не на зарезервированных ключевых словах, а на системе строгих &lt;a href=&#34;http://localhost:1313/docs/syntax/&#34;&gt;грамматических правил&lt;/a&gt;. Имеется возможность расширения основного синтаксиса за счет использования макросов. &lt;em&gt;Расширенный синтаксис&lt;/em&gt; — программные вставки на языке реализации (С/С++), когда основного синтаксиса становится недостаточно.&lt;/p&gt; -&lt;p&gt;Еще одно неудобство современных языков в том, что большинство из них были созданы до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек. Это же касается и вычислений с неограниченной точностью, которые так же требуют применения дополнительных библиотечных функций.&lt;/p&gt; -&lt;p&gt;У &lt;em&gt;NewLang&lt;/em&gt; тензорные вычисления и рациональные числа неограниченной точности доступны «из коробки». Они поддерживаются на уровне синтаксиса для записи литералов соответствующих типов, а простые арифметические типы данных являются скалярами (тензорами нулевой размерности). Реализация тензорных вычислений сделана на базе библиотеки &lt;a href=&#34;https://pytorch.org/&#34;&gt;libtorch&lt;/a&gt;, а рациональные числа с использованием &lt;a href=&#34;https://github.com/openssl/openssl/blob/master/crypto/bn/README.pod&#34;&gt;OpenSSL&lt;/a&gt;.&lt;/p&gt; -&lt;h2 id=&#34;новые-глобальные-фичи-и-изменения-в-синтаксисе&#34;&gt;Новые глобальные фичи и изменения в синтаксисе:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bd%d0%be%d0%b2%d1%8b%d0%b5-%d0%b3%d0%bb%d0%be%d0%b1%d0%b0%d0%bb%d1%8c%d0%bd%d1%8b%d0%b5-%d1%84%d0%b8%d1%87%d0%b8-%d0%b8-%d0%b8%d0%b7%d0%bc%d0%b5%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b2-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h3 id=&#34;простые-чистые-функции-удалены&#34;&gt;Простые чистые функции удалены&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%be%d1%81%d1%82%d1%8b%d0%b5-%d1%87%d0%b8%d1%81%d1%82%d1%8b%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d1%83%d0%b4%d0%b0%d0%bb%d0%b5%d0%bd%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Раньше я пытался использовать синтаксис предикатов из Пролога, в котором проверки условий записываются через запятую. Но эта идея оказалась провальной, а сами операторы просто ужасными (тестировал разные варианты, но каждый раз получал много отрицательных отзывов), поэтому сейчас решил полностью от них отказаться.&lt;/p&gt; -&lt;p&gt;Они получались не только сложными для восприятия, но и по факту не нужными, так как легко заменялись обычной функцией с комбинации обычных логических операций.&lt;/p&gt; -&lt;h3 id=&#34;зафиксирован-синтаксис-операторов-проверки-условияdocsopsif-и-цикловdocsopswhile&#34;&gt;Зафиксирован синтаксис операторов проверки &lt;a href=&#34;http://localhost:1313/docs/ops/if/&#34;&gt;условия&lt;/a&gt; и &lt;a href=&#34;http://localhost:1313/docs/ops/while/&#34;&gt;циклов&lt;/a&gt;.&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b7%d0%b0%d1%84%d0%b8%d0%ba%d1%81%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d0%be%d0%b2-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b8-%d1%83%d1%81%d0%bb%d0%be%d0%b2%d0%b8%d1%8fdocsopsif-%d0%b8-%d1%86%d0%b8%d0%ba%d0%bb%d0%be%d0%b2docsopswhile&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Изменен и упрощен синтаксис операторов проверки условия (импликации) и цикла, для которых оставлено только по одному варианту. Проверка условия записывается в виде оператора математического следования &lt;strong&gt;&amp;ndash;&amp;gt;&lt;/strong&gt;, а цикл с помощью оператора &lt;strong&gt;&amp;lt;-&amp;gt;&lt;/strong&gt;.&lt;/p&gt; -&lt;p&gt;Но для упрощения записи можно пользоваться макросами, тогда в этом случае операции проверки условий и циклы превращаются в классические&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;\if(...){ - ... -} \elif(...) { - ... -} \else { - ... -}; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;или&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; \while( ... ){ - ... -}; -&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;конструкция-else-у-операторов-цикла&#34;&gt;Конструкция else у операторов цикла&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%86%d0%b8%d1%8f-else-%d1%83-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d0%be%d0%b2-%d1%86%d0%b8%d0%ba%d0%bb%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Теперь оператор цикла &lt;strong&gt;while&lt;/strong&gt; поддерживает конструкцию &lt;a href=&#34;http://localhost:1313/docs/ops/while/&#34;&gt;&lt;strong&gt;else&lt;/strong&gt;&lt;/a&gt;, которая выполняется если условие входа в цикл не было выполнено. &lt;em&gt;Это поведение отличается от аналогичных конструкций в языке Python, у которого секция &lt;strong&gt;else&lt;/strong&gt; выполняется всегда, кроме прерывания цикла по break.&lt;/em&gt;&lt;/p&gt; -&lt;p&gt;Ветка &lt;strong&gt;else&lt;/strong&gt; у оператора цикла записывается так же как и ветка иначе в условном операторе, т. е.&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[ cond ] &amp;lt;-&amp;gt; { - ... -}, [_] --&amp;gt; { - ... -}; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Или тоже самое, но с использованием макросов:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;\while(cond) { - ... -} \else { - ... -}; -&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;пространства-имен&#34;&gt;Пространства имен&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%be%d1%81%d1%82%d1%80%d0%b0%d0%bd%d1%81%d1%82%d0%b2%d0%b0-%d0%b8%d0%bc%d0%b5%d0%bd&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;В синтаксис NewLang добавлены &lt;a href=&#34;http://localhost:1313/docs/syntax/namespace/&#34;&gt;пространства имен&lt;/a&gt;, в стиле очень похожим на С++. Имена разделяются двойным двоеточием, а для определение пространства имен, его нужно указать перед открывающейся фигурной скобкой.&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;ns { - name { - var := 0; # Имя переменной будет ns::name::var - ::var := 1; # Переменная из глобального пространства имен - } -} -&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;программные-модули&#34;&gt;Программные модули&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%bd%d1%8b%d0%b5-%d0%bc%d0%be%d0%b4%d1%83%d0%bb%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Реализована концепция программных модулей - которая повторяет концепцию иерархического расположения файлов в структуре каталогов файловой системы, как в языках Python и Java.&lt;/p&gt; -&lt;p&gt;Имя модуля начинается на префикс &lt;strong&gt;@&lt;/strong&gt;, а структура каталогов указывается через точку. Причем концепции программных модулей и пространства имен объединены, и полное имя переменой из предыдущего абзаца будет &lt;code&gt;@root.dir.module::ns::name::var&lt;/code&gt;, где &lt;strong&gt;root&lt;/strong&gt; и &lt;strong&gt;dir&lt;/strong&gt; это каталоги в файловой системе, а &lt;strong&gt;module&lt;/strong&gt; — имя файла.&lt;/p&gt; -&lt;h3 id=&#34;объектно-ориентированное-программирование&#34;&gt;Объектно ориентированное программирование&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%bd%d0%be-%d0%be%d1%80%d0%b8%d0%b5%d0%bd%d1%82%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Реализована часть концепции ООП и добавлена поддержка &lt;a href=&#34;http://localhost:1313/docs/types/class/&#34;&gt;определения классов&lt;/a&gt; и их наследование, которая сейчас выглядит следующим образом:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;:NewClass := :Class() { # Новый тип (класс) - field := 1; - method() := {}; -}; -obj := :NewClass(); # Экземпляр класса -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Неожиданно для самого себя понял, что имея полный набор вариантов проверок при создании объектов (&lt;strong&gt;::=&lt;/strong&gt; - создать новый объект, &lt;strong&gt;:=&lt;/strong&gt; - создать новый или присвоить значение существующему, &lt;strong&gt;=&lt;/strong&gt; - только присвоить значение, а если объект не существует будет ошибка), концепция переопределения наследуемых функций не требует вообще никаких ключевых слов:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;:NewClass2 := :NewClass() { # Новый класс на базе существующего - field ::= 2; # Будет ошибка, т. к. поле field уже есть в базовом классе - method() = {}; # Аналог override, т.к. method должен существовать в базовом классе -}; -&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;прерывания-возврат-и-обработка-ошибок&#34;&gt;Прерывания, возврат и обработка ошибок&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b5%d1%80%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%b2%d0%be%d0%b7%d0%b2%d1%80%d0%b0%d1%82-%d0%b8-%d0%be%d0%b1%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b0-%d0%be%d1%88%d0%b8%d0%b1%d0%be%d0%ba&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Изменена, а точнее полностью переделана идеология возвратов из функций и обработки ошибок. -Теперь она чем-то похожа на подход, примененный в Ruby. Любая последовательность команд заключенные в фигурные скобки (в том числе тело функции), рассматривается как блок кода у которого нет специального оператора аналога &lt;strong&gt;return&lt;/strong&gt;, который возвращает какое либо значение. -Просто любой блок кода всегда возвращает последнее вычисленное значение (это чем то похоже на оператор «запятая» в языках C/C++).&lt;/p&gt; -&lt;p&gt;Для того, чтобы прервать выполнение кода используются две разные команды - прерывания, которые условно можно назвать &lt;em&gt;положительным&lt;/em&gt; и &lt;em&gt;отрицательным&lt;/em&gt; результатом. Что примерно соответствует семантике их записи. -&amp;ldquo;Отрицательное&amp;rdquo; прерывание записывается в виде двух минусов, а &amp;ldquo;положительное&amp;rdquo; прерывание в виде двух плюсов, т.е. &lt;strong&gt;--&lt;/strong&gt; или &lt;strong&gt;++&lt;/strong&gt;.&lt;/p&gt; -&lt;p&gt;По умолчанию данные операции возвращают пустое значение. Чтобы прерывание вернуло результат, возвращаемые данные нужно записывать между парой соответствующих символов, -т.е. &lt;strong&gt;--&lt;/strong&gt; 100 &lt;strong&gt;--&lt;/strong&gt;, что является близким аналогом оператора &lt;code&gt;return 100;&lt;/code&gt; в других языках программирования, а &lt;strong&gt;++&lt;/strong&gt;«Строка»&lt;strong&gt;++&lt;/strong&gt; - аналогом &lt;code&gt;return «Строка»;&lt;/code&gt;.&lt;/p&gt; -&lt;p&gt;Хотя более точным аналогом этих операторов будет все таки не &lt;strong&gt;return&lt;/strong&gt;, а &lt;strong&gt;throw&lt;/strong&gt;, -т.к. эти команды не только прерывают выполнение последовательности команд в блоке, но их еще можно «ловить». -Для этого используется блок кода с соответствующей семантикой, &lt;strong&gt;{+&lt;/strong&gt; … &lt;strong&gt;+}&lt;/strong&gt; - блок кода, -который перехватывает положительные прерывания и &lt;strong&gt;{-&lt;/strong&gt; … &lt;strong&gt;-}&lt;/strong&gt; - блок кода, который перехватывает прерывания, созданные операторами &lt;strong&gt;&amp;ndash;&lt;/strong&gt;.&lt;/p&gt; -&lt;p&gt;Подобная концепция (в явном виде не разделять возвраты из функций и обработку исключений), -хоть и выглядит немного необычной, но позволяет реализовывать несколько очень полезных финтов, -которые сложно реализуемые в обычных языках программирования.&lt;/p&gt; -&lt;p&gt;Например, возврат из нескольких вложенных функций без необходимости обрабатывать результат возврата каждой из них. -В этом примере функция &lt;em&gt;Test&lt;/em&gt; перехватывает &amp;ldquo;положительные&amp;rdquo; прерывания из вложенных функций:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; Test0(arg) := { \if($arg==0) \return(&amp;#34;DONE - 0&amp;#34;); «FAIL» }; - Test1(arg) := { \if($arg==1) \return(&amp;#34;DONE - 1&amp;#34;); Test0($arg); }; - Test(arg) := {+ \if($arg &amp;gt;= 0) Test1($arg); $arg; +}; - - Test(0); # Вернет «DONE — 0» возврат из вложенной функции Test0 - Test(1); # Вернет «DONE — 1» возврат из вложенной функции Test1 - Test(2); # Вернет «FAIL» возврат из вложенной функции Test0 - Test(-2); # Вернет -2 — возврат из функции Test -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Есть еще блок &lt;code&gt;{* … *}&lt;/code&gt;, который перехватывает оба типа прерываний. Такой блок кода поддерживает типизацию возвращаемого значения, что позволяет в явном виде указывать типы данных, которые нужно перехватывать. -Например, &lt;code&gt;{* ... *} :Type1&lt;/code&gt; — будет перехвачено прерывание вида &lt;code&gt;++ :Type1 ++&lt;/code&gt; или &lt;code&gt;--:Type1--&lt;/code&gt;, что позволяет очень гибко формировать логику работы программы.&lt;/p&gt; -&lt;p&gt;Блоки кода с перехватом исключений также поддерживают оператор иначе (&lt;em&gt;\else&lt;/em&gt;) который, по аналогии с оператором &lt;em&gt;\else&lt;/em&gt; в циклах, выполняется только тогда, если прерывания не произошло.&lt;/p&gt; -&lt;p&gt;Можно указать сразу несколько типов, которые нужно перехватывать:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; {* - .... - *} &amp;lt;:Type1, :Type2, :Type3&amp;gt;; -&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;бинарная-сборка-под-windws&#34;&gt;Бинарная сборка под Windws:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%b0%d1%8f-%d1%81%d0%b1%d0%be%d1%80%d0%ba%d0%b0-%d0%bf%d0%be%d0%b4-windws&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;В текущем релизе версия clang повышена 15, а вызовы нативных функций опять реализованы с помощью libffi, что в итоге позволило собрать бинарную сборку не только под Linux, но и под Windows. И теперь чтобы поиграться с REPL read-eval-print loop можно скачать уже готовый бинарник.&lt;/p&gt; -&lt;h2 id=&#34;подробная-информация-о-языке&#34;&gt;Подробная информация о языке:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d0%be%d0%b4%d1%80%d0%be%d0%b1%d0%bd%d0%b0%d1%8f-%d0%b8%d0%bd%d1%84%d0%be%d1%80%d0%bc%d0%b0%d1%86%d0%b8%d1%8f-%d0%be-%d1%8f%d0%b7%d1%8b%d0%ba%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;ul&gt; -&lt;li&gt;&lt;a href=&#34;http://localhost:1313/docs/syntax/&#34;&gt;Синтаксис &lt;em&gt;NewLang&lt;/em&gt;&lt;/a&gt;&lt;/li&gt; -&lt;li&gt;&lt;a href=&#34;http://localhost:1313/docs/types/&#34;&gt;Подробное описание типов данных&lt;/a&gt;&lt;/li&gt; -&lt;li&gt;&lt;a href=&#34;http://localhost:1313/docs/ops/&#34;&gt;Операторы и управляющие конструкции&lt;/a&gt;&lt;/li&gt; -&lt;li&gt;&lt;a href=&#34;http://localhost:1313/docs/_print/&#34;&gt;Вся документация по &lt;em&gt;NewLang&lt;/em&gt; на одной странице&lt;/a&gt;&lt;/li&gt; -&lt;/ul&gt; -&lt;h2 id=&#34;обратная-связь&#34;&gt;Обратная связь&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%b1%d1%80%d0%b0%d1%82%d0%bd%d0%b0%d1%8f-%d1%81%d0%b2%d1%8f%d0%b7%d1%8c&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Если у вас появятся предложения по развитию нового или улучшению уже существующего функционала &lt;em&gt;NewLang&lt;/em&gt;, &lt;a href=&#34;https://github.com/rsashka/newlang/discussions&#34;&gt;пишите&lt;/a&gt;.&lt;/p&gt; -&lt;h2 id=&#34;примеры-кода&#34;&gt;Примеры кода&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80%d1%8b-%d0%ba%d0%be%d0%b4%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#!../output/nlc --eval -# Определение функции hello -hello(str) := { - # Импорт стандартной C функции - printf := :Pointer(&amp;#39;printf(format:FmtChar, ...):Int32&amp;#39;); - # Вызов C функции с проверкой типов аргументов по строке формата - printf(&amp;#39;%s&amp;#39;, $str); - # Возврат значения из функции hello - $str; -}; - -hello(&amp;#39;Привет, мир!&amp;#39;); # Вызвать функцию&amp;lt;/code&amp;gt; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Вывод (первая строка выводится с помощью printf, а вторая — возвращаемое значение функции hello):&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; Привет, мир! - Привет, мир! -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Пример скрипта для вычисления факториала 1000&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#!../output/nlc --eval - -fact := 1\1; # Рациональное число без ограничения точности -mult := 1000..1..-1?; # Сделать из диапазона итератор для множителей от 1000 до 2 -[mult ?!] &amp;lt;-&amp;gt; { # Цикл, пока не закончатся данные итератора - # Получить текущий множитель и перейти на следующий элемент итератора - fact *= mult !; -}; -fact # Вывести итоговый результат -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Вывод:&lt;/p&gt; -&lt;spoiler title=&#34;Много цифр&#34;&gt; -402387260077093773543702433923003985719374864210714632543799910429938512398629 -020592044208486969404800479988610197196058631666872994808558901323829669944590 -997424504087073759918823627727188732519779505950995276120874975462497043601418 -278094646496291056393887437886487337119181045825783647849977012476632889835955 -735432513185323958463075557409114262417474349347553428646576611667797396668820 -291207379143853719588249808126867838374559731746136085379534524221586593201928 -090878297308431392844403281231558611036976801357304216168747609675871348312025 -478589320767169132448426236131412508780208000261683151027341827977704784635868 -170164365024153691398281264810213092761244896359928705114964975419909342221566 -832572080821333186116811553615836546984046708975602900950537616475847728421889 -679646244945160765353408198901385442487984959953319101723355556602139450399736 -280750137837615307127761926849034352625200015888535147331611702103968175921510 -907788019393178114194545257223865541461062892187960223838971476088506276862967 -146674697562911234082439208160153780889893964518263243671616762179168909779911 -903754031274622289988005195444414282012187361745992642956581746628302955570299 -024324153181617210465832036786906117260158783520751516284225540265170483304226 -143974286933061690897968482590125458327168226458066526769958652682272807075781 -391858178889652208164348344825993266043367660176999612831860788386150279465955 -131156552036093988180612138558600301435694527224206344631797460594682573103790 -084024432438465657245014402821885252470935190620929023136493273497565513958720 -559654228749774011413346962715422845862377387538230483865688976461927383814900 -140767310446640259899490222221765904339901886018566526485061799702356193897017 -860040811889729918311021171229845901641921068884387121855646124960798722908519 -296819372388642614839657382291123125024186649353143970137428531926649875337218 -940694281434118520158014123344828015051399694290153483077644569099073152433278 -288269864602789864321139083506217095002597389863554277196742822248757586765752 -344220207573630569498825087968928162753848863396909959826280956121450994871701 -244516461260379029309120889086942028510640182154399457156805941872748998094254 -742173582401063677404595741785160829230135358081840096996372524230560855903700 -624271243416909004153690105933983835777939410970027753472000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000\1 -&lt;/spoiler&gt; -&lt;h2 id=&#34;как-посмотреть&#34;&gt;Как посмотреть?&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%ba%d0%b0%d0%ba-%d0%bf%d0%be%d1%81%d0%bc%d0%be%d1%82%d1%80%d0%b5%d1%82%d1%8c&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;ul&gt; -&lt;li&gt;&lt;a href=&#34;https://github.com/rsashka/newlang/releases/download/v0.3.0/nlc_win_64.zip&#34;&gt;Бинарная сборка и тесты под Windows&lt;/a&gt;&lt;/li&gt; -&lt;li&gt;&lt;a href=&#34;https://github.com/rsashka/newlang/releases/download/v0.3.0/nlc_lin_64.tar.xz&#34;&gt;Бинарная сборка и тесты под Ubuntu&lt;/a&gt;&lt;/li&gt; -&lt;li&gt;Для запуска бинарных сборок потребуются разделяемые библиотеки libLLVM-15 и libtorch (&lt;a href=&#34;https://github.com/rsashka/newlang/releases/download/v0.3.0/nlc_dll.zip&#34;&gt;архив с библиотеками для Windows&lt;/a&gt;), (&lt;a href=&#34;https://github.com/rsashka/newlang/releases/download/v0.3.0/nlc_so.tar.xz&#34;&gt;архив с библиотеками для Ubuntu&lt;/a&gt;).&lt;/li&gt; -&lt;li&gt;Так же все можно собрать напрямую из исходников по инструкции в &lt;a href=&#34;https://github.com/rsashka/newlang&#34;&gt;репозитории&lt;/a&gt;&lt;/li&gt; -&lt;/ul&gt; - - </description> - </item> - - <item> - <title>Blog: Релиз языка программрования NewLang 0.2</title> - <link>http://localhost:1313/blog/release-v0.2/</link> - <pubDate>Fri, 12 Aug 2022 00:00:00 +0000</pubDate> - - <guid>http://localhost:1313/blog/release-v0.2/</guid> - <description> - - - &lt;p&gt;&lt;img alt=&#34;КДПВ&#34; src=&#34;http://localhost:1313/blog/langs.jpeg&#34;&gt;&lt;/p&gt; - - -&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; -&lt;p&gt;Внимание!!!&lt;/p&gt; -&lt;p&gt;Данная статья содержит описание синтаксиса NewLnag предыдущей версии.&lt;/p&gt; -&lt;p&gt;Актуальную версию синтаксиса языка можно посмотреть &lt;a href=&#34;http://localhost:1313/docs/&#34;&gt;тут&lt;/a&gt;.&lt;/p&gt; - -&lt;/div&gt; - -&lt;p&gt;&lt;em&gt;NewLang&lt;/em&gt; - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения.&lt;/p&gt; -&lt;p&gt;Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка).&lt;/p&gt; -&lt;p&gt;&lt;em&gt;NewLang&lt;/em&gt; находится в процессе активного развития и это второй публичный релиз в котором добавлены существенные новые возможности и произошли некоторые изменения по сравнению с &lt;a href=&#34;https://habr.com/company/timeweb/blog/673176/&#34;&gt;предыдущей версией&lt;/a&gt;.&lt;/p&gt; -&lt;h2 id=&#34;особенности-языка&#34;&gt;Особенности языка:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d1%81%d0%be%d0%b1%d0%b5%d0%bd%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d1%8f%d0%b7%d1%8b%d0%ba%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;ul&gt; -&lt;li&gt;Возможность работы как в режиме интерпретатора, так и компилятора*.&lt;/li&gt; -&lt;li&gt;Динамическая и статическая типизация с возможностью указания типов в явном виде.&lt;/li&gt; -&lt;li&gt;Статическая типизация является условно строгой (автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных, например, целое число может быть автоматически преобразовано в вещественное или рациональное, но не наоборот).&lt;/li&gt; -&lt;li&gt;Автоматическое управление памятью.&lt;/li&gt; -&lt;li&gt;ООП в виде явного наследования классов и «утиная» типизация.&lt;/li&gt; -&lt;li&gt;На уровне синтаксиса поддержка нескольких типов функций (обычные и чистые функции без побочных эффектов).&lt;/li&gt; -&lt;li&gt;Необязательные и именованные параметры функций.&lt;/li&gt; -&lt;li&gt;Возможны вставки кода на языке реализации (С/С++)*.&lt;/li&gt; -&lt;li&gt;Простая интеграция с уже существующими программными библиотеками (в том числе импорт нативных переменных и функций из С/С++).&lt;/li&gt; -&lt;li&gt;Имеется REPL read-eval-print loop — «цикл: чтение — вычисление — вывод».&lt;/li&gt; -&lt;/ul&gt; -&lt;h2 id=&#34;новые-глобальные-фичи&#34;&gt;Новые глобальные фичи:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bd%d0%be%d0%b2%d1%8b%d0%b5-%d0%b3%d0%bb%d0%be%d0%b1%d0%b0%d0%bb%d1%8c%d0%bd%d1%8b%d0%b5-%d1%84%d0%b8%d1%87%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;ul&gt; -&lt;li&gt;Добавлены макросы. Теперь можно делать собственные языковые диалекты и использовать более привычную запись алгоритмических конструкций с использование ключевых слов. -Например, цикл&lt;/li&gt; -&lt;/ul&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[ cond ] &amp;lt;-&amp;gt; { - тело цикла -}; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;можно записать в более привычный нотации&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;\while (cond) { - тело цикла -}; -&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt; -&lt;li&gt;Добавлены итераторы для перебора элементов словарей или для запросов к другим контейнерам (например, к базам данных). На уровне базового синтаксиса поддерживается фильтрация данный, включая функциональный аналог LINQ за счет применения функций обратного вызова в качестве условия фильтра.&lt;/li&gt; -&lt;li&gt;Добавлен новый тип данных — рациональные числа с неограниченной точностью. Они записываются в виде обыкновенной дроби, у которой разделитель бекслеш, например единицу можно записать &lt;code&gt;1\1&lt;/code&gt;, а число 0.5 как &lt;code&gt;1\2&lt;/code&gt;.&lt;/li&gt; -&lt;li&gt;Реализован оператор распаковки словаря &lt;strong&gt;…&lt;/strong&gt; (многоточие), который можно использовать чтобы передать несколько аргументов при вызове функции или для присвоения значения сразу нескольким переменным.&lt;/li&gt; -&lt;li&gt;Теперь оператор присвоения поддерживает установку значений сразу нескольким переменным. С правой стороны от оператора присвоения может находится одно или несколько значений или оператор распаковки словаря. Причем словарь может быть указан и с левой стороны от оператора присвоения и таким образом можно записать самый простой способ перебора всех его элементов, когда в цикле первый элемент словаря сохраняется в переменную &lt;em&gt;item&lt;/em&gt;, а из самого словаря удаляется:&lt;/li&gt; -&lt;/ul&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[ dict ] &amp;lt;-&amp;gt; { - item, dict := ... dict; -}; -&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;изменения-в-синтаксисе&#34;&gt;Изменения в синтаксисе:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b8%d0%b7%d0%bc%d0%b5%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b2-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;ul&gt; -&lt;li&gt;Изменена запись циклов. Вместо двух разных типов с предусловием и постусловие, теперь используется единая форма записи, а тип цикла определяется взаимным расположением условия и его тела.&lt;/li&gt; -&lt;li&gt;Изменены названия арифметических и некоторых других типов данных на более логичные. В именах арифметических типов теперь указан их размер (Int8, Int16 … Float32, Float64 и т.д.).&lt;/li&gt; -&lt;li&gt;Многострочные комментарии стали вложенными&lt;/li&gt; -&lt;/ul&gt; -&lt;h2 id=&#34;подробная-информация-о-языке&#34;&gt;Подробная информация о языке:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d0%be%d0%b4%d1%80%d0%be%d0%b1%d0%bd%d0%b0%d1%8f-%d0%b8%d0%bd%d1%84%d0%be%d1%80%d0%bc%d0%b0%d1%86%d0%b8%d1%8f-%d0%be-%d1%8f%d0%b7%d1%8b%d0%ba%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;ul&gt; -&lt;li&gt;&lt;a href=&#34;http://localhost:1313/docs/syntax/&#34;&gt;Основные правила синтаксиса:&lt;/a&gt;&lt;/li&gt; -&lt;li&gt;&lt;a href=&#34;http://localhost:1313/docs/types/&#34;&gt;Встроенные типы данных:&lt;/a&gt;&lt;/li&gt; -&lt;li&gt;&lt;a href=&#34;http://localhost:1313/docs/ops/&#34;&gt;Операторы и управляющие конструкции:&lt;/a&gt;&lt;/li&gt; -&lt;/ul&gt; -&lt;h2 id=&#34;примеры-кода&#34;&gt;Примеры кода&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80%d1%8b-%d0%ba%d0%be%d0%b4%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;spoiler title=&#34;Привет, мир!&#34;&gt; -``` -#!../output/nlc --eval -&lt;h1 id=&#34;определение-функции-hello&#34;&gt;Определение функции hello&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-hello&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;hello(str) := {&lt;/p&gt; -&lt;pre&gt;&lt;code&gt;# Импорт стандартной C функции -printf := :Pointer(&#39;printf(format:FmtChar, ...):Int32&#39;); - -# Вызов C функции с проверкой типов аргументов по строке формата -printf(&#39;%s&#39;, $str); - -# Возврат значения из функции hello - $str; -&lt;/code&gt;&lt;/pre&gt; -&lt;p&gt;};&lt;/p&gt; -&lt;p&gt;hello(&amp;lsquo;Привет, мир!&amp;rsquo;); # Вызвать функцию&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Вывод (первая строка выводится с помощью printf, а вторая - возвращаемое значение функции hello): -&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;Привет, мир! -Привет, мир! -&lt;/code&gt;&lt;/pre&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-&lt;/spoiler&gt;&#34; data-lang=&#34;&lt;/spoiler&gt;&#34;&gt; -&amp;lt;spoiler title=&amp;#34;Пример скрипта для вычисления факториала 1000&amp;#34;&amp;gt; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;#!../output/nlc &amp;ndash;eval&lt;/p&gt; -&lt;p&gt;@fact := 1\1; # Рациональное число без ограничения точности -@mult := 1000..1..-1?; # Сделать из диапазона итератор для множителей от 1000 до 2 -[mult ?!] &amp;lt;-&amp;gt; { # Цикл, пока не закончатся данные итератора -# Получить текущий множитель и перейти на следующий элемент итератора -fact *= mult !; -}; -fact # Вывести итоговый результат&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Вывод: -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;402387260077093773543702433923003985719374864210714632543799910429938512398629 -020592044208486969404800479988610197196058631666872994808558901323829669944590 -997424504087073759918823627727188732519779505950995276120874975462497043601418 -278094646496291056393887437886487337119181045825783647849977012476632889835955 -735432513185323958463075557409114262417474349347553428646576611667797396668820 -291207379143853719588249808126867838374559731746136085379534524221586593201928 -090878297308431392844403281231558611036976801357304216168747609675871348312025 -478589320767169132448426236131412508780208000261683151027341827977704784635868 -170164365024153691398281264810213092761244896359928705114964975419909342221566 -832572080821333186116811553615836546984046708975602900950537616475847728421889 -679646244945160765353408198901385442487984959953319101723355556602139450399736 -280750137837615307127761926849034352625200015888535147331611702103968175921510 -907788019393178114194545257223865541461062892187960223838971476088506276862967 -146674697562911234082439208160153780889893964518263243671616762179168909779911 -903754031274622289988005195444414282012187361745992642956581746628302955570299 -024324153181617210465832036786906117260158783520751516284225540265170483304226 -143974286933061690897968482590125458327168226458066526769958652682272807075781 -391858178889652208164348344825993266043367660176999612831860788386150279465955 -131156552036093988180612138558600301435694527224206344631797460594682573103790 -084024432438465657245014402821885252470935190620929023136493273497565513958720 -559654228749774011413346962715422845862377387538230483865688976461927383814900 -140767310446640259899490222221765904339901886018566526485061799702356193897017 -860040811889729918311021171229845901641921068884387121855646124960798722908519 -296819372388642614839657382291123125024186649353143970137428531926649875337218 -940694281434118520158014123344828015051399694290153483077644569099073152433278 -288269864602789864321139083506217095002597389863554277196742822248757586765752 -344220207573630569498825087968928162753848863396909959826280956121450994871701 -244516461260379029309120889086942028510640182154399457156805941872748998094254 -742173582401063677404595741785160829230135358081840096996372524230560855903700 -624271243416909004153690105933983835777939410970027753472000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000\1&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-&lt;/spoiler&gt;&#34; data-lang=&#34;&lt;/spoiler&gt;&#34;&gt; -## Как посмотреть? -- [Загрузить собранный REPL и тесты (пока только под Ubuntu)](https://github.com/rsashka/newlang/releases/download/v0.2.0/nlc_bin.tar.xz) -- Для запуска бинарных файлов потребуются разделяемые библиотеки libLLVM-13 и libtorch: [архив только с нужными библиотеками](https://github.com/rsashka/newlang/releases/download/v0.2.0/nlc_so.tar.xz). -- Так же все можно собрать напрямую из исходников по инструкции в [репозитории](https://github.com/rsashka/newlang) -&lt;/code&gt;&lt;/pre&gt; - </description> - </item> - - <item> - <title>Blog: Релиз языка программрования NewLang</title> - <link>http://localhost:1313/blog/release-v0.1/</link> - <pubDate>Fri, 24 Jun 2022 00:00:00 +0000</pubDate> - - <guid>http://localhost:1313/blog/release-v0.1/</guid> - <description> - - - &lt;p&gt;&lt;img alt=&#34;КДПВ&#34; src=&#34;http://localhost:1313/blog/langs.jpeg&#34;&gt;&lt;/p&gt; - - -&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; -&lt;p&gt;Внимание!!!&lt;/p&gt; -&lt;p&gt;Данная статья содержит описание синтаксиса NewLnag предыдущей версии.&lt;/p&gt; -&lt;p&gt;Актуальную версию синтаксиса языка можно посмотреть &lt;a href=&#34;http://localhost:1313/docs/&#34;&gt;тут&lt;/a&gt;.&lt;/p&gt; - -&lt;/div&gt; - -&lt;p&gt;&lt;strong&gt;NewLang&lt;/strong&gt; - это язык программирования высокого уровня, в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения.&lt;/p&gt; -&lt;p&gt;Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка).&lt;/p&gt; -&lt;p&gt;Новое по сравнению с &lt;a href=&#34;https://habr.com/company/timeweb/blog/651999/&#34;&gt;прошлым выпуском&lt;/a&gt;:&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Реализованы все основные алгоритмические конструкции: проверка условий, различные варианты циклов, сравнение по образцу, прерывание последовательности команд и возврат данных, обработка ошибок и т.д.&lt;/li&gt; -&lt;li&gt;Переработан основной синтаксис для отдельных языковых конструкций.&lt;/li&gt; -&lt;li&gt;Реализованы большинство операций с переменными, включая операторы раскрытие списков и тензоров.&lt;/li&gt; -&lt;li&gt;Серьезно переработана система встроенных типов, реализованы функции для их преобразования и для определения данных (последнее можно назвать data comprehensions).&lt;/li&gt; -&lt;li&gt;Добавлены новые тесты и пр.&lt;/li&gt; -&lt;/ul&gt; -&lt;cut /&gt; -&lt;h1 id=&#34;зачем-нужен-newlang&#34;&gt;Зачем нужен &lt;em&gt;NewLang&lt;/em&gt;?&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b7%d0%b0%d1%87%d0%b5%d0%bc-%d0%bd%d1%83%d0%b6%d0%b5%d0%bd-newlang&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;У всех современных языков программирования происходит постоянное развитие (читай усложнение) синтаксиса по мере выхода новых версий. Это является своего рода, платой за появление новых возможностей и воспринимается пользователями как естественное явление.&lt;/p&gt; -&lt;p&gt;Но одновременно является и серьезной проблемой, т.к. с выходом новых версий добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки и трудоемкости поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.&lt;/p&gt; -&lt;p&gt;У &lt;em&gt;NewLang&lt;/em&gt; сложность языковых конструкций естественно ограничена за счет разделения синтаксиса языка на две части, что упрощает его изучение и использование.&lt;/p&gt; -&lt;p&gt;&lt;em&gt;Основной синтаксис&lt;/em&gt; — для написания программ в объектно-ориентированном (императивном) и декларативном стилях, который основан не на зарезервированных ключевых словах, а на строгих грамматических правилах и &lt;em&gt;Расширенный синтаксис&lt;/em&gt; — когда основного синтаксиса становится недостаточно, или требуется использовать языковую конструкцию языка реализации.&lt;/p&gt; -&lt;p&gt;Еще одно неудобство современных мейнстримовых языков, большинство из них были созданы до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек, а не встроены в основной синтаксис языка и систему базовых типов.&lt;/p&gt; -&lt;p&gt;У &lt;em&gt;NewLang&lt;/em&gt; тензорные вычисления доступны «из коробки» (используется библиотека &lt;a href=&#34;https://pytorch.org/&#34;&gt;libtorch&lt;/a&gt;), а обычные числа являются скалярами (тензорами нулевой размерности).&lt;/p&gt; -&lt;h1 id=&#34;синтаксис-newlang&#34;&gt;Синтаксис NewLang&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81-newlang&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;При разработке синтаксиса я старался придерживаться уже сложившихся в IT индустрии правил, чтобы не генерировать множественных смыслов, которые будут зависеть от контекста.&lt;/p&gt; -&lt;p&gt;&lt;strong&gt;Основы&lt;/strong&gt;&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Операторы разделяются точкой с запятой «;».&lt;/li&gt; -&lt;li&gt;Отступы и переводы строк игнорируются (очень хотелось иметь возможность автоматического форматирование кода).&lt;/li&gt; -&lt;li&gt;Многострочные комментарии в исходном коде соответствуют стилю С/С++ и должны располагаться между символами /* и */. Вложенность многострочных комментариев не поддерживается.&lt;/li&gt; -&lt;li&gt;Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash.&lt;/li&gt; -&lt;li&gt;Последовательность команд, которая должна выполняться как единое целое, заключается в фигурные скобки «{}».&lt;/li&gt; -&lt;li&gt;Программные вставки расширенного синтаксиса на языке реализации заключается в фигурные скобки со знаком процента %{ /* тут может быть любой код на C/C++*/ %}, как в лексерах lex и flex.&lt;/li&gt; -&lt;/ul&gt; -&lt;h1 id=&#34;создания-объектов-и-присвоения-новых-значений&#34;&gt;Создания объектов и присвоения новых значений&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%be%d0%b7%d0%b4%d0%b0%d0%bd%d0%b8%d1%8f-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%be%d0%b2-%d0%b8-%d0%bf%d1%80%d0%b8%d1%81%d0%b2%d0%be%d0%b5%d0%bd%d0%b8%d1%8f-%d0%bd%d0%be%d0%b2%d1%8b%d1%85-%d0%b7%d0%bd%d0%b0%d1%87%d0%b5%d0%bd%d0%b8%d0%b9&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;Для создания объектов и присвоения им новых значений в NewLang используется сразу три разных оператора:&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;&lt;strong&gt;::=&lt;/strong&gt; используется только для создания новых объектов, а если объект с таким именем уже существует, то генерируется ошибка.&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;:=&lt;/strong&gt; используется для тех же целей, но если объект с таким именем уже существует, то ошибки не происходит, а новое значение присваивается уже существующему объекту.&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;=&lt;/strong&gt; применяется только для присвоения значения уже существующим объектам, и если объект с указанным именем отсутствует, то тоже происходит ошибка выполнения.&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;Использование трех разных операторов для создания/изменения объектов позволяет более гибко контролировать подобные операции и выявлять логические ошибки в коде на более раннем этапе.&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;var ::= 1.0; # Создать новую переменную var без указания типа -var = 100; # Присвоить новое значение уже существующей переменной -printf := @import(&amp;#39;printf(format:Format, ...):Int&amp;#39;); /* Создать новый или переопределить объект printf, который будет результатом выполнения глобальной функции @import */ -&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;идентификаторы-объектов-и-модификаторы&#34;&gt;Идентификаторы объектов и модификаторы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b8%d0%b4%d0%b5%d0%bd%d1%82%d0%b8%d1%84%d0%b8%d0%ba%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%be%d0%b2-%d0%b8-%d0%bc%d0%be%d0%b4%d0%b8%d1%84%d0%b8%d0%ba%d0%b0%d1%82%d0%be%d1%80%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;В качестве идентификаторов можно использовать буквы, цифры и знаки подчеркивания в любых комбинациях, при условии, что первый символ идентификатора не является цифрой.&lt;/p&gt; -&lt;p&gt;В NewLang существует возможность указания области видимости и времени жизни объекта с помощью модификатора — специального символа перед именем переменной. Это может показаться немного похожим на венгерскую нотацию, но в отличие от нее, модификатор не имеет отношения к типу объекта и не является частью имени идентификатора. К тому же в качестве модификаторов используется строго определённые символы, назначение которых определено заранее.&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;&lt;strong&gt;$&lt;/strong&gt; - в начале имени обозначает локальную переменную, время жизни которой ограничено текущей областью видимости и при её завершении локальная переменная уничтожается.&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;@&lt;/strong&gt; - обозначает глобальную переменную, а сам объект сохраняет свое состояние даже после выхода из текущей области видимости.&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;:&lt;/strong&gt; - двоеточие вначале имени используется в качестве модификатора для указания типа.&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;Семантика обращения к аргументам функций очень похоже на работу с аргументами в bash скриптах, где $1 или $arg — порядковый номер или имя аргумента (происходит обращение к локальным переменным в текущей области видимости).&lt;/p&gt; -&lt;h3 id=&#34;использование-модификаторов-является-обязательным-только-в-двух-случаях&#34;&gt;Использование модификаторов является обязательным только в двух случаях:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%bc%d0%be%d0%b4%d0%b8%d1%84%d0%b8%d0%ba%d0%b0%d1%82%d0%be%d1%80%d0%be%d0%b2-%d1%8f%d0%b2%d0%bb%d1%8f%d0%b5%d1%82%d1%81%d1%8f-%d0%be%d0%b1%d1%8f%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d1%8b%d0%bc-%d1%82%d0%be%d0%bb%d1%8c%d0%ba%d0%be-%d0%b2-%d0%b4%d0%b2%d1%83%d1%85-%d1%81%d0%bb%d1%83%d1%87%d0%b0%d1%8f%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;ul&gt; -&lt;li&gt;При создании нового типа данных, так как типы всегда создаются в глобальной области видимости, а их символьные имена должны быть уникальными.&lt;/li&gt; -&lt;li&gt;При обращении к объектам NewLang внутри программных вставок кода на языке реализации, так как они используется как маркеры при поиске идентификаторов NewLang в коде С/С++.&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;В остальных случаях, для обращения к переменным указывать их модификаторы необязательно. И если при обращении к объекту модификатор не указан, то сперва ищется локальная переменная, а потом глобальная с таким же именем. Причем, локальная переменная будет перекрывать глобальную.&lt;/p&gt; -&lt;p&gt;Так же следует иметь в виду, что компилятор может генерировать код для прямого обращения к локальным объектам уже на этапе компиляции, тогда как для обращения к глобальным объектам, или если модификатор области видимости отсутствует, компилятор вынужден каждый раз встраивать runtime вызов функции поиска объекта в глобальной таблице символов.&lt;/p&gt; -&lt;h1 id=&#34;система-типов&#34;&gt;Система типов&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0-%d1%82%d0%b8%d0%bf%d0%be%d0%b2&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;Так как система типов языка динамическая, то явное указание типа не влияет на размер переменной и является только своего рода логическим ограничением на возможность присвоения переменной значения другого типа.&lt;/p&gt; -&lt;p&gt;Информация о типах используется при проверке их совместимости, когда существующему объекту присваивается значение другого типа. Такая операция возможна только когда типы совместимы между собой и допускают автоматическое приведение. Это справедливо как во время парсинга/компиляции исходного теста, так и во время выполнения в режимах интерпретатора и/или скомпилированного файла.&lt;/p&gt; -&lt;h2 id=&#34;простые-типы&#34;&gt;Простые типы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%be%d1%81%d1%82%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h3 id=&#34;арифметические-значения&#34;&gt;Арифметические значения&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b0%d1%80%d0%b8%d1%84%d0%bc%d0%b5%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5-%d0%b7%d0%bd%d0%b0%d1%87%d0%b5%d0%bd%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Арифметические типы данных являются тензорами — массивами чисел одного типа с произвольным количеством измерений и одинаковым размером столбцов в каждом. Единичное число тоже тензор нулевого размера.&lt;/p&gt; -&lt;p&gt;Поддерживаются только знаковые целые числа, т.к. в беззнаковых числах особая нужда отсутствует, а проблем с ними можно найти очень много на ровном месте.&lt;/p&gt; -&lt;p&gt;Проблемы беззнаковых чисел (из интернета):&lt;/p&gt; -&lt;blockquote&gt; -&lt;p&gt;Во-первых, вычитание двух беззнаковых чисел, например 3 и 5. 3 минус 5 равно 4294967294, т.к. -2 не может быть представлено как беззнаковое число. Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных значений со знаком и без знака. С++ может свободно преобразовывать числа со знаком и без знака, но не проверяет диапазон, чтобы убедиться, что вы не переполняете свой тип данных. -В C++ всё же есть несколько случаев, когда можно (или необходимо) использовать беззнаковые числа. Во-первых, числа без знака предпочтительнее при работе с битами. Во-вторых, использование беззнаковых чисел связанных с индексацией массивов.&lt;/p&gt; -&lt;/blockquote&gt; -&lt;p&gt;Но это не мой случай, так как индекс может быть отрицательным и даже не числом, а диапазоном или многоточием.&lt;/p&gt; -&lt;p&gt;З.Ы. И даже зная об этом, все равно умудрился недавно словить баг с отрицательными индексами у словарей!&lt;/p&gt; -&lt;p&gt;Имена встроенных арифметических типов говорят сами за себя: Char, Short, Int, Long, Float, Double, ComplexFloat, ComplexDouble. Отдельным типом идет логический тип Bool, который может принимать значения только 0 или 1 (false/true соответственно), и в зависимости от выполняемой операции может быть отнесен к целочисленным типам, так и не входить в их состав (данный подход интерпретации логического типа данных был взят из библиотеки Torch).&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;// Treat bool as a distinct &amp;#34;category,&amp;#34; to be consistent with type promotion -// rules (e.g. `bool_tensor + 5 -&amp;gt; int64_tensor`). If `5` was in the same -// category as `bool_tensor`, we would not promote. Differing categories -// implies `bool_tensor += 5` is disallowed. -// -// NB: numpy distinguishes &amp;#34;unsigned&amp;#34; as a category to get the desired -// `bool_tensor + 5 -&amp;gt; int64_tensor` behavior. We don&amp;#39;t, because: -// * We don&amp;#39;t want the performance hit of checking the runtime sign of Scalars. -// * `uint8_tensor + 5 -&amp;gt; int64_tensor` would be undesirable. -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;В будущем планируется добавить классы чисел для длинной арифметики и дробей, для чего зарезервированы названия типов BigNum, Currency и Fraction.&lt;/p&gt; -&lt;p&gt;Доступ к элементам тензора происходит по целочисленному индексу, который начинается с 0. Для многомерного тензора, индексы элемента перечисляются в квадратных скобках через запятую. Поддерживается доступ к элементам через отрицательный индекс, который обрабатывается точно так же, как в Python (-1 последний элемент, -2 предпоследний и т.д.).&lt;/p&gt; -&lt;p&gt;Литерал тензор в тексте программы записывается в квадратных скобках с обязательной завершающей запятой, т.е. [1, 2,] — это литерал одномерный тензор из двух чисел. После закрывающей скобки тип тензора может быть указан в явном виде. Если тип не указан, то он выводится автоматически на основании указанных данных и выбирается минимально возможный байтовый размер, который позволяет сохранить все значения без потери точности.&lt;/p&gt; -&lt;p&gt;&lt;em&gt;Примеры:&lt;/em&gt;&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$var_char := 123; # Тип Char выводится автоматически -$var_short := 1000; # Тип Short выводится автоматически -$var_bool := [0, 1, 0, 1,]; # Тензор из 4 элементов. Тип Bool выводится автоматически -$tensor[10,10]:Int := 1; # Тензор Int размером 2x2 инициализированный 1 -$scalar := $tensor[5,5]; # Присвоить скаляру значение указанного элемента тензора -&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;строки&#34;&gt;Строки&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d1%82%d1%80%d0%be%d0%ba%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Поддерживаются два типа строк, StrWide — символьные (широкие) и StrChar — байтовые. Различия между ними заключается в типе единичного элемента. У символьных строк единичным элементом является широкий символ &lt;em&gt;wchar_t&lt;/em&gt;, а у байтовой строки единичным элементом является один байт (точнее &lt;em&gt;char&lt;/em&gt;, т.е. байт со знаком). Символьные строки литералы в исходном тексте записывается в «двойных кавычках», а байтовые строки в &amp;lsquo;одинарных кавычках&amp;rsquo;.&lt;/p&gt; -&lt;p&gt;Количество элементов символьной строки возвращается в широких символах, а размер байтовой строки в байтах, поэтому и обращение к элементу строки по индексу происходит соответственно либо к символу, либо к байту.&lt;/p&gt; -&lt;p&gt;Важный момент. К любой переменной можно обратиться так же, как к функции (записав после её имени круглые скобки). Результатом этой операции будет создание копии/клона объекта. Причем некоторые типы (словари, классы и символьные строки) можно использовать в качестве шаблона при создании копии объекта с модифицированными свойствами, если новые и/или изменяемые значения указать в скобках, как аргументы при вызовах функций. Так, если при создании копии в скобках указать набор новых данных, то результирующая копия будет содержать уже измененные данные.&lt;/p&gt; -&lt;p&gt;&lt;em&gt;Например:&lt;/em&gt;&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$template := &amp;#34;${name} $1&amp;#34;; # Обычная строка -$result := $template(&amp;#34;шаблон&amp;#34;, name = &amp;#34;Строка&amp;#34;); # result = &amp;#34;Строка шаблон&amp;#34; -&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;системные&#34;&gt;Системные&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%8b%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h3 id=&#34;pointer---указатель-на-системную-область-памяти&#34;&gt;:Pointer - указатель на системную область памяти&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#pointer---%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%83%d1%8e-%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Так как любой программе приходится взаимодействовать с внешним миром, то по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип &lt;em&gt;Pointer&lt;/em&gt;. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. Но можно вывести его значение, например для отладки.&lt;/p&gt; -&lt;h3 id=&#34;plain---указатель-на-представление-данных-в-бинарном-виде&#34;&gt;:Plain - указатель на представление данных в бинарном виде&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#plain---%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d0%bf%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%be%d0%bc-%d0%b2%d0%b8%d0%b4%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Для взаимодействия с внешними библиотеками требуется еще и обмен данными. И для этих целей служит тип данных &lt;em&gt;Plain&lt;/em&gt; - который также является указателем, но на двоичное представление данных в единой области памяти. Конечно, если их можно представить в виде единого фрагмента.&lt;/p&gt; -&lt;h2 id=&#34;составные-типы-данных&#34;&gt;Составные типы данных:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%be%d1%81%d1%82%d0%b0%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h3 id=&#34;словарь&#34;&gt;Словарь&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%bb%d0%be%d0%b2%d0%b0%d1%80%d1%8c&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Словарь (:Dictionary) — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии (он похож и на tuple и на структуру одновременно). Словари от тензоров отличаются тем, что являются только одномерными массивами, но каждый элемент может содержать произвольное количество элементов любого типа, в том числе и другие словари.&lt;/p&gt; -&lt;p&gt;Доступ к элементам словарей происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. Индекс также начинается с 0 и как у тензоров и тоже может быть отрицательным.&lt;/p&gt; -&lt;p&gt;Литерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, т. е. (,) — пустой словарь, (1, 2= «2», name=3,).&lt;/p&gt; -&lt;h3 id=&#34;перечисление-структура-и-объединение&#34;&gt;Перечисление, структура и объединение&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d0%b5%d1%80%d0%b5%d1%87%d0%b8%d1%81%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d0%b8-%d0%be%d0%b1%d1%8a%d0%b5%d0%b4%d0%b8%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;&lt;em&gt;:Enum&lt;/em&gt;, &lt;em&gt;:Struct&lt;/em&gt; и &lt;em&gt;:Union&lt;/em&gt; — это такие же словари, только на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера.&lt;/p&gt; -&lt;h3 id=&#34;классы&#34;&gt;Классы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%ba%d0%bb%d0%b0%d1%81%d1%81%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Класс (реализован частично) — тип данных, с помощью которого реализуется один из принципов ООП — наследование. При создании экземпляра класса создается новая переменная, у которой сохраняется информацию о своем родителе и которая наследует от него свойства и методы. Тип данных &lt;em&gt;:Class&lt;/em&gt; аналогичен словарю, но все свойства обязаны иметь имена (хотя доступ к свойствам класса по индексу так же возможен).&lt;/p&gt; -&lt;h2 id=&#34;функции&#34;&gt;Функции&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Синтаксис NewLang поддерживать несколько типов функций (а в будущем и методов классов): обычные функции, чистые функции и простые чистые функции.&lt;/p&gt; -&lt;p&gt;Для всех типов функций поддерживаются аргументы по умолчанию. При создании функции, её аргументы указываются как в Python, т.е. вначале идут обязательные аргументы, потом аргументы со значениями по умолчанию, где имя аргумента отделяется от его значения по умолчанию знаком равно &lt;strong&gt;=&lt;/strong&gt;. Если функция допускает обработку произвольного количества аргументов, то последним в списке параметров указывается многоточие &lt;strong&gt;&amp;hellip;&lt;/strong&gt; (три точки подряд) .&lt;/p&gt; -&lt;h3 id=&#34;обычная-функция&#34;&gt;Обычная функция&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%b1%d1%8b%d1%87%d0%bd%d0%b0%d1%8f-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Обычная функция — такие функции являются именно обычными функциями в понимании С/С++. Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д.&lt;/p&gt; -&lt;p&gt;Внутри обычной функции можно обращаться к локальным и глобальным объектам, и они могут содержаться вставки на языке реализации*, например, для вызова функций из внешних библиотек.&lt;/p&gt; -&lt;p&gt;Вставки на языке реализации оформляются в виде %{ %} и могут содержать любой текст на С/С++, а прямо из него можно обращаться к локальным и глобальным объектам NewLang так же, как и в обычном синтаксисе, указывая первым символом имени соответствующий модификатор (&lt;em&gt;$&lt;/em&gt; для локальных объектов и &lt;em&gt;@&lt;/em&gt; для глобальных).&lt;/p&gt; -&lt;p&gt;Технически, такая программная вставка просто переносится трансплайтером непосредственно в исходный текст генерируемого файла, а все идентификаторы NewLang специальным образом декорируются (добавляются специальные маркеры для их идентификации), после этого исходный текст подается на вход обычному компилятору С++. Для локальных объектов трансплайтер может генерировать код для прямого доступа к объекту на этапе компиляции, а для работы с глобальными объектами вынужден использовать runtime вызовы функции поиска в таблице символов.&lt;/p&gt; -&lt;hr&gt; -&lt;p&gt;*) - Программные вставки на языке реализации обрабатываются только во время компиляции&lt;/p&gt; -&lt;p&gt;&lt;em&gt;Например:&lt;/em&gt;&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;print(str) := { - %{ - printf(&amp;#34;%s&amp;#34;, static_cast&amp;lt;const char *&amp;gt;($str)); /* Прямой вызов С функции */ - %} -}; -&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;чистые-функции&#34;&gt;Чистые функции&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%87%d0%b8%d1%81%d1%82%d1%8b%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Чистая функция — это тоже обычная функция, только в том смысле, какой в него вкладывает функциональное программирование. Создания чистой функции происходит с помощью оператора &lt;strong&gt;:-&lt;/strong&gt;, а сам оператор заимствован из языка Пролог. У чистой функции отсутствует доступ к контексту и глобальным переменным, поэтому она может обрабатывать только те данные, которые были ей переданы в качестве аргументов.&lt;/p&gt; -&lt;p&gt;Программные вставки на языке реализации внутри чистых функций не запрещены и могут использоваться, например, для отладки. Но делается это на страх и риск разработчика. Именно он отвечает за их «чистоту», например при вызове функций из внешних библиотек.&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Sum(arg1, arg2) :- {$arg1+$arg2;}; # Вернуть сумму аргументов -&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;простые-чистые-функции&#34;&gt;Простые чистые функции&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%be%d1%81%d1%82%d1%8b%d0%b5-%d1%87%d0%b8%d1%81%d1%82%d1%8b%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Простые чистые функции — отдельный класс чистых функций, которые предназначены только для вычисления логического результата (т.е. они являются предикатами) и их отличает упрощенная формой записи. Тело простой чистой функции состоит из последовательности операторов, которые разделяются запятыми и заканчиваются, как и любое выражение, точкой с запятой. Все операторы простой чистой функции всегда приводятся к булевому значению, а итоговый результат функции вычисляется по одной из возможных логических операций: И, ИЛИ и исключающее ИЛИ.&lt;/p&gt; -&lt;p&gt;&lt;em&gt;Например:&lt;/em&gt;&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;func_and(arg1, arg2) :&amp;amp;&amp;amp;= arg1==3, arg2 &amp;gt; 0; # Простая чистая функция Логическое И -func_or(arg1, arg2) :||= arg1==3, arg2 &amp;gt; 0; # Простая чистая функция Логическое ИЛИ -func_xor(arg1, arg2) :^^= arg1==3, arg2 &amp;gt; 0; # Простая чистая функция Исключающее ИЛИ -&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;специальные-типы-данных&#34;&gt;Специальные типы данных:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%bf%d0%b5%d1%86%d0%b8%d0%b0%d0%bb%d1%8c%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h3 id=&#34;пусто-none&#34;&gt;Пусто (:None)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%83%d1%81%d1%82%d0%be-none&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;&lt;strong&gt;:None&lt;/strong&gt; (пусто) — не содержит значения (точнее имеет одно значение None) и совместим с любым другим типом данных. Указывается в тексте программы как один подчерк «_». None имеют не инициализированные переменные и при попытке чтения из такой переменной возникает ошибка.&lt;/p&gt; -&lt;p&gt;Тип переменной может быть явно указан или выведен автоматически из присваиваемого значения. Присвоить новое значение уже инициализированной переменной можно только для совместимого типа, так как неявное преобразование типов не допускаются.&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$var := _; # Создать не инициализированную переменную -$var2 := var; # Ошибка!!! Нельзя прочитать неинициализированную переменную var -$var = 1000; # У переменной будет тип Short (минимальный размер для хранения значения) -$var = 0,5; # Ошибка!!! Short ← Float не совместимы -$var = _; # Очистить значение переменной -$var = 0,5; # Теперь можно, т. к. None совместим с любым типом -&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;диапазон-range&#34;&gt;Диапазон (:Range)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b4%d0%b8%d0%b0%d0%bf%d0%b0%d0%b7%d0%be%d0%bd-range&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Диапазон — специальный тип данных, являющейся приблизительным аналогом типа «генератор» в Python. К диапазону можно обращаться как к итератору и он будет поочередно выдавать элементы в указанном интервале с заданным шагом. Диапазон в тексте программы указывается как два или три элемента через две точки, например 1..5 — диапазон от единицы до пяти с шагом по умолчанию 1. В качестве параметров диапазона можно указывать не только литералы, но и имена переменных. Например, &lt;em&gt;0,1..$stop..0,1&lt;/em&gt; — диапазон от 0,1 до значения, указанного в переменной $stop с шагом 0,1.&lt;/p&gt; -&lt;p&gt;Диапазон для целых чисел можно использовать в качестве индекса у тензоров (точнее, у любых объектов, которые допускают доступ к своим элементам по индексу, т.е. тензоры, словари и текстовые строки). Фактический, это поведение аналогично &lt;em&gt;slice&lt;/em&gt; в языке Python и &lt;em&gt;array[1:5]&lt;/em&gt; в Python означает тоже самое, что и &lt;em&gt;array[1..5]&lt;/em&gt; в NewLang.&lt;/p&gt; -&lt;p&gt;В качестве индекса у тензоров еще можно указать произвольное количество измерений с помощью многоточия, т.е.&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$tensor[…, 0] = 0; # Обнулить все первые элементы в каждом измерении. -&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;преобразование-типов&#34;&gt;Преобразование типов&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b5%d0%be%d0%b1%d1%80%d0%b0%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d1%82%d0%b8%d0%bf%d0%be%d0%b2&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h3 id=&#34;явное-приведение-типов&#34;&gt;Явное приведение типов&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%8f%d0%b2%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%b8%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5-%d1%82%d0%b8%d0%bf%d0%be%d0%b2&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Несмотря на динамическую типизацию языка, если тип переменной указан явно, то автоматическое приведение типов не выполняется, и чтобы присвоить переменой значение не совместимого типа, требуется явное преобразование.&lt;/p&gt; -&lt;p&gt;Так как символьные названия типов относятся к деталям реализации, то явное преобразование в конкретный тип данных производится с помощью вызова функции с именем типа, т.е. :Bool(), :StrWide(), :Long() и т.д.&lt;/p&gt; -&lt;p&gt;Для преобразования любого типа данных в строку ещё можно использовать оператор конкатенации строк, которой преобразует любой тип данных в строковое представление. Но, так как строковых типов два (байтовые и широкие строки), то тип строки определяется первым аргументом в операторе конкатенации/сцепления &lt;strong&gt;++&lt;/strong&gt;. Также преобразовать любое значение в строковое можно с помощью строки-шаблона.&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;#34;&amp;#34; ++ 123; # &amp;#34;123&amp;#34; - Строка широких символов -&amp;#39;&amp;#39; ++ 123; # &amp;#39;123&amp;#39; - Байтовая строка - -val := 12345; # Число -&amp;#34;$1&amp;#34;(val); # Будет строка &amp;#34;12345&amp;#34; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Так как тензоры могут иметь больше одного значения, то и в качестве аргументов могут принимать их произвольное количество, а итоговым результатом будет тензор, в котором все переданные данные преобразованы к требуемому типу автоматически.&lt;/p&gt; -&lt;p&gt;&lt;em&gt;Примеры:&lt;/em&gt;&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;gt; tstr := :Tensor(&amp;#34;Тест&amp;#34;); # Создать тензор из строки широких символов -[1058, 1077, 1089, 1090,]:Int - -&amp;gt; t2 := :Tensor[2,2](&amp;#34;Тест&amp;#34;); # Тоже самое, но тензор указанной размерности -[ - [1058, 1077,], [1089, 1090,], -]:Int - -&amp;gt; :StrWide(tstr) # Создать символьную строку из тензора -Тест - -&amp;gt; :Double(t2) # Изменить тип данных тезора без изменения размерности -[ - [1058, 1077,], [1089, 1090,], -]:Double - -&amp;gt; t3 := :Char[4]( t2 ) # Изменить размерность тензора и его тип (в данном случае с частичной потерей данных) -[34, 53, 65, 66,]:Char - - -&amp;gt;:Tensor( (1,2,3,) ); # Тензор из словаря -[1, 2, 3,]:Char - -&amp;gt;:Tensor( &amp;#39;first second&amp;#39; ) # Байтовая строка в тензор -[102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char - -&amp;gt;:Tensor( (first=&amp;#39;first&amp;#39;, space=32, second=&amp;#39;second&amp;#39;,) ) # Получаем тензор из словаря с такими же данными -[102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char - -&amp;gt;:Double[10,2]( 0, ...) # Тензор заданного формата с нулями, где многоточие повторяет последние указанные данные до получения тензора требуемого размера -[ - [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], -]:Double - -&amp;gt;:Int[3,2]( ... rand() ...) # Тензор со случайными данными, где между многоточиями указана функция, которую следует вызывать каждый раз при получении нового элемента тензора -# Пришлось придумывать новую конструкцию, т.к. многоточие перед именем, это оператор раскрытия словаря, а многоточие после имени, это повторение последнего значения до конца заданной размерности. -[ - [1804289383, 846930886,], [1681692777, 1714636915,], [1957747793, 424238335,], -]:Int - -&amp;gt;:Int[5,2]( 0..10 ); # Создание тензора из диапазона -[ - [0, 1,], [2, 3,], [4, 5,], [6, 7,], [8, 9,], -]:Int - -&amp;gt;:Tensor( 0..0.99..0.1 ); # Или даже так -[0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,]:Double -&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;операторы-и-управляющие-конструкции&#34;&gt;Операторы и управляющие конструкции&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d0%b8-%d1%83%d0%bf%d1%80%d0%b0%d0%b2%d0%bb%d1%8f%d1%8e%d1%89%d0%b8%d0%b5-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%86%d0%b8%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;h2 id=&#34;операторы&#34;&gt;Операторы:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Все операторы имеют парный аналог с присвоением значения:&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;&lt;strong&gt;+&lt;/strong&gt; и &lt;strong&gt;+=&lt;/strong&gt; - сложение арифметических типов данных;&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;-&lt;/strong&gt; и &lt;strong&gt;-=&lt;/strong&gt; - вычитание арифметических типов данных;&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;/&lt;/strong&gt; и &lt;strong&gt;/=&lt;/strong&gt; - деление (результат число с плавающей точкой);&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;//&lt;/strong&gt; и &lt;strong&gt;//=&lt;/strong&gt; - целочисленное деление с округлением к меньшему числу (как в Python);&lt;/li&gt; -&lt;li&gt;&lt;em&gt;*&lt;/em&gt; и &lt;em&gt;*=&lt;/em&gt; - умножение;&lt;/li&gt; -&lt;li&gt;&lt;em&gt;**&lt;/em&gt; и &lt;strong&gt;**=&lt;/strong&gt; - возведение в степень (он же используется и для повторения текстовых строк);&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;++&lt;/strong&gt; и &lt;strong&gt;++=&lt;/strong&gt; - конкатенация строк с автоматическим приведением аргументов к стоковому типу (символ инкремента специально используется вместо одиночного плюса для того, чтобы в явном виде разделить конкатенацию строк и операторы арифметического сложения).&lt;/li&gt; -&lt;/ul&gt; -&lt;h2 id=&#34;операторы-сравнения&#34;&gt;Операторы сравнения:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d1%81%d1%80%d0%b0%d0%b2%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;ul&gt; -&lt;li&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;, &lt;strong&gt;&amp;gt;&lt;/strong&gt;, &lt;strong&gt;&amp;lt;=&lt;/strong&gt;, &lt;strong&gt;&amp;gt;=&lt;/strong&gt; - классические для сравнения скаляров&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;==&lt;/strong&gt; и &lt;strong&gt;!=&lt;/strong&gt; - операторы сравнения с автоматическим приведением совместимых типов для любых объектов&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;===&lt;/strong&gt; и &lt;strong&gt;!==&lt;/strong&gt; - оператор точного сравнения для любых объектов (автоматического приведения типов не выполняется)&lt;/li&gt; -&lt;/ul&gt; -&lt;h2 id=&#34;проверки-типа-имени-класса-объекта&#34;&gt;Проверки типа (имени класса объекта):&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b8-%d1%82%d0%b8%d0%bf%d0%b0-%d0%b8%d0%bc%d0%b5%d0%bd%d0%b8-%d0%ba%d0%bb%d0%b0%d1%81%d1%81%d0%b0-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Для оператора проверки имени класса объекта используется символ тильда &lt;strong&gt;~&lt;/strong&gt;. Он немного похож на оператор &lt;em&gt;instanceof&lt;/em&gt; в Java. Левым операндом должен быть проверяемый объект, а правым — проверяемый тип, который можно указать строкой литералом, переменной строкового типа или именем проверяемого класса непосредственно. Результатом операции будет истина, если правый операнд содержит название класса проверяемого объекта или он присутствует в иерархии наследования.&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;name := &amp;#34;class&amp;#34;; # Строковая переменная с именем класса -var ~ name; -var ~ :class; # Имя типа -var ~ &amp;#34;class&amp;#34;; # Строка литерал с именем типа -&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;утиная-типизация&#34;&gt;Утиная типизация&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%83%d1%82%d0%b8%d0%bd%d0%b0%d1%8f-%d1%82%d0%b8%d0%bf%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Оператор утиной типизации, два символа тильны &lt;strong&gt;~~&lt;/strong&gt; — приблизительный аналог функции isinstance() в Python, который для простых типов сравнивает непосредственную совместимость типа левого операнда по отношению к правому. А для словарей и классов в левом операнде проверяется наличие всех имен полей, присутствующих у правого операнда, т.е.:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(field1=«value», field2=2,) ~~ (); # Истина (т. е. левый операнд словарь) -(field1=«value», field2=2,) ~~ (field1=_); # Тоже истина (т. к. поле field1 присутствует у левого операнда) -(field1=«value», field2=2,) ~~ (not_found=_); # Ложь, т.к. поле not_found у левого операнда отсутствует -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Строгая утиная типизация &lt;strong&gt;~~~&lt;/strong&gt; — для простых типов сравнивается идентичности типов без учета совместимости, а для составных типов происходит сравнение всех свойств с помощью оператора строгого равенства. Для данной операции, пустой тип совместим только с другим пустим типом.&lt;/p&gt; -&lt;h1 id=&#34;управляющие-конструкции&#34;&gt;Управляющие конструкции&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%83%d0%bf%d1%80%d0%b0%d0%b2%d0%bb%d1%8f%d1%8e%d1%89%d0%b8%d0%b5-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%86%d0%b8%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;К управляющим конструкциям языка NewLang относятся условный оператор, два вида циклов, оператор оценки выражения, оператор прерывания последовательности выполнения команд и перехват прерывания. Операторы проверки условий всегда указываются в квадратных скобках, а последовательность команд для выполнения - в фигурных.&lt;/p&gt; -&lt;h2 id=&#34;условный-оператор&#34;&gt;Условный оператор&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%83%d1%81%d0%bb%d0%be%d0%b2%d0%bd%d1%8b%d0%b9-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;В качестве оператора проверки условия используется синтаксическая конструкция, соответствующая по смыслу термину «следует», т.е. тире и угловая скобка &lt;strong&gt;-&amp;gt;&lt;/strong&gt; или с двумя тире для большей наглядности &lt;strong&gt;&amp;ndash;&amp;gt;&lt;/strong&gt;. Такая запись условного оператора очень похожа на математическую и легко объединяется в последовательности для проверки множественных условий вида «else if».&lt;/p&gt; -&lt;p&gt;В общем случае условный оператор имеет вид: &lt;code&gt;[ условие ] -&amp;gt; действие;&lt;/code&gt; или &lt;code&gt;[ условие ] -&amp;gt; {действие};&lt;/code&gt; или &lt;code&gt;[ условие1 || условие2 ] --&amp;gt; {действие}, [_] --&amp;gt; {действие иначе};&lt;/code&gt;&lt;/p&gt; -&lt;p&gt;Для наглядности записанный с отступами:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[ условие1 ] -&amp;gt; { действие1 }, - [ условие2 ] -&amp;gt; действие2, - [ условие3 ] -&amp;gt; действие3, - [_] -&amp;gt; {действие_иначе}; -&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;оценка-выражения&#34;&gt;Оценка выражения&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d1%86%d0%b5%d0%bd%d0%ba%d0%b0-%d0%b2%d1%8b%d1%80%d0%b0%d0%b6%d0%b5%d0%bd%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Синтаксическая конструкция с помощью которой реализуется аналог оператора switch выглядит следующим образом:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[ $var ] ==&amp;gt; { - [1] -&amp;gt; { code }; # Выполнится проверка условия $var == 1 - [1, 2] -&amp;gt; { code }; # Выполнится проверка условия ($var == 1 || $var == 2) - [_] -&amp;gt; { code default }; # Ветка условия иначе -}; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Причем в качестве оператора для оценки могут быть использован любые имеющиеся операторы сравнения на равенство:&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;&lt;strong&gt;==&amp;gt;&lt;/strong&gt; - проверка на равенство с приведением типов;&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;===&amp;gt;&lt;/strong&gt; - проверка на точное равенство;&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;~&amp;gt;&lt;/strong&gt; - проверка типа (имени класса);&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;~~&amp;gt;&lt;/strong&gt; - утиная типизация;&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;~~~&amp;gt;&lt;/strong&gt; - строгая утиная типизация.&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;И если в качестве оператора сравнения использовать оператор утиной типизации, то оценка выражения превращается в классический Pattern Matching:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$value := (f1=1, f2=&amp;#34;2&amp;#34;,); -[ $value ] ~~~&amp;gt; { - [ (f1=_, ), (f1=_, f2=0, ) ] -&amp;gt; { code }; # Поле f2 отсутствует или число - [(f1=_, f2=&amp;#34;&amp;#34;,), (f1=_, f2=&amp;#39;&amp;#39;,)] -&amp;gt; { code }; # Поле f2 строка - [_] -&amp;gt; { code default }; # Код по умолчанию -}; -&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;операторы-циклов&#34;&gt;Операторы циклов&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d1%86%d0%b8%d0%ba%d0%bb%d0%be%d0%b2&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Для указания операторов циклов используются управляющие &lt;strong&gt;-&amp;raquo;&lt;/strong&gt; или &lt;strong&gt;&amp;ndash;&amp;raquo;&lt;/strong&gt; (с двумя стрелками по направлению от проверки условия к телу цикла). И в зависимости от расположения условия и тела цикла, он может быть с предусловием (&lt;em&gt;while&lt;/em&gt;) или постусловием (&lt;em&gt;do while&lt;/em&gt;). Хотя пока эти синтаксические конструкции не &amp;ldquo;отлежались&amp;rdquo; и их можно считать временными из-за того, что их легко перепутать с условным оператором, и, возможно, имеет смысл заменить разные операторы цикла одной единственной конструкцией вида: &lt;strong&gt;&amp;lt;&amp;ndash;&amp;gt;&lt;/strong&gt; или &lt;strong&gt;&amp;laquo;-&amp;raquo;&lt;/strong&gt;, которая сильнее отличается от оператора следования.&lt;/p&gt; -&lt;p&gt;Но в настоящий момент циклы реализованы вот так:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[условие while] -&amp;gt;&amp;gt; { - тело цикла while -}; - -{ - тело цикла do while -} &amp;lt;&amp;lt;-- [условие do while]; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Реализация цикла foreach на примере суммирования всех элементов словаря (или одномерного тензора):&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;summa := 0; -dict := (1,2,3,4,5,); -[ dict ] --&amp;gt;&amp;gt; { # Условие цикла, пока есть данные - item, dict := ... dict; # Результат оператора раскрытия словаря - первый его элемент перемещается в item - summa += item; # Вычисление суммы всех элементов словаря -}; -&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;операторы-прерывания-возврата&#34;&gt;Операторы прерывания (возврата)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d0%bf%d1%80%d0%b5%d1%80%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%b2%d0%be%d0%b7%d0%b2%d1%80%d0%b0%d1%82%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;В качестве оператора прерывания/возврата используется два символа минус &lt;strong&gt;&amp;ndash;&lt;/strong&gt;. Оператор позволяет прервать выполнение последовательности команд и/или вернуть данные из текущей функции/блока кода и является самым близким аналогом оператора &lt;strong&gt;return&lt;/strong&gt; и &lt;strong&gt;throw&lt;/strong&gt; одновременно. Для того чтобы вернуть данные, их необходимо указать между двумя операторами прерывания, т.е. &lt;code&gt;--100--; # Вернуть указанное значение&lt;/code&gt;. Если возвращаемое значение не указано явно, то будет возвращено значение &lt;em&gt;None&lt;/em&gt;.&lt;/p&gt; -&lt;h2 id=&#34;следование-блок-кодалямбда-функция&#34;&gt;Следование (блок кода/лямбда функция)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%bb%d0%b5%d0%b4%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%b1%d0%bb%d0%be%d0%ba-%d0%ba%d0%be%d0%b4%d0%b0%d0%bb%d1%8f%d0%bc%d0%b1%d0%b4%d0%b0-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Алгоритмическая конструкция, которая отвечает последовательное выполнение нескольких команд/операторов и возвращающая результат выполнения последнего из них. Также, результатом выполнения может быть значение, которое возвращается с помощью оператора прерывания (возврата). Это очень похоже на классическую лямбда функцию, только она выполняется сразу во время определения, а в переменную сохраняется уже результат её выполнения.&lt;/p&gt; -&lt;p&gt;Следование без перехвата прерывания оформляется в виде последовательности обычных и фигурных скобок, т.е. &lt;code&gt;(){ run code };&lt;/code&gt; или тоже самое, но сохраняет результата выполнения в переменной: &lt;code&gt;$result := (){ run(); code() };&lt;/code&gt;. Но если внутри такой функции будет выполнен оператор прерывания, то она никогда вернет управления и не сохранит возвращаемое значение в переменой &lt;em&gt;$result&lt;/em&gt;!&lt;/p&gt; -&lt;p&gt;Чтобы перехватывать прерывания, в том числе и возвращаемые значения, необходимо использовать конструкция следования с перехватом прерываний, которая оформляется в виде последовательности обычных и &lt;strong&gt;двойных&lt;/strong&gt; фигурных скобок, т.е. &lt;code&gt;$error := (){{ run(); error();code() }};&lt;/code&gt;. Такая конструкция перехватывает все возвраты и прерывания, если они возникают во время выполнения последовательности команд. В этом случае любой результат будет сохранен в переменной &lt;em&gt;$error&lt;/em&gt; как при нормальном завершении, так и в случае возникновения ошибки.&lt;/p&gt; -&lt;p&gt;Для более тонкой настройки перехвата прерываний следует использовать типизированную конструкцию, когда в явном виде указывается, какие типы прерываний следует перехватывать. &lt;code&gt;$runtime := (){{ run(); error(); code() }}:ErrorRuntime;&lt;/code&gt;. Такая конструкция вернет результат только в случае успешного завершения (когда с помощью оператора прерывания возвращается не типизированное значение, например, &lt;code&gt;--&amp;quot;Строка&amp;quot;--;&lt;/code&gt;), или при создании прерывания с указанием конкретного типа &lt;strong&gt;&amp;ndash;:ErrorRuntime(&amp;ldquo;Описание ошибки&amp;rdquo;)&amp;ndash;;&lt;/strong&gt;. А вот при возникновении любого другого типизированного прерывания, значение перехвачено не будет и все отработает как самый первый вариант, т.е. без перехвата прерывания и без сохранения возвращаемого значения в переменную.&lt;/p&gt; -&lt;h2 id=&#34;стратегия-обработки-ошибок&#34;&gt;Стратегия обработки ошибок&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d1%82%d1%80%d0%b0%d1%82%d0%b5%d0%b3%d0%b8%d1%8f-%d0%be%d0%b1%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b8-%d0%be%d1%88%d0%b8%d0%b1%d0%be%d0%ba&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Обработка ошибок состоит из комбинации двух элементов: оператора прерывания выполнения с указанием типа возвращаемого значения и алгоритмической конструкции следование с возможностью перехвата прерывания заданного типа.&lt;/p&gt; -&lt;p&gt;Это немного отличается от классического варианта обработки исключений, который в обычных языках программирования обычно оформляется ключевыми словами try… catch… finally с различными вариациями. Ведь основная цель подобных синтаксических конструкций — выделить участок кода, где возможно возникновение ошибки, перехватить и обработать правильный тип данных (исключений), т.к. &lt;strong&gt;NewLang&lt;/strong&gt; не делает различий между операторами возврата и генерации исключения.&lt;/p&gt; -&lt;h3 id=&#34;подход-к-обработке-исключений-следующий&#34;&gt;Подход к обработке исключений следующий:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d0%be%d0%b4%d1%85%d0%be%d0%b4-%d0%ba-%d0%be%d0%b1%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b5-%d0%b8%d1%81%d0%ba%d0%bb%d1%8e%d1%87%d0%b5%d0%bd%d0%b8%d0%b9-%d1%81%d0%bb%d0%b5%d0%b4%d1%83%d1%8e%d1%89%d0%b8%d0%b9&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Программный код, который может привести к ошибке, заключается в двойные фигурные скобки, а результат выполнения такого блока кода присваивается переменной. После этого анализируется возвращенное значение, например, оператором сравнения по образцу:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$result := (){{ # начало аналога блока try - $value := call_or_exception1(); - [условие1] -&amp;gt; { -- :Error -- }; - [условие2] -&amp;gt; { -- $value -- }; - $value := call_or_exception2(); -}}; # конец аналога блока try - -[$result] ~&amp;gt; { # Для сравнения по образцу использовать оператор проверки типа (имени класса) - [:ErrorParser] -&amp;gt; {Код обработки ошибок парсера}; - [:ErrorRunTime] -&amp;gt; {Код обработки ошибок времени выполнения}; - [:Error] -&amp;gt; { Код обработки остальных ошибок }; - [_] -&amp;gt; { Обработка нормальных данных $value без ошибок }; -}; -&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;сборка-repl-из-исходников-пока-только-под-linux&#34;&gt;Сборка REPL из исходников (пока только под Linux)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b1%d0%be%d1%80%d0%ba%d0%b0-repl-%d0%b8%d0%b7-%d0%b8%d1%81%d1%85%d0%be%d0%b4%d0%bd%d0%b8%d0%ba%d0%be%d0%b2-%d0%bf%d0%be%d0%ba%d0%b0-%d1%82%d0%be%d0%bb%d1%8c%d0%ba%d0%be-%d0%bf%d0%be%d0%b4-linux&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h3 id=&#34;подготовка-репозитория&#34;&gt;Подготовка репозитория&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d0%be%d0%b4%d0%b3%d0%be%d1%82%d0%be%d0%b2%d0%ba%d0%b0-%d1%80%d0%b5%d0%bf%d0%be%d0%b7%d0%b8%d1%82%d0%be%d1%80%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;ul&gt; -&lt;li&gt;&lt;a href=&#34;https://github.com/rsashka/newlang&#34;&gt;&lt;u&gt;Скачать исходники&lt;/u&gt;&lt;/a&gt;&lt;/li&gt; -&lt;li&gt;Скачать и развернуть архив &lt;a href=&#34;https://pytorch.org/&#34;&gt;libtorch&lt;/a&gt; в каталоге &lt;em&gt;contrib&lt;/em&gt; (PyTorch Build: Stable (1.10.*) -&amp;gt; Your OS: Linux -&amp;gt; Package: LibTorch -&amp;gt; Language: C++ / Java -&amp;gt; Compute Platform: CPU -&amp;gt; Download here (cxx11 ABI): -&lt;a href=&#34;https://download.pytorch.org/libtorch/cpu/libtorch-cxx11-abi-shared-with-deps-1.10.2%2Bcpu.zip&#34;&gt;libtorch-cxx11-abi-shared-with-deps-1.10.2+cpu.zip&lt;/a&gt;)&lt;/li&gt; -&lt;li&gt;Активировать и скачать исходники субмодулей (&lt;code&gt;git submodule init &amp;amp;&amp;amp; git submodule update&lt;/code&gt;)&lt;/li&gt; -&lt;li&gt;В каталоге &lt;em&gt;contrib&lt;/em&gt; запустить файл &lt;code&gt;build.sh&lt;/code&gt; для сборки библиотеки libffi&lt;/li&gt; -&lt;li&gt;В каталоге &lt;em&gt;core&lt;/em&gt; запустить файл &lt;code&gt;compile_syntax.sh&lt;/code&gt; для генерации файлов парсера и лексического анализатора. Также может потребоваться установка утилит &lt;em&gt;flex&lt;/em&gt; и &lt;em&gt;bison&lt;/em&gt;. Если что, у меня установлены flex 2.6.4 и bison (GNU Bison) 3.7.4&lt;/li&gt; -&lt;/ul&gt; -&lt;h3 id=&#34;собрать&#34;&gt;Собрать&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%be%d0%b1%d1%80%d0%b0%d1%82%d1%8c&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;ul&gt; -&lt;li&gt;Юнит-тесты (newlang_test): в каталоге &lt;em&gt;core&lt;/em&gt; выполнить команду &lt;code&gt;make CONF=UnitTest&lt;/code&gt;*&lt;/li&gt; -&lt;li&gt;Интерпретатор (nlc): в каталоге &lt;em&gt;core&lt;/em&gt; выполнить команду &lt;code&gt;make CONF=Debug&lt;/code&gt;*&lt;/li&gt; -&lt;/ul&gt; -&lt;hr&gt; -&lt;p&gt;*) - Сборка проекта выполняется обычной утилитой make, но сборочные файлы генерируются автоматически в давно устаревшей версии NetBeans 8.2, т.к. это единственная универсальная среда разработки с поддержкой Makefile &amp;ldquo;из коробки&amp;rdquo;, тогда как в текущей версии Apache NetBeans полноценная поддержка разработки на С/С++ вообще отсутствует. Начал постепенный переход на использование редактора VSCodium (аналога VSCode, в котором вычищена телеметрия от Microsoft) и генерацию скриптов сборки с помощью сmake, но этот процесс пока не завершен.&lt;/p&gt; -&lt;h1 id=&#34;планы-на-будущее&#34;&gt;Планы на будущее&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d0%bb%d0%b0%d0%bd%d1%8b-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;Текущая версия языка значительно обогатилась возможностями, но все еще является тестовой платформой для проверки декларируемых концепций и основного синтаксиса. Если говорить о планах, то в настоящий момент роадмап развития NewLang следующий:&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Реализовать макросы для более привычного использования языка (за счет использования DSL);&lt;/li&gt; -&lt;li&gt;Добавить в арифметические типы длинные числа и дроби;&lt;/li&gt; -&lt;li&gt;Сделать какую-нибудь логическую игру (крестики нолики, судоку или что-то похожее) с алгоритмическим выбором следующего хода и его вычислением с помощью машинного обучения;&lt;/li&gt; -&lt;li&gt;Написать еще больше разных примеров для оценки синтаксиса;&lt;/li&gt; -&lt;li&gt;Зафиксировать синтаксис с учетом полученного опыта и обратной связи;&lt;/li&gt; -&lt;li&gt;Восстановить работоспособность компилятора для генерации исполняемых файлов;&lt;/li&gt; -&lt;li&gt;Сделать очередную большую чистку кода;&lt;/li&gt; -&lt;li&gt;Переработать и задокументировать получившуюся семантику языка с учетом всех возможностей и выпустить первую полнофункциональную версию NewLang.&lt;/li&gt; -&lt;/ul&gt; - - </description> - </item> - - <item> - <title>Blog: Новый язык программирования</title> - <link>http://localhost:1313/blog/newlang/</link> - <pubDate>Fri, 18 Feb 2022 00:00:00 +0000</pubDate> - - <guid>http://localhost:1313/blog/newlang/</guid> - <description> - - - &lt;p&gt;&lt;img alt=&#34;КДПВ&#34; src=&#34;http://localhost:1313/blog/langs.jpeg&#34;&gt;&lt;/p&gt; - - -&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; -&lt;p&gt;Внимание!!!&lt;/p&gt; -&lt;p&gt;Данная статья содержит описание синтаксиса NewLnag предыдущей версии.&lt;/p&gt; -&lt;p&gt;Актуальную версию синтаксиса языка можно посмотреть &lt;a href=&#34;http://localhost:1313/docs/&#34;&gt;тут&lt;/a&gt;.&lt;/p&gt; - -&lt;/div&gt; - -&lt;p&gt;Более года назад я начал публикацию статей с описанием особенностей нового языка программирования. -С тех пор утекло много воды, было протестировано множество идей, в итоге несколько раз все поменялось кардинальным образом -и сейчас представляю на суд читателей описание предфинальной версии языка и его особенностей.&lt;/p&gt; -&lt;p&gt;Данная статья предназначена в первую очередь для проверки основных концепций нового языка программирования, а также для получения обратной связи от читателей Хабра. -Ведь согласно наблюдению &lt;a href=&#34;https://habr.com/post/539674/&#34;&gt;Хабр-ума палата&lt;/a&gt;, не замыленный взгляд со стороны очень сильно помогает в проработке новых идей.&lt;/p&gt; -&lt;p&gt;Этот проект очень долго был без собственного названия и в публикациях назывался просто и абстрактно &amp;ldquo;новый язык&amp;rdquo;. -Но после нескольких статей, временное название &amp;ldquo;новый язык&amp;rdquo; постепенно превратилось в имя собственное &lt;em&gt;NewLang&lt;/em&gt;, -которое я и решил в конечном итоге оставить (что еще раз подтверждает поговорку, что нет ничего более постоянного, чем что-то временное).&lt;/p&gt; -&lt;p&gt;&lt;strong&gt;NewLang&lt;/strong&gt; - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические конструкции -с декларативным программированием и тензорными вычислениями для задач машинного обучения.&lt;/p&gt; -&lt;p&gt;Основной особенностью языка является легкий, логичный и непротиворечивый синтаксис, который основан не на использовании зарезервированных ключевых слов, -а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка). -Основные свойства и особенности языка:&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Возможность работы как в режиме интерпретатора, так и компилятора.&lt;/li&gt; -&lt;li&gt;Динамическая и статическая типизация с возможностью указания типов в явном виде.&lt;/li&gt; -&lt;li&gt;Статическая типизация является условно строгой (автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных, например, целое число может быть автоматически преобразовано в вещественное, но не наоборот)&lt;/li&gt; -&lt;li&gt;Автоматическое управление памятью.&lt;/li&gt; -&lt;li&gt;ООП в виде явного наследования классов и &lt;a href=&#34;https://ru.wikipedia.org/wiki/%D0%A3%D1%82%D0%B8%D0%BD%D0%B0%D1%8F_%D1%82%D0%B8%D0%BF%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F&#34;&gt;утиная&lt;/a&gt; типизация.&lt;/li&gt; -&lt;li&gt;На уровне синтаксиса поддержка нескольких типов функций (обычные и &lt;a href=&#34;https://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D1%82%D0%BE%D1%82%D0%B0_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8&#34;&gt;чистые функции без побочных эффектов&lt;/a&gt;).&lt;/li&gt; -&lt;li&gt;Необязательные и именованные параметры функций.&lt;/li&gt; -&lt;li&gt;Возможны вставки кода на языке реализации (С/С++).&lt;/li&gt; -&lt;li&gt;Простая интеграция с уже существующими программными библиотеками (в том числе импорт нативных переменных и функций из С/С++).&lt;/li&gt; -&lt;li&gt;Имеется REPL &lt;a href=&#34;https://ru.wikipedia.org/wiki/REPL&#34;&gt;read-eval-print loop — «цикл: чтение — вычисление — вывод»&lt;/a&gt;.&lt;/li&gt; -&lt;/ul&gt; -&lt;h2 id=&#34;зачем-нужен-newlang&#34;&gt;Зачем нужен NewLang?&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b7%d0%b0%d1%87%d0%b5%d0%bc-%d0%bd%d1%83%d0%b6%d0%b5%d0%bd-newlang&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;У всех современных языков программирования происходит постоянное развитие (читай усложнение) синтаксиса по мере выхода новых версий. -Это является своего рода, платой за появление новых возможностей и воспринимается пользователями как естественное явление.&lt;/p&gt; -&lt;p&gt;Но одновременно является и серьезной проблемой, т.к. с выходом новых версий добавляются новые ключевые слова и синтаксические конструкции, -что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки -и трудоемкости поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.&lt;/p&gt; -&lt;p&gt;У NewLang сложность языковых конструкций естественно ограничена за счет разделения синтаксиса языка на две части, -что упрощает его изучение и использование. &lt;em&gt;Основной синтаксис&lt;/em&gt; — для написания программ в объектно-ориентированном (императивном) -и декларативном стилях, который основан не на зарезервированных ключевых словах, а на строгих грамматических правилах -и &lt;em&gt;Расширенный синтаксис&lt;/em&gt; — когда основного синтаксиса становится недостаточно, или требуется использовать языковую конструкцию языка реализации.&lt;/p&gt; -&lt;p&gt;Еще одно неудобство современных мейнстримовых языков, большинство из них были созданы до начала эпохи машинного обучения, -поэтому тензорные вычисления у них выполнены в виде отдельных библиотек, а не встроены в основной синтаксис языка и систему базовых типов. -У &lt;em&gt;NewLang&lt;/em&gt; тензорные вычисления доступны «из коробки» (используется библиотека &lt;a href=&#34;https://pytorch.org/&#34;&gt;libtorch&lt;/a&gt;), -а арифметические типы данных являются скалярами (тензорами нулевой размерности).&lt;/p&gt; -&lt;h3 id=&#34;основной-синтаксис&#34;&gt;Основной синтаксис&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d1%81%d0%bd%d0%be%d0%b2%d0%bd%d0%be%d0%b9-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Основной синтаксис &lt;em&gt;NewLang&lt;/em&gt; - простой и логичный за счет того, что он построен исключительно на грамматических правилах -и не использует каких либо зарезервированных ключевых слов, а все буквенно-символьные последовательности рассматриваются как идентификаторы -в которых можно использовать любые не-ASCII символы.&lt;/p&gt; -&lt;blockquote&gt; -&lt;p&gt;Идеализированная цель отказа от ключевых слов, приблизить чтение исходного текста программы к чтению обычного текста за счет использования знаков препинания при описании логики работы алгоритма.&lt;/p&gt; -&lt;/blockquote&gt; -&lt;blockquote&gt; -&lt;p&gt;Конечно &lt;em&gt;запятая&lt;/em&gt; человек может вычленять ключевые управляющие слова языка и &lt;em&gt;слеш&lt;/em&gt; или учитывать форматирование программы &lt;em&gt;запятая&lt;/em&gt; -чтобы на их основе понимать синтаксические конструкции &lt;em&gt;запятая&lt;/em&gt; хотя при обычном чтении мы привыкли опираться именно на семантику -знаков препинания &lt;em&gt;точка&lt;/em&gt; мы конечно можем писать знаки препинания и обычным текстом &lt;em&gt;точка&lt;/em&gt; но согласитесь &lt;em&gt;запятая&lt;/em&gt; что тогда -&lt;em&gt;открытая скобка&lt;/em&gt; например &lt;em&gt;запятая&lt;/em&gt; вот такой вот текст &lt;em&gt;закрытая скобка&lt;/em&gt; будет очень не удобно читать &lt;em&gt;точка&lt;/em&gt;&lt;/p&gt; -&lt;/blockquote&gt; -&lt;p&gt;Названия встроенных типов или имена служебных функций системной библиотеки определяются конкретной реализацией языка, -поэтому не являются зарезервированными ключевыми словами и при необходимости могут быть переопределены, например, -для создания собственного, предметно-ориентированного диалекта (&lt;a href=&#34;ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%B4%D0%BC%D0%B5%D1%82%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D1%8F%D0%B7%D1%8B%D0%BA&#34;&gt;DSL - domain-specific language&lt;/a&gt;), если в этом возникнет необходимость. -Но сама структура программы и логика выполняемого алгоритма все равно останутся понятны всем, кто знаком с правилами основного синтаксиса NewLang.&lt;/p&gt; -&lt;p&gt;&lt;strong&gt;Пример скрипта Hello world! на NewLang&lt;/strong&gt;&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;#!./nlc --eval &lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Определение функции hello&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; hello&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;str&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87&#34;&gt;printf&lt;/span&gt; :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @import&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;printf(format:Format, ...):Int&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Импорт стандартной C функции&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; printf&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;%s\n&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#000&#34;&gt;$str&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Вызов C функции с проверкой типов аргументов по строке формата&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; hello&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;Привет, мир!&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Вызвать функцию&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Вывод: Привет, мир!&lt;/p&gt; -&lt;h3 id=&#34;расширенный-синтаксис&#34;&gt;Расширенный синтаксис&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%80%d0%b0%d1%81%d1%88%d0%b8%d1%80%d0%b5%d0%bd%d0%bd%d1%8b%d0%b9-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Расширенный синтаксис — это возможность вставить в текст программы NewLang исходный код на языке реализации. -Сейчас это С/С++, что позволяет использовать любые возможности этого мощного языка программирования.&lt;/p&gt; -&lt;p&gt;Обработка расширенного синтаксиса происходит на этапе компиляции приложения, а взаимодействие между основным и расширенным синтаксисами происходит за счет совместного использования идентификаторов, -которое полностью прозрачно для пользователя и подчиняется единым грамматическим правилам основного синтаксиса.&lt;/p&gt; -&lt;h3 id=&#34;еще-немного-примеров&#34;&gt;Еще немного примеров:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b5%d1%89%d0%b5-%d0%bd%d0%b5%d0%bc%d0%bd%d0%be%d0%b3%d0%be-%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80%d0%be%d0%b2&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Любая последовательность вычислений возвращает результат выполнения последнего оператора. -Поэтому выполнение одной команды или последовательности команд всегда возвращает какой-либо результат, -а оператор возврата из функции необязателен, так как результатом будет значение последнего вычисленного выражения.&lt;/p&gt; -&lt;p&gt;&lt;strong&gt;Создание переменных&lt;/strong&gt;&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; scalar :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;42&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;42&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; tensor :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;1,2,3,4,5,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Тип тензора выводится автоматически&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;1, 2, 3, 4, 5,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;:Char -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; str :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;$1 string&amp;#39;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;$1&lt;/span&gt; string -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Арифметические операции&lt;/strong&gt;&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; tensor * &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;2&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;2, 4, 6, 8, 10,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;:Short -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; tensor * &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;20&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;20, 40, 60, 80, 100,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;:Short -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; tensor * 0.5 -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;0.5, 1, 1.5, 2, 2.5,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;:Double -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; tensor / &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Результат деления — число с плавающей точкой&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;0.5, 1, 1.5, 2, 2.5,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;:Double -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; tensor // &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Целочисленное деление без остатка&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;0, 1, 1, 2, 2,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;:Char&amp;lt;/source&amp;gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; tensor % &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Целочисленный остаток от деления&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;1, 0, 1, 0, 1,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;:Char&amp;lt;/source&amp;gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Строковые операции&lt;/strong&gt;&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;str&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;сцепеление строк &amp;#39;&lt;/span&gt; ++ str&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; сцепеление строк &lt;span style=&#34;color:#000&#34;&gt;$1&lt;/span&gt; string -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; str&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;строка как шаблон&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; сцепеление строк строка как шаблон string -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;преобразование-тензоров&#34;&gt;Преобразование тензоров&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b5%d0%be%d0%b1%d1%80%d0%b0%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d1%82%d0%b5%d0%bd%d0%b7%d0%be%d1%80%d0%be%d0%b2&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;В эпоху машинного обучения тензоры являются основными элементами вычислений, -поэтому для конвертирования &lt;em&gt;данных&lt;/em&gt; в тензоры используется отдельная синтаксическая конструкция, -состоящая из двойных квадратных скобок &lt;strong&gt;[[&lt;/strong&gt; &lt;em&gt;данные&lt;/em&gt; &lt;strong&gt;]]&lt;/strong&gt;. Подробнее про особенности преобразования типов можно прочитать далее.&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; tstr :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[[&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Тест&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]]&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Создать тензор из строки широких символов&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;1058, 1077, 1089, 1090,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;:Int -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; t2 :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[[&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Тест&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]]&lt;/span&gt;:Int&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;2,2&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Тоже самое, но тензор двухмерный&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;1058, 1077,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;, &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;1089, 1090,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;, -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;:Int&amp;lt;/source&amp;gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; StrWide&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;tstr&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Конвертировать тензор обратно в строку&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Тест -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Double&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;t2&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Изменить тип данных тезора&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;1058, 1077,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;, &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;1089, 1090,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;, -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;:Double -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; t3 :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[[&lt;/span&gt; t2 &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]]&lt;/span&gt;:Char&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;4&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Преобразовать тип данных тензора и его размерность&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;34, 53, 65, 66,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;:Char -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;синтаксис-newlang&#34;&gt;Синтаксис NewLang:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81-newlang&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;При разработке синтаксиса я старался придерживаться уже сложившихся правил, чтобы не создавать множественных смыслов, -зависящих от контекста. &lt;del&gt;И одновременно «объять необъятное»&lt;/del&gt;&lt;/p&gt; -&lt;h3 id=&#34;основы&#34;&gt;Основы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d1%81%d0%bd%d0%be%d0%b2%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;ul&gt; -&lt;li&gt;Операторы разделяются точкой с запятой «;».&lt;/li&gt; -&lt;li&gt;Отступы и переводы строк игнорируются (очень хотелось иметь возможность автоматического форматирование кода).&lt;/li&gt; -&lt;li&gt;Многострочные комментарии в исходном коде соответствуют стилю С/С++ и должны располагаться между символами /* и */. Вложенность многострочных комментариев не поддерживается.&lt;/li&gt; -&lt;li&gt;Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash.&lt;/li&gt; -&lt;li&gt;Последовательность выполняемых команд, которая должна выполняться как единое целое, заключается в фигурные скобки «{}».&lt;/li&gt; -&lt;li&gt;Программные вставки расширенного синтаксиса на языке реализации заключается в фигурные скобки со знаком процента &lt;strong&gt;%{&lt;/strong&gt; &lt;em&gt;/* тут может быть любой код на C/C++*/&lt;/em&gt; &lt;strong&gt;%}&lt;/strong&gt;.&lt;/li&gt; -&lt;/ul&gt; -&lt;h3 id=&#34;создания-объектов-и-присвоения-новых-значений&#34;&gt;Создания объектов и присвоения новых значений&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%be%d0%b7%d0%b4%d0%b0%d0%bd%d0%b8%d1%8f-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%be%d0%b2-%d0%b8-%d0%bf%d1%80%d0%b8%d1%81%d0%b2%d0%be%d0%b5%d0%bd%d0%b8%d1%8f-%d0%bd%d0%be%d0%b2%d1%8b%d1%85-%d0%b7%d0%bd%d0%b0%d1%87%d0%b5%d0%bd%d0%b8%d0%b9&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Для создания объектов и присвоения им новых значений в NewLang используется сразу три разных оператора.&lt;br&gt; -Оператор «&lt;strong&gt;::=&lt;/strong&gt;» используется только для создания новых объектов, а если объект с таким именем уже существует, то генерируется ошибка.&lt;br&gt; -Оператор «&lt;strong&gt;:=&lt;/strong&gt;» используется для тех же целей, но если объект с таким именем уже существует, то ошибки не происходит, -а новое значение присваивается уже существующему объекту.&lt;br&gt; -И последний оператор «&lt;strong&gt;=&lt;/strong&gt;» применяется только для присвоения значения уже существующим объектам, и если объект с указанным именем отсутствует, то тоже происходит ошибка.&lt;/p&gt; -&lt;p&gt;Использование трех разных операторов для создания/изменения объектов позволяет более гибко контролировать подобные операции и выявлять логические ошибки в коде на более раннем этапе.&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;::=&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1.0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;#&lt;/span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;Создать&lt;/span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;новую&lt;/span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;переменную&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;без&lt;/span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;указания&lt;/span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;типа&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;100&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;#&lt;/span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;Присвоить&lt;/span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;новое&lt;/span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;значение&lt;/span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;уже&lt;/span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;существующей&lt;/span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;переменной&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#f57900&#34;&gt;printf&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;import&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;printf&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#f57900&#34;&gt;format&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Format&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;...)&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;/* Создать новый или переопределить -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt; объект printf, который будет результатом выполнения глобальной функции @import */&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;идентификаторы-объектов-и-модификаторы&#34;&gt;Идентификаторы объектов и модификаторы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b8%d0%b4%d0%b5%d0%bd%d1%82%d0%b8%d1%84%d0%b8%d0%ba%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d0%be%d0%b1%d1%8a%d0%b5%d0%ba%d1%82%d0%be%d0%b2-%d0%b8-%d0%bc%d0%be%d0%b4%d0%b8%d1%84%d0%b8%d0%ba%d0%b0%d1%82%d0%be%d1%80%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;В качестве идентификаторов можно использовать буквы, цифры и знаки подчеркивания в любых комбинациях, при условии, -что первый символ идентификатора не является цифрой.&lt;/p&gt; -&lt;p&gt;В NewLang существует возможность указания области видимости и времени жизни объекта с помощью модификатора — специального символа перед -именем переменной. Это может показаться немного похожим на венгерскую нотацию, но в отличие от нее, -модификатор не имеет отношения к типу объекта и не является частью имени идентификатора. -К тому же в качестве модификаторов используется строго определённые символы, назначение которых определено заранее.&lt;/p&gt; -&lt;p&gt;Так, символ «&lt;strong&gt;$&lt;/strong&gt;» в начале имени обозначает локальную переменную, время жизни которой ограничено текущей областью видимости и при её завершении локальная переменная уничтожается. -Символ «&lt;strong&gt;@&lt;/strong&gt;» обозначает глобальную переменную, а сам объект сохраняет свое состояние даже после выхода из текущей области видимости. -Так же обозначаются и имена типов данных, например, при создания новых типов, а в качестве модификатора используется символа двоеточия «&lt;strong&gt;:&lt;/strong&gt;»&lt;/p&gt; -&lt;p&gt;Семантика обращения к аргументам функций очень похоже на работу с аргументами в bash скриптах, где &lt;strong&gt;$1&lt;/strong&gt; или &lt;strong&gt;$arg&lt;/strong&gt; — порядковый номер -или имя аргумента (происходит обращение к локальным переменным в текущей области видимости).&lt;/p&gt; -&lt;p&gt;Использование модификаторов является обязательным только в двух случаях: -- При создании нового типа данных, так как типы всегда создаются в глобальной области видимости, а их символьные имена должны быть уникальными -- При обращении к объектам NewLang внутри программных вставок кода на языке реализации, так как они используется как маркеры при поиске идентификаторов NewLang в коде С/С++.&lt;/p&gt; -&lt;p&gt;В остальных случаях, для обращения к переменным указывать их модификаторы не обязательно. -И если при обращении к объекту модификатор не указан, то сперва ищется локальная переменная, а потом глобальная с таким же именем. -Причем, локальная переменная будет перекрывать глобальную.&lt;/p&gt; -&lt;p&gt;Так же следует иметь в виду, что компилятор может генерировать код для прямого обращения к локальным объектам уже на этапе компиляции, -тогда как для обращения к глобальным объектам, или если модификатор области видимости отсутствует, компилятор вынужден каждый раз встраивать runtime вызов функции поиска объекта в таблице символов.&lt;/p&gt; -&lt;h2 id=&#34;система-типов&#34;&gt;Система типов&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0-%d1%82%d0%b8%d0%bf%d0%be%d0%b2&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Так как система типов языка динамическая, то явное указание типа не влияет на размер переменной и является только своего рода логическим ограничением на возможность присвоения переменной значения другого типа.&lt;/p&gt; -&lt;p&gt;Информация о типах используется при проверке их совместимости, когда существующему объекту присваивается значение другого типа. -Такая операция возможна только когда типы совместимы между собой и допускают автоматическое приведение. -Это справедливо как во время парсинга/компиляции исходного теста, так и во время выполнения в режимах интерпретатора и/или скомпилированного файла.&lt;/p&gt; -&lt;h3 id=&#34;арифметические-типы&#34;&gt;Арифметические типы:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b0%d1%80%d0%b8%d1%84%d0%bc%d0%b5%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Арифметические типы данных являются тензорами - массивами чисел одного типа с произвольным количеством измерений и одинаковым размером столбцов в каждом. -Единичное число тоже тензор нулевого размера.&lt;/p&gt; -&lt;p&gt;Поддерживаются только знаковые целые числа, т.к. в беззнаковых числах особая нужда отсутствует, а проблем с ними можно найти очень много на ровном месте.&lt;/p&gt; -&lt;p&gt;&lt;strong&gt;Проблемы беззнаковых чисел (из интернета)&lt;/strong&gt;&lt;/p&gt; -&lt;blockquote&gt; -&lt;p&gt;Во-первых, вычитание двух беззнаковых чисел, например 3 и 5. 3 минус 5 равно 4294967294, -т.к. -2 не может быть представлено как беззнаковое число. Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных -значений со знаком и без знака. С++ может свободно преобразовывать числа со знаком и без знака, -но не проверяет диапазон, чтобы убедиться, что вы не переполняете свой тип данных.&lt;/p&gt; -&lt;p&gt;В C++ всё же есть несколько случаев, когда можно (или необходимо) использовать беззнаковые числа. -Во-первых, числа без знака предпочтительнее при работе с битами. Во-вторых, использование беззнаковых чисел связаных с индексацией массивов.&lt;/p&gt; -&lt;/blockquote&gt; -&lt;p&gt;Но это мой случай, так как индекс может быть отрицательным и даже не числом, а диапазоном или многоточием. -З.Ы. И даже зная об этом, все равно умудрился недавно словить баг с отрицательными индексами у словарей!&lt;/p&gt; -&lt;p&gt;Имена встроенных арифметических типов говорят сами за себя: Char, Short, Int, Long, Float, Double, ComplexFloat, ComplexDouble. -Отдельным типом идет логический тип Bool, который может принимать значения только 0 или 1 (false/true соответственно), -и в зависимости от выполняемой операции может быть отнесен к целочисленным типам, так и не входить в их состав.&lt;/p&gt; -&lt;p&gt;&lt;em&gt;(данный подход интерпретации логического типа данных был взят из библиотеки Torch)&lt;/em&gt;&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// Treat bool as a distinct &amp;#34;category,&amp;#34; to be consistent with type promotion -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// rules (e.g. `bool_tensor + 5 -&amp;gt; int64_tensor`). If `5` was in the same -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// category as `bool_tensor`, we would not promote. Differing categories -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// implies `bool_tensor += 5` is disallowed. -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// NB: numpy distinguishes &amp;#34;unsigned&amp;#34; as a category to get the desired -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// `bool_tensor + 5 -&amp;gt; int64_tensor` behavior. We don&amp;#39;t, because: -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// * We don&amp;#39;t want the performance hit of checking the runtime sign of Scalars. -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;// * `uint8_tensor + 5 -&amp;gt; int64_tensor` would be undesirable. -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;В будущем планируется добавить классы чисел для длинной арифметики и дробей, для чего зарезервированы названия типов BigNum, Currency и Fraction.&lt;/p&gt; -&lt;p&gt;Доступ к элементам тензора происходит по целочисленному индексу, который начинается с 0. -Для многомерного тензора, индексы элемента перечисляются в квадратных скобках через запятую. -Поддерживается доступ к элементам через отрицательный индекс, который обрабатывается точно так же, -как в Python (-1 последний элемент, -2 предпоследний и т.д.).&lt;/p&gt; -&lt;p&gt;Литерал тензор в тексте программы записывается в квадратных скобках с обязательной завершающей запятой, т.е. [1, 2,] - это литерал одномерный тензор из двух чисел. -После закрывающей скобки тип тензора может быть указан в явном виде. Если тип не указан, то он выводится автоматически на основании указанных данных и выбирается минимально возможный байтовый размер, -который позволяет сохранить все значения без потери точности.&lt;/p&gt; -&lt;p&gt;Примеры:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;$var_char&lt;/span&gt; :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; 123&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Тип Char выводится автоматически&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;$var_short&lt;/span&gt; :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; 1000&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Тип Short выводится автоматически&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;$var_bool&lt;/span&gt; :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;0, 1, 0, 1,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Тензор из 4 элементов. Тип Bool выводится автоматически&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;$tensor&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;10,10&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;:Int :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; 1&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Тензор Int размером 2x2 инициализированный 1&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;$scalar&lt;/span&gt; :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;$tensor&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;5,5&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Присвоить скаляру значение указанного элемента тензора&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;строковые-типы-данных&#34;&gt;Строковые типы данных:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d1%82%d1%80%d0%be%d0%ba%d0%be%d0%b2%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Поддерживаются два типа строк, StrWide - символьные (широкие) и StrChar — байтовые. Различия между ними заключается в типе единичного элемента. -У символьных строк единичным элементом является широкий символ wchar_t, а у байтовой строки единичным элементом является один байт (точнее char, т. е. байт со знаком). -Символьные строки литералы в исходном тексте записывается в «двойных кавычках», а байтовые строки в &amp;lsquo;одинарных кавычках&amp;rsquo;.&lt;/p&gt; -&lt;p&gt;Количество элементов символьной строки возвращается в широких символах, а размер байтовой строки в байтах, поэтому и обращение к элементу строки по индексу происходит соответственно либо к символу, либо к байту.&lt;/p&gt; -&lt;p&gt;Важный момент. К любой переменной можно обратиться так же, как к функции (записав после её имени круглые скобки). -Результатом этой операции будет создание копии/клона объекта. Причем некоторые типы (словари, классы и символьные строки) можно использовать в качестве шаблона -при создании копии объекта с модифицированными свойствами, если новые и/или изменяемые значения указать в скобках, как аргументы при вызовах функций. -Так, если при создании копии в скобках указать набор новых данных, то результирующая копия будет содержать уже измененные данные.&lt;/p&gt; -&lt;p&gt;Например:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;$template&lt;/span&gt; :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;${&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$1&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Обычная строка&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;$result&lt;/span&gt; :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;$template&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;шаблон&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#000&#34;&gt;name&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Строка&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# result = &amp;#34;Строка шаблон&amp;#34;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;составные-типы-данных&#34;&gt;Составные типы данных:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%be%d1%81%d1%82%d0%b0%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;h4 id=&#34;словарь&#34;&gt;Словарь&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%bb%d0%be%d0%b2%d0%b0%d1%80%d1%8c&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h4&gt; -&lt;p&gt;Словарь — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии -(он похож и на tuple и на структуру одновременно). Словари от тензоров отличаются тем, что являются только одномерными массивами, -но каждый элемент может содержать произвольное количество элементов любого типа, в том числе и другие словари.&lt;/p&gt; -&lt;p&gt;Доступ к элементам словарей происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. -Индекс также начинается с 0 и как у тензоров, тоже может быть отрицательным.&lt;/p&gt; -&lt;p&gt;Литерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, -т.е. (,) - пустой словарь, (1, 2= «2», name=3,).&lt;/p&gt; -&lt;h3 id=&#34;перечисление&#34;&gt;Перечисление&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d0%b5%d1%80%d0%b5%d1%87%d0%b8%d1%81%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Перечисление - это не отдельный тип данных, а обычный словарь, у которого все элементы имеют уникальные имена и целочисленные значение, -которое явно указывается при определении или вычисляется автоматически (на единицу больше предыдущего элемента). -У перечислений тип значения указывается сразу после закрывающей скобки через двоеточие (ONE=1, TWO=, THREE=): Int.&lt;/p&gt; -&lt;h4 id=&#34;классы&#34;&gt;Классы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%ba%d0%bb%d0%b0%d1%81%d1%81%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h4&gt; -&lt;p&gt;Класс (реализовано частично) - тип данных, с помощью которого реализуется один из принципов ООП - наследование. -При создании экземпляра класса создается новая переменная, у которой сохраняется информацию о своем родителе -и которая наследует от него свойства и методы. Тип данных «класс» аналогичен словарю, -но все свойства обязаны иметь имена (хотя доступ к свойствам класса по индексу так же возможен). -Литерал с типом «Класс» в тексте программы записывается в круглых скобках без завершающей запятой, т. е. () - пустой класс, (1, 2= «2», name=3).&lt;/p&gt; -&lt;p&gt;Пока остальные детали классов до конца не реализованы, поэтому описывать их не буду, т. к. в итоговом варианте синтаксис классов и определения их методов могут поменяться.&lt;/p&gt; -&lt;h3 id=&#34;функции&#34;&gt;Функции&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Синтаксис NewLang поддерживать несколько типов функций (а в будущем и методов классов): обычные функции, чистые функции и простые чистые функции.&lt;/p&gt; -&lt;p&gt;Для всех типов функций поддерживаются аргументы по умолчанию. При создании функции, её аргументы указываются как в Питоне, -т.е. вначале идут обязательные аргументы, потом аргументы со значениями по умолчанию, -где имя аргумента отделяется от его значения по умолчанию знаком равно «=». -Если функция допускает обработку произвольного количества аргументов, то последним в списке параметров указывается многоточие.&lt;/p&gt; -&lt;h4 id=&#34;обычная-функция&#34;&gt;Обычная функция&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%b1%d1%8b%d1%87%d0%bd%d0%b0%d1%8f-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h4&gt; -&lt;p&gt;Обычная функция — такие функции являются именно обычными функциями в понимании С/С++. -Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д.&lt;/p&gt; -&lt;p&gt;Внутри обычной функции можно обращаться к локальным и глобальным объектам, и они могут содержаться вставки на языке реализации, например, для вызова функций из внешних библиотек.&lt;/p&gt; -&lt;p&gt;Вставки на языке реализации оформляются в виде &lt;strong&gt;%{&lt;/strong&gt; &lt;strong&gt;%}&lt;/strong&gt; и могут содержать любой текст на С/С++, -а прямо из него можно обращаться к локальным и глобальным объектам NewLang так же, как и в обычном синтаксисе, -указывая первым символом имени соответствующий модификатор (&lt;strong&gt;$&lt;/strong&gt; для локальных объектов и &lt;strong&gt;@&lt;/strong&gt; для глобальных).&lt;/p&gt; -&lt;p&gt;Технически, такая программная вставка просто переносится трансплайтером непосредственно в исходный текст генерируемого файла, -а все идентификаторы NewLang специальным образом декорируются (добавляются специальные маркеры для их идентификации), -после этого исходный текст подается на вход обычному компилятору С++. -Для локальных объектов трансплайтер может генерировать код для прямого доступа к объекту на этапе компиляции, -а для работы с глобальными объектами вынужден использовать runtime вызовы функции поиска в таблице символов.&lt;/p&gt; -&lt;p&gt;Например:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;print&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;str&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;printf&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;%s&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;static_cast&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;*&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;str&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;));&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;/* Прямой вызов С функции */&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;чистые-функции&#34;&gt;Чистые функции&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%87%d0%b8%d1%81%d1%82%d1%8b%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h4&gt; -&lt;p&gt;Чистая функция - это тоже обычная функция, только в том смысле, какой в него вкладывает функциональное программирование. -Создания чистой функции происходит с помощью оператора «:-». У чистой функции отсутствует доступ к контексту и глобальным объектам, -поэтому она может обрабатывать только те данные, которые были ей переданы в качестве аргументов.&lt;/p&gt; -&lt;p&gt;Программные вставки на языке реализации внутри чистых функций не запрещены и могут использоваться, например, для отладки. -Но делается это на страх и риск разработчика. Именно он отвечает за их «чистоту», например при вызове функций из внешних библиотек.&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Sum&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;arg1, arg2&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; :- &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$arg1&lt;/span&gt;+&lt;span style=&#34;color:#000&#34;&gt;$arg2&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Вернуть сумму аргументов&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Так как в языке отсутствует оператор возврата данных из текущего блока выполнения (аналог оператора return &amp;lt;данные&amp;gt;), -то возвращаемым значением функции / блока кода всегда является результат выполнения последней операции.&lt;/p&gt; -&lt;h4 id=&#34;простые-чистые-функции&#34;&gt;Простые чистые функции&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%be%d1%81%d1%82%d1%8b%d0%b5-%d1%87%d0%b8%d1%81%d1%82%d1%8b%d0%b5-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h4&gt; -&lt;p&gt;Простые чистые функции — отдельный класс чистых функций, которые предназначены только для вычисления логического результата -(т.е. они являются предикатами) и их отличает упрощенная формой записи. -Тело простой чистой функции состоит из последовательности операторов, которые разделяются запятыми и заканчиваются, -как и любое выражение, точкой с запятой. Все операторы простой чистой функции всегда приводятся к булевому значению, -а итоговый результат функции вычисляется по одной из возможных логических операций: &lt;em&gt;И&lt;/em&gt;, &lt;em&gt;ИЛИ&lt;/em&gt; и &lt;em&gt;исключающее ИЛИ&lt;/em&gt;.&lt;/p&gt; -&lt;p&gt;Например:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; func_and&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;arg1, arg2&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;=&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;arg1&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;==&lt;/span&gt;3, arg2 &amp;gt; 0&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Простая чистая функция Логическое И&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; func_or&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;arg1, arg2&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;||=&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;arg1&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;==&lt;/span&gt;3, arg2 &amp;gt; 0&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Простая чистая функция Логическое ИЛИ&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; func_xor&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;arg1, arg2&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; ^^&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;arg1&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;==&lt;/span&gt;3, arg2 &amp;gt; 0&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Простая чистая функция Исключающее ИЛИ&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;специальные-типы-данных&#34;&gt;Специальные типы данных:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%bf%d0%b5%d1%86%d0%b8%d0%b0%d0%bb%d1%8c%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;h4 id=&#34;none&#34;&gt;None&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#none&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h4&gt; -&lt;p&gt;None (пустой тип) — не содержит значения (точнее имеет одно значение None) и совместим с любым другим типом данных. -Указывается в тексте программы как один подчерк «_». Значение None имеют не инициализированные переменные -и при попытке чтения из такой переменной возникает ошибка.&lt;/p&gt; -&lt;p&gt;Тип переменной может быть явно указан или выведен автоматически из присваиваемого значения. -Присвоить новое значение уже инициализированной переменной можно только для совместимого типа, так как неявное преобразование типов не допускаются.&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;$var&lt;/span&gt; :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; _&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Создать переменную со значением None&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;$var2&lt;/span&gt; :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; var&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Ошибка!!! Нельзя прочитать неинициализированную переменную var&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;$var&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; 1000&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# У переменной будет тип Short (минимальный размер для хранения значения)&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;$var&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; 0,5&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Ошибка!!! Short ← Float не совместимы&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;$var&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; _&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Очистить значение переменной&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;$var&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; 0,5&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Теперь можно, т. к. None совместим с любым типом&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;диапазон-range&#34;&gt;Диапазон (Range)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b4%d0%b8%d0%b0%d0%bf%d0%b0%d0%b7%d0%be%d0%bd-range&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h4&gt; -&lt;p&gt;Диапазон (реализовано частично) — специальный тип данных, являющейся приблизительным аналогом типа «генератор» в Python. -К диапазону можно обращаться как к итератору и он будет поочередно выдавать элементы в указанном интервале с заданным шагом. -Диапазон в тексте программы указывается как два или три элемента через две точки, например 1..5 — диапазон от единицы до пяти с шагом по умолчанию 1. -В качестве параметров диапазона можно указывать не только литералы, но и имена переменных. -Например, 0,1..&lt;em&gt;$stop&lt;/em&gt;..0,1 — диапазон от значения 0,1 до значения, указанного в переменной &lt;em&gt;$stop&lt;/em&gt; с шагом 0,1.&lt;/p&gt; -&lt;p&gt;Диапазон для целых чисел можно использовать в качестве индекса у тензоров (точнее, у любых объектов, которые допускают доступ к своим элементам по индексу, -т.е. тензоры, словари и текстовые строки). Фактический, это поведение аналогично slice в языке Python и array[1:5] -в Python означает тоже самое, что и array[1..5] в NewLang.&lt;/p&gt; -&lt;p&gt;В качестве индекса у тензоров еще можно указать произвольное количество измерений с помощью многоточия, т.е.&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;$tensor&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;…, 0&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; 0&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Обнулить все первые элементы в каждом измерении.&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;итераторы&#34;&gt;Итераторы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b8%d1%82%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h4&gt; -&lt;p&gt;Итераторы (в разработке) - самый сложный и неоднозначный тип данных для работы с элементами коллекций.&lt;br&gt; -Для работы с итераторами зарезервированы символы &amp;ldquo;!&amp;rdquo; и &amp;ldquo;?&amp;rdquo;, но сами итераторы пока не реализованы.&lt;/p&gt; -&lt;h3 id=&#34;преобразование-типов&#34;&gt;Преобразование типов&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b5%d0%be%d0%b1%d1%80%d0%b0%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d1%82%d0%b8%d0%bf%d0%be%d0%b2&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;h4 id=&#34;явное-приведение-типов&#34;&gt;Явное приведение типов&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%8f%d0%b2%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%b8%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5-%d1%82%d0%b8%d0%bf%d0%be%d0%b2&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h4&gt; -&lt;p&gt;Несмотря на динамическую типизацию языка, если тип переменной указан явно, то автоматическое приведение типов не выполняется, -и чтобы присвоить переменой значение не совместимого типа, требуется явное преобразование.&lt;/p&gt; -&lt;p&gt;Так как символьные названия типов относятся к деталям реализации, то явное преобразование в конкретный тип данных производится с помощью вызова функции с системным именем, -т. е. Bool(), StrWide(), Long и т. д. Причем у тензоров при таком преобразовании изменяется только тип данных, но размерность тензора не меняется.&lt;/p&gt; -&lt;p&gt;Для преобразования любого типа данных в строку ещё можно использовать оператор конкатенации строк, которой преобразует любой тип данных в строковое представление. -Но так как строковых типов два (байтовые и широкие строки), то тип строки определяется первым аргументом в операторе конкатенации, т. е.&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt; ++ &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;123&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# &amp;#34;123&amp;#34; - Строка широких символов&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt; ++ &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;123&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# &amp;#39;123&amp;#39; - Байтовая строка&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;Или преобразовать любое значение в строковое с помощью строки-шаблона: -&lt;/code&gt;&lt;/pre&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; val :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; 12345&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$1&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;val&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Будет строка &amp;#34;12345&amp;#34;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;tensor-comprehensions&#34;&gt;Tensor comprehensions&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#tensor-comprehensions&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h4&gt; -&lt;p&gt;В эпоху машинного обучения тензоры являются основным элементом вычислений, поэтому для конвертирования &lt;em&gt;данных&lt;/em&gt; в тензоры используется отдельная синтаксическая конструкция, -состоящая из двойных квадратных скобок &lt;strong&gt;[[&lt;/strong&gt; &lt;em&gt;данные&lt;/em&gt; &lt;strong&gt;]]&lt;/strong&gt;. Фактически это оператор и функция времени выполнения в зависимости от указанных между двойные квадратными скобками выражения.&lt;/p&gt; -&lt;p&gt;Чтобы преобразовать любую переменную в тензор (с учетом допустимости такого преобразования), её достаточно указать между двойными квадратными скобками. -Выражение &lt;strong&gt;[[&lt;/strong&gt; &lt;em&gt;varibale&lt;/em&gt; &lt;strong&gt;]]&lt;/strong&gt; - преобразует переменную &lt;em&gt;varibale&lt;/em&gt; в одномерный тензор с автоматическим выводом типа данных. -Для преобразования в одномерный тензор конкретного типа используется выражение &lt;strong&gt;[[&lt;/strong&gt; &lt;em&gt;varibale&lt;/em&gt; &lt;strong&gt;]]&lt;/strong&gt;:&lt;em&gt;Type&lt;/em&gt;, где _Type- - любой из арифметических типов.&lt;/p&gt; -&lt;p&gt;Если требуется преобразовать переменную не в одномерный тензор, а в тензор конкретного типа и заданной размерности, -то это делается выражением [[ varibale ]]:Type[2,2], которая вернет тензор с размерностью 2х2 и типом Type у элементов.&lt;/p&gt; -&lt;p&gt;Внутри двойных квадратных скобок может быть не только любое выражение, но и литерал или диапазон. -В этом случае, они также раскрываются в тензор по таким же правилам.&lt;br&gt; -В будущем планирую добавить возможность указания сразу нескольких значений через запятую для их объединения в один тензор.&lt;/p&gt; -&lt;p&gt;Примеры:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[[(&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)]]&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Тензор из словаря&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,]:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Char&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[[&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;first second&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]]&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Байтовая строка в тензор&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;102&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;105&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;114&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;115&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;116&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;32&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;115&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;101&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;99&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;111&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;110&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;100&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,]:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Char&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[[(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;first&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;first&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;space&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;32&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;second&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#39;second&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)]]&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Получаем тензор из словаря с такими же данными&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;102&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;105&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;114&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;115&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;116&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;32&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;115&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;101&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;99&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;111&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;110&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;100&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,]:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Char&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[[&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]]:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Double&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;10&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Тензор заданного формата с нулями&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,],&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,],&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,],&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,],&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,],&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,],&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,],&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,],&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,],&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,],&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Double&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[[&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;rand&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]]:&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;Int&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Тензор со случайными данными&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1804289383&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;846930886&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,],&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1681692777&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1714636915&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,],&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1957747793&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;424238335&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,],&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[[&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0..10&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]]:&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;Int&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;5&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Тензор из диапзона&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,],&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,],&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;4&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;5&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,],&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;6&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;7&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,],&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;8&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;9&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,],&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[[&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0..0.99&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;.0.1&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]]&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Или даже так&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0.1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0.2&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0.3&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0.4&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0.5&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0.6&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0.7&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0.8&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;0.9&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,]:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Double&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;source&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;операторы-и-управляющие-конструкции&#34;&gt;Операторы и управляющие конструкции&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d0%b8-%d1%83%d0%bf%d1%80%d0%b0%d0%b2%d0%bb%d1%8f%d1%8e%d1%89%d0%b8%d0%b5-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%86%d0%b8%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h4 id=&#34;операторы&#34;&gt;Операторы:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h4&gt; -&lt;p&gt;Все операторы имеют парный оператор с присвоением значения.&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;&lt;strong&gt;+&lt;/strong&gt; и += сложение арифметических типов данных&lt;/li&gt; -&lt;li&gt; -&lt;ul&gt; -&lt;li&gt;и -= вычитание арифметических типов данных&lt;/li&gt; -&lt;/ul&gt; -&lt;/li&gt; -&lt;li&gt;/ и /= деление (результат число с плавающей точкой)&lt;/li&gt; -&lt;li&gt;// и //= целочисленное деление с округлением к меньшему числу (как в Python)&lt;/li&gt; -&lt;li&gt; -&lt;ul&gt; -&lt;li&gt;и *= умножение&lt;/li&gt; -&lt;/ul&gt; -&lt;/li&gt; -&lt;li&gt;** и **= возведение в степень (он же используется и для повторения текстовых строк)&lt;/li&gt; -&lt;li&gt;++ и ++= конкатенация строк с автоматическим приведением аргументов к стоковому типу (символ инкремента специально используется вместо одиночного плюса для того, чтобы в явном виде разделить конкатенацию строк и операторы арифметического сложения)&lt;/li&gt; -&lt;/ul&gt; -&lt;h4 id=&#34;операторы-сравнения&#34;&gt;Операторы сравнения:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d1%81%d1%80%d0%b0%d0%b2%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h4&gt; -&lt;ul&gt; -&lt;li&gt;&amp;lt;, &amp;gt;, &amp;lt;=, &amp;gt;= классические для сравнения скаляров&lt;/li&gt; -&lt;li&gt;==, != операторы сравнения с автоматическим приведением совместимых типов для любых объектов&lt;/li&gt; -&lt;li&gt;===, !== оператор точного сравнения для любых объектов (автоматического приведения типов не выполняется)s&lt;/li&gt; -&lt;/ul&gt; -&lt;h3 id=&#34;проверки-типов--в-разработке&#34;&gt;Проверки типов (в разработке):&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b8-%d1%82%d0%b8%d0%bf%d0%be%d0%b2--%d0%b2-%d1%80%d0%b0%d0%b7%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Проверка имени класса «~» - немного похож на оператор instanceof в Java. -Левым оператором должен быть проверяемый объект, а правым оператором - название типа, строка литерал или объект строкового типа с именем класса. -Результатом операции будет истина, если правый операнд содержит название класса проверяемого объекта или он присутствует в иерархии наследования у проверяемого класса.&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; name :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;class&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Строка с именем класса&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; var ~ :class&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; var ~ &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;class&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; var ~ name&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;field1&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;«value», &lt;span style=&#34;color:#000&#34;&gt;field2&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;2, &lt;span style=&#34;color:#000&#34;&gt;field3&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;«33»,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; ~~ &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Истина (т. е. левый операнд словарь)&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;field1&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;«value», &lt;span style=&#34;color:#000&#34;&gt;field2&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;2, &lt;span style=&#34;color:#000&#34;&gt;field3&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;«33»,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; ~~ &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;field1&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;_&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Тоже истина (т. к. поле field1 присутствует у левого операнда)&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Утиная типизация «~~» - приблизительный аналог функции isinstance() в Python, который для простых типов сравнивает совместимость типа левого операнда по отношению к правому, а для словарей и классов в левом операнде проверяется наличие всех имен полей, присутствующих у правого операнда. т. е.&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;field1&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;«value», &lt;span style=&#34;color:#000&#34;&gt;field2&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;2, &lt;span style=&#34;color:#000&#34;&gt;field3&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;«33»,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; ~~ &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Истина (т. е. левый операнд словарь)&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;field1&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;«value», &lt;span style=&#34;color:#000&#34;&gt;field2&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;2, &lt;span style=&#34;color:#000&#34;&gt;field3&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;«33»,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; ~~ &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;field1&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;_&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Тоже истина (т. к. поле field1 присутствует у левого операнда)&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Строгая утиная типизация «~~~» - для простых типов сравнивается идентичности типов без учета совместимости, -а для составных типов происходит строгое сравнение всех свойств. Для данной операции, пустой тип совместим только с другим пустим типом!&lt;/p&gt; -&lt;h2 id=&#34;управляющие-конструкции-в-разработке&#34;&gt;Управляющие конструкции (в разработке)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%83%d0%bf%d1%80%d0%b0%d0%b2%d0%bb%d1%8f%d1%8e%d1%89%d0%b8%d0%b5-%d0%ba%d0%be%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%86%d0%b8%d0%b8-%d0%b2-%d1%80%d0%b0%d0%b7%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h3 id=&#34;условный-оператор&#34;&gt;Условный оператор&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%83%d1%81%d0%bb%d0%be%d0%b2%d0%bd%d1%8b%d0%b9-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;В качестве оператора проверки условия используется синтаксическая конструкция, соответствующая по смыслу термину «следует», -т.е. тире и угловая скобка «-&amp;gt;». Такая запись условного оператора очень похожа на математическую и легко объединяется в последовательности для проверки множественных условий вида «else if».&lt;/p&gt; -&lt;p&gt;В общем случае условный оператор имеет вид:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; условие -&amp;gt; действие&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; или -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;условие&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt;действие&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; или -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;условие1 &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;||&lt;/span&gt; условие2&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt;действие&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt;действие иначе&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Или расширенный вариант «else if», для наглядности записанный с отступами:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;условие1&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt;действие1&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;условие2&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt;действие2&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;условие3&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt;действие3&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&amp;gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt;действие_иначе&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;операторы-циклов-в-планах&#34;&gt;Операторы циклов (в планах)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d1%86%d0%b8%d0%ba%d0%bb%d0%be%d0%b2-%d0%b2-%d0%bf%d0%bb%d0%b0%d0%bd%d0%b0%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;&lt;em&gt;Операторы циклов пока в разработке , т. к. плотно связаны с итераторами.&lt;/em&gt;&lt;/p&gt; -&lt;p&gt;Пока планирую для циклов использовать конструкции: (условие) &lt;strong&gt;&amp;lt;&amp;ndash;&amp;gt;&lt;/strong&gt; {тело цикла};&lt;/p&gt; -&lt;p&gt;Или так: (условие) &lt;strong&gt;-&amp;raquo;&lt;/strong&gt; {тело цикла};&lt;/p&gt; -&lt;p&gt;И хотя синтаксис мне не очень нравится, но я решил пока не ломать над этим голову и планирую попробовать несколько вариантов оформления циклов.&lt;/p&gt; -&lt;h4 id=&#34;операторы-прерывания-потока-выполнения-команд-реализовано-частично&#34;&gt;Операторы прерывания потока выполнения команд (реализовано частично)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b-%d0%bf%d1%80%d0%b5%d1%80%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%bf%d0%be%d1%82%d0%be%d0%ba%d0%b0-%d0%b2%d1%8b%d0%bf%d0%be%d0%bb%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%ba%d0%be%d0%bc%d0%b0%d0%bd%d0%b4-%d1%80%d0%b5%d0%b0%d0%bb%d0%b8%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%be-%d1%87%d0%b0%d1%81%d1%82%d0%b8%d1%87%d0%bd%d0%be&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h4&gt; -&lt;p&gt;Оператором прерывания потока выполнения команд и возврата из текущей функции, т.е. самым близким аналогом оператора return&lt;br&gt; -является оператор два символа минус «&amp;ndash;». Но в отличие от классического return, оператор возврата не возвращает значения, -т.к. значение из любой функции или блока кода возвращается всегда и им является результат выполнения самой последней операции -(или None, если такая операция отсутствует).&lt;/p&gt; -&lt;p&gt;Пока не придумал, как оформлять оператор прерывания потока выполнения в случае ошибки (при его выполнении будет происходить генерация исключения), -поэтому, если будут предложения, пишите в комментариях к статье (и про оформление циклов тоже).&lt;/p&gt; -&lt;h3 id=&#34;обработка-ошибок-в-планах&#34;&gt;Обработка ошибок (в планах)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%b1%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b0-%d0%be%d1%88%d0%b8%d0%b1%d0%be%d0%ba-%d0%b2-%d0%bf%d0%bb%d0%b0%d0%bd%d0%b0%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;В самом начале работ я ориентировался на классический вариант обработки исключений, -который в обычных языках программирования обычно оформляется ключевыми словами &lt;em&gt;try&lt;/em&gt; .. &lt;em&gt;catch&lt;/em&gt; .. &lt;em&gt;finally&lt;/em&gt; с различными вариациями. -Но в условиях жестких ограничений на синтаксис языка, и невозможности использовать ключевые слова, -комбинировать символы для указания разных типов блоков при обработке исключений, было бы крайне сомнительной затеей. -Ведь основная цель разработки NewLang — простота и понятность кода, а тут с самого начала могут появиться комбинации скобочек, стрелочек, -палочек и других подобных символов.&lt;/p&gt; -&lt;p&gt;И тут в голову пришла очень простая мысль. А ненужно повторять логику обработки ошибок из классических языков программирования! -Ведь основная цель подобных синтаксических конструкций - выделить участок кода где возможно возникновение ошибки, -перехватить и обработать правильный тип исключения. -Ведь классические языки программирования изначально были жестко привязаны к машинному представлению данных в оперативной памяти компьютера -и тип данных для них играл принципиально важное значение. -Но это не является ограничением для языков с динамической типизацией!&lt;/p&gt; -&lt;p&gt;Поэтому, подход к обработке исключений планируется следующий: Программный код, который может привести к ошибке, заключается в двойные фигурные скобки -&lt;strong&gt;{{&lt;/strong&gt; &lt;i&gt;любой код или вызов одиночной функции&lt;/i&gt; &lt;strong&gt;}}&lt;/strong&gt;, -а результат выполнения такого блока кода присваивается переменной. После этого анализируется возвращенное значение и тип исключения может обрабатываться обычным условным оператором.&lt;/p&gt; -&lt;p&gt;Наверно, это проще показать на примере:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;$error&lt;/span&gt; :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{{&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# начало блока try&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; call_or_exception1&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; call_or_exception2&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}}&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# конец блока try&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Обычные условные операторы вместо типизированных блоков catch&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$error&lt;/span&gt; ~ :type1&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;-&amp;gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt; код обработки ошибки 1&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$error&lt;/span&gt; ~ :type2&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;-&amp;gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt; код обработки ошибки 2&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Самое удивительное, что при таком подходе значительно упрощается и семантика блоков &lt;em&gt;try&lt;/em&gt; &lt;strong&gt;…&lt;/strong&gt; &lt;em&gt;finally&lt;/em&gt;, которые вообще становятся не нужны.&lt;/p&gt; -&lt;p&gt;Исходный код на Java:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;try&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;try&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;throw&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;new&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Exception&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;a&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;finally&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;throw&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;new&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;IOException&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;b&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;catch&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;IOException&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;ex&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;System&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;err&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;println&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;ex&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;getMessage&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;());&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;catch&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Exception&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;ex&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;System&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;err&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;println&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;ex&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#c4a000&#34;&gt;getMessage&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;());&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#f8f8f8;text-decoration:underline&#34;&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Эквивалентный ему на NewLang:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;$catch&lt;/span&gt; :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;$finally&lt;/span&gt; :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Error1&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}}&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Error2&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;2&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Строка выполнится даже при возникновении исключении Error1&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;$finally&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Error1 вернется, если не будет Error2&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}}&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$catch&lt;/span&gt; ~ :Error1&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; -&amp;gt; printf&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;«%s», &lt;span style=&#34;color:#000&#34;&gt;$catch&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$catch&lt;/span&gt; ~ :Error2&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; -&amp;gt; printf&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;«%s», &lt;span style=&#34;color:#000&#34;&gt;$catch&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;как-все-это-попробовать&#34;&gt;Как все это попробовать?&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%ba%d0%b0%d0%ba-%d0%b2%d1%81%d0%b5-%d1%8d%d1%82%d0%be-%d0%bf%d0%be%d0%bf%d1%80%d0%be%d0%b1%d0%be%d0%b2%d0%b0%d1%82%d1%8c&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Сейчас сборка проекта реализована только под Linux и если кроме текстового описания захочется в живую поэкспериментировать на своей машине, то придется собрать интерпретатор из исходников самостоятельно.&lt;/p&gt; -&lt;p&gt;Так как текущий вариант предназначен первую очередь для отработки концепции, то часть из описанных возможностей пока не реализована (алгоритмические конструкции, наследование классов, итераторы, некоторые операции и т. д).&lt;/p&gt; -&lt;p&gt;Но можно поиграться с созданием переменных, вызовом функций и выполнением арифметических операций над данными, чтобы оценить синтаксис, основанный на правилах, и может быть, предложить свои собственные мысли и доработки для его улучшения.&lt;/p&gt; -&lt;h3 id=&#34;сборка-repl-из-исходников-пока-только-под-linux&#34;&gt;Сборка REPL из исходников (пока только под Linux)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b1%d0%be%d1%80%d0%ba%d0%b0-repl-%d0%b8%d0%b7-%d0%b8%d1%81%d1%85%d0%be%d0%b4%d0%bd%d0%b8%d0%ba%d0%be%d0%b2-%d0%bf%d0%be%d0%ba%d0%b0-%d1%82%d0%be%d0%bb%d1%8c%d0%ba%d0%be-%d0%bf%d0%be%d0%b4-linux&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;h4 id=&#34;подготовка-репозитория&#34;&gt;Подготовка репозитория&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d0%be%d0%b4%d0%b3%d0%be%d1%82%d0%be%d0%b2%d0%ba%d0%b0-%d1%80%d0%b5%d0%bf%d0%be%d0%b7%d0%b8%d1%82%d0%be%d1%80%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h4&gt; -&lt;ul&gt; -&lt;li&gt;Скачать &lt;a href=&#34;https://github.com/rsashka/newlang&#34;&gt;исходники&lt;/a&gt;&lt;/li&gt; -&lt;li&gt;Скачать и развернуть архив libtorch в каталоге contrib (PyTorch Build: Stable (1.10.*) -&amp;gt; Your OS: Linux -&amp;gt; Package: LibTorch -&amp;gt; Language: C++ / Java -&amp;gt; Compute Platform: CPU -&amp;gt; Download here (cxx11 ABI): libtorch-cxx11-abi-shared-with-deps-1.10.2+cpu.zip)&lt;/li&gt; -&lt;li&gt;Активировать и скачать исходники субмодулей (git submodule init &amp;amp;&amp;amp; git submodule update)&lt;/li&gt; -&lt;li&gt;В каталоге &lt;em&gt;contrib&lt;/em&gt; запустить файл &lt;em&gt;build.sh&lt;/em&gt; для сборки библиотеки libffi&lt;/li&gt; -&lt;li&gt;В каталоге &lt;em&gt;core&lt;/em&gt; запустить файл &lt;em&gt;compile_syntax.sh&lt;/em&gt; для генерации файлов парсера и лексического анализатора. Может потребоваться установка утилит flex и bison. Если что, у меня установлены flex 2.6.4 и bison (GNU Bison) 3.7.4&lt;/li&gt; -&lt;/ul&gt; -&lt;h4 id=&#34;собрать&#34;&gt;Собрать&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%be%d0%b1%d1%80%d0%b0%d1%82%d1%8c&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h4&gt; -&lt;ul&gt; -&lt;li&gt;Юнит-тесты (newlang_test): в каталоге core выполнить команду &lt;em&gt;make CONF=UnitTest&lt;/em&gt;&lt;/li&gt; -&lt;li&gt;Интерпретатор (nlc): в каталоге core выполнить команду &lt;em&gt;make CONF=Debug&lt;/em&gt;&lt;/li&gt; -&lt;/ul&gt; -&lt;h2 id=&#34;утилита-nlc-newlangcompiler&#34;&gt;Утилита nlc (NewLangCompiler)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%83%d1%82%d0%b8%d0%bb%d0%b8%d1%82%d0%b0-nlc-newlangcompiler&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;В текущее время nlc поддерживать работу только в режиме интерпретатора (несмотря на название). -Для тестирования и простой проверки компилятор не нужен, хотя на первых порах я делал именно его. -Но трудоемкость работ по постоянной переделке под новый синтаксис оказалась очень высокой, поэтому на время первичной отладки языковых конструкций было принято волевое решение ограничиться интерпретатором, -как более простым и быстрым способом проверки различных гипотез, а разработку настоящего компилятора (в виде трансплайтера на язык С++), -отложить до окончательной проработки синтаксиса.&lt;/p&gt; -&lt;h2 id=&#34;планы-на-будущее&#34;&gt;Планы на будущее&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d0%bb%d0%b0%d0%bd%d1%8b-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Естественное, одна статья и несколько маленьких примеров не дают исчерпывающей информации о возможностях языка. -Да и сами возможности пока не раскрыты в полной мере. -Ведь текущая версия, это скорее тестовая платформа для проверки декларируемых концепций и основного синтаксиса.&lt;/p&gt; -&lt;p&gt;Пока остаются не реализованными некоторые из заявленных возможностей и очень важных хотелок. -Но протестировать основной подход можно уже сейчас, и я буду благодарен за любую обратную связь и предложения.&lt;/p&gt; -&lt;p&gt;Если говорить о планах (естественно, в будущих версиях что-то может добавиться или измениться порядок их реализации), но в настоящий момент роадмап развития NewLang мне видится следующим образом:&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Доделать стандартные управляющие конструкции, обработку ошибок и итераторы.&lt;/li&gt; -&lt;li&gt;Доработать систему типов с учетом множественного наследования классов.&lt;/li&gt; -&lt;li&gt;Реализовать длинную арифметику и дроби.&lt;/li&gt; -&lt;li&gt;Сделать какую нибудь логическую игру (крестики нолики, судоку или что-то похожее) с алгоритмическим выбором следующего хода и его вычислением с помощью машинного обучения.&lt;/li&gt; -&lt;li&gt;Написать много разных примеров для оценки синтаксиса.&lt;/li&gt; -&lt;li&gt;Доработать синтаксис с учетом полученного опыта и обратной связи.&lt;/li&gt; -&lt;li&gt;Восстановить работоспособность компилятора для генерации исполняемых файлов.&lt;/li&gt; -&lt;li&gt;Сделать очередную большую чистку кода.&lt;/li&gt; -&lt;li&gt;Переработать и задокументировать получившуюся семантику языка с учетом всех возможностей и выпустить первую полнофункциональную версию NewLang.&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;&lt;a href=&#34;https://habr.com/companies/timeweb/articles/651999/&#34;&gt;Ссылка на первую публикаци&lt;/a&gt;&lt;/p&gt; - - </description> - </item> - - <item> - <title>Blog: Можно ли использовать декларативный и императивный стили написания программ одновременно?</title> - <link>http://localhost:1313/blog/prog-styles-same-time/</link> - <pubDate>Mon, 26 Jul 2021 00:00:00 +0000</pubDate> - - <guid>http://localhost:1313/blog/prog-styles-same-time/</guid> - <description> - - - &lt;p&gt;&lt;img alt=&#34;КДПВ&#34; src=&#34;http://localhost:1313/blog/matrix.jpeg&#34;&gt;&lt;/p&gt; - - -&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; -&lt;p&gt;Внимание!!!&lt;/p&gt; -&lt;p&gt;Данная статья содержит описание синтаксиса NewLnag предыдущей версии.&lt;/p&gt; -&lt;p&gt;Актуальную версию синтаксиса языка можно посмотреть &lt;a href=&#34;http://localhost:1313/docs/&#34;&gt;тут&lt;/a&gt;.&lt;/p&gt; - -&lt;/div&gt; - -&lt;p&gt;При разработке своего собственного языка программирования автор должен определиться, какими свойствами его язык должен обладать, -ведь в конечном итоге именно это и будет определять назначение языка и особенности его использования. -Причем некоторые свойства настолько сильно влияют на итоговую концепцию языка и его синтаксис, -что впоследствии их изменение невозможно в принципе, либо новый синтаксис получается очень запутанным и непонятным. -Наверно из-за этого многие свойства языков программирования рассматриваются и изучаются как взаимоисключающие.&lt;/p&gt; -&lt;p&gt;До недавнего времени я считал, что императивная и декларативная парадигмы написания программ являются антагонистами и взаимоисключающими понятиями. -Ведь выбор стиля написания кода, изначально определяется автором языка еще на стадии его проектирования и оказывает влияние на все последующие аспекты.&lt;/p&gt; -&lt;p&gt;Но сейчас я думаю, что это не верно. Императивный и декларативный стили программирования не являются взаимоисключающими, -а писать программы только в одной из указанных парадигм подталкивают правила синтаксиса, реализованные в языке!&lt;/p&gt; -&lt;p&gt;Другими словами, использовать только императивную или только декларативную парадигмы разработчик вынужден не потому, что он не умеет или не хочет писать код по другому, а из-за того, -что все более-менее мейнстримные языки программирования ориентированы на использование только одной парадигмы. -И выбор только одной парадигмы написания кода, это ограничение, которое навязано программистам создателями языка. -Ведь если они изначально ориентировались только на одну концепцию разработки кода, то и разрабатывали синтаксис языка в соответствии с этой парадигмой.&lt;/p&gt; -&lt;p&gt;Данная статья — размышление о совместимости декларативной и императивной парадигм программирования и возможности их одновременного использования в рамках одного языка программирования одновременно.&lt;/p&gt; -&lt;h2 id=&#34;что-такое-декларативное-программирование&#34;&gt;Что такое &amp;ldquo;Декларативное программирование&amp;rdquo;?&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%87%d1%82%d0%be-%d1%82%d0%b0%d0%ba%d0%be%d0%b5-%d0%b4%d0%b5%d0%ba%d0%bb%d0%b0%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Вначале мне захотелось разобраться, а существуют ли чисто декларативные языки программирования? -Такие, которые могут полностью обходятся без императивных конструкций?&lt;/p&gt; -&lt;p&gt;Но чуть не споткнулся уже в самом начале, т.к. даже само определение «декларативное программировании», в вики описывается &lt;a href=&#34;https://ru.wikipedia.org/wiki/%D0%94%D0%B5%D0%BA%D0%BB%D0%B0%D1%80%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&#34;&gt;следующим образом&lt;/a&gt;:&lt;/p&gt; -&lt;blockquote&gt; -&lt;p&gt;Декларати́вное программи́рование — парадигма программирования, в которой задаётся спецификация решения задачи, то есть описывается, что представляет собой проблема и ожидаемый результат. Противоположностью декларативного является императивное программирование, описывающее на том или ином уровне детализации, как решить задачу и представить результат.&lt;/p&gt; -&lt;/blockquote&gt; -&lt;p&gt;Уже в изначальном определении закладывается противопоставление парадигм, а дальше идут рассуждения о «направлении» программирования. -И хоть вики сама и не является авторитетным источником информации, но даже такая заготовка статьи смогла показать направление поиска ответов на первый поставленный вопрос.&lt;/p&gt; -&lt;p&gt;И заставил задуматься один абзац в конце статьи следующего содержания:&lt;/p&gt; -&lt;blockquote&gt; -&lt;p&gt;«Чисто декларативные» компьютерные языки зачастую неполны по Тьюрингу — так как теоретически не всегда возможно порождение исполняемого кода по декларативному описанию. -Это иногда приводит к спорам о корректности термина «декларативное программирование» (менее спорным является «декларативное описание решения» или, что то же самое, «декларативное описание задачи»).&lt;/p&gt; -&lt;/blockquote&gt; -&lt;p&gt;Судя по наличию такой оговорки, ставится под сомнение наличие «чисто декларативных» языков. -И как только пришлось задуматься над это мыслью, то сразу стало очевидным, что какой бы декларативный язык программирования не существовал, -то в нем должна быть как минимум одна императивная конструкция, которая будет запускать поиск решения! -Ведь любой синоним слова «выполнить» или «запустить» по определению будет императивом!&lt;/p&gt; -&lt;p&gt;Например в языке Prolog, который обычно и приводят в качестве примера декларативного языка программирования, &amp;ldquo;замаскированным&amp;rdquo; императивным оператором является знак вопроса. -Он кажется естественным и логичным, как же без него? Но по своей сути, это императивная конструкция!&lt;/p&gt; -&lt;p&gt;Тоже самое касается и языка SQL. Он тоже как бы декларативный, но неожиданно все его команды являются императивными по сути. &lt;em&gt;SELECT&lt;/em&gt;, &lt;em&gt;CREATE&lt;/em&gt;, &lt;em&gt;ALTER&lt;/em&gt;, &lt;em&gt;DROP&lt;/em&gt;, &lt;em&gt;INSERT&lt;/em&gt;, &lt;em&gt;UPDATE&lt;/em&gt;, &lt;em&gt;DELETE&lt;/em&gt; и т. д., а декларативными являются только описания условий их выполнения!&lt;/p&gt; -&lt;p&gt;В результате, у меня так и не получилось найти чисто-декларативный язык программирования без императивных операторов (может быть, Вики права и такого языка программирования и вовсе не существует?).&lt;/p&gt; -&lt;h2 id=&#34;а-что-отличает-декларативные-языки-программирования-от-императивных&#34;&gt;А что отличает декларативные языки программирования от императивных?&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b0-%d1%87%d1%82%d0%be-%d0%be%d1%82%d0%bb%d0%b8%d1%87%d0%b0%d0%b5%d1%82-%d0%b4%d0%b5%d0%ba%d0%bb%d0%b0%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b5-%d1%8f%d0%b7%d1%8b%d0%ba%d0%b8-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%be%d1%82-%d0%b8%d0%bc%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Согласно определению, декларативными языками программирования их называют из-за возможности записать некие условия в декларативном стиле. -Но кроме этого, в декларативных языках как правило присутствует и некий внутренний механизм поиска решений. -Подобный &amp;ldquo;вычислитель&amp;rdquo; есть и в SQL и Prolog и во многих других декларативных языках.&lt;/p&gt; -&lt;p&gt;Интересно, а является ли внутренняя система поиска решений обязательным признаком декларативного стиля программирования или это только особенность конкретного языка программирования, которая не зависит от декларативного стиля написания кода?&lt;/p&gt; -&lt;p&gt;Чтобы проверить данные предположения, можно было попробовать написать классическую декларативную программу на императивном языке, у которого отсутствует внутренний механизм поиска решений.&lt;/p&gt; -&lt;p&gt;А заодно, таким образом можно будет и изучить вопрос, получится ли написать программу в декларативном стиле используя обычный императивный язык программирования?&lt;/p&gt; -&lt;p&gt;Для примера, решил попробовать повторить уже классическую программу в декларативном стиле на Прологе.&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;parent&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Tom&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Jake&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;).&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;parent&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Janna&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Jake&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;).&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;parent&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Tom&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Tim&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;).&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;male&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Tom&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;).&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;male&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Tim&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;).&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;male&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Jake&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;).&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;female&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Janna&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;).&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;brother&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;X&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Y&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:-&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;parent&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Z&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;X&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;),&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;parent&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Z&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Y&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;),&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;male&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;X&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;),&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;male&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Y&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;),&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;X&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Y&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;.&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;?&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;brother&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Получилась вот такая функционально - эквивалентная программа на С++, которая максимально приближена по стилю к декларативному прототипу:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;sex_&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;male&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;female&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;human&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;std&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;vector&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;human&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;*&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;parent_&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;human&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;sex_&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;sex&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;parent_&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;parent&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;human&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;Tom&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Tom&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;male&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,{}};&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;human&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;Janna&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Janna&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;female&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,{}};&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;human&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;Jake&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Jake&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;male&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,{&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Tom&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Janna&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}};&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;human&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;Tim&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Tim&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;male&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,{&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Tom&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}};&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;std&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;vector&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;human&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;*&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;humans&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Tom&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Janna&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Jake&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Tim&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;auto&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;brothers&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[](&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;human&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;a&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;human&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;b&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;auto&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;intersec&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[](&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;parent_&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;a&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;parent_&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;b&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;auto&lt;/span&gt; &lt;span style=&#34;color:#f57900&#34;&gt;elem_a&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;a&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;auto&lt;/span&gt; &lt;span style=&#34;color:#f57900&#34;&gt;elem_b&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;b&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;elem_a&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;elem_b&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;elem_a&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;elem_b&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#204a87&#34;&gt;true&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#204a87&#34;&gt;false&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;b&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;b&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;a&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;sex&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;male&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;b&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;sex&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;male&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;intersec&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;a&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;parent&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;b&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;parent&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;));&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;auto&lt;/span&gt; &lt;span style=&#34;color:#f57900&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;humans&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;auto&lt;/span&gt; &lt;span style=&#34;color:#f57900&#34;&gt;b&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;humans&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;brothers&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;a&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;b&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;))&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;std&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;cout&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;a&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;name&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34; and &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;b&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;name&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Конечно, текст на С++ получается значительно многословней, чем вариант на Прологе, но по сути, это почти дословное повторение декларативного стиля написания кода. -Тем более, не стоит забывать про рассуждения в начале статьи об изначальном выборе концепции при создании языка -и &amp;ldquo;принуждении&amp;rdquo; программистов пользоваться только одной, изначально выбранной парадигмой разработки.&lt;/p&gt; -&lt;p&gt;&lt;strong&gt;Таким образом, можно с высокой долей уверенности утверждать, что теоретически можно писать код одновременно в разных стилях.&lt;/strong&gt;&lt;/p&gt; -&lt;p&gt;Но что тогда мешает в рамках одного языка программирования писать с использованием императивного и декларативного стиля? -Неужели только убежденность создателей языков в том, что императивный и декларативный стили программирования являются взаимоисключающими? -И только из-за этого получаются языки программирования, синтаксис которых подходит для использования одной единственной парадигмы?&lt;/p&gt; -&lt;p&gt;&lt;em&gt;Но если это так, то что мешает попробовать разработать синтаксис языка программирования, в котором можно было бы использовать сразу императивный и декларативный стили программирования одновременно?&lt;/em&gt;&lt;/p&gt; -&lt;h2 id=&#34;что-мешает-совместить-императивный-и-декларативный-стили-написания-в-рамках-одной-программы&#34;&gt;Что мешает совместить императивный и декларативный стили написания в рамках одной программы?&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%87%d1%82%d0%be-%d0%bc%d0%b5%d1%88%d0%b0%d0%b5%d1%82-%d1%81%d0%be%d0%b2%d0%bc%d0%b5%d1%81%d1%82%d0%b8%d1%82%d1%8c-%d0%b8%d0%bc%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b9-%d0%b8-%d0%b4%d0%b5%d0%ba%d0%bb%d0%b0%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b9-%d1%81%d1%82%d0%b8%d0%bb%d0%b8-%d0%bd%d0%b0%d0%bf%d0%b8%d1%81%d0%b0%d0%bd%d0%b8%d1%8f-%d0%b2-%d1%80%d0%b0%d0%bc%d0%ba%d0%b0%d1%85-%d0%be%d0%b4%d0%bd%d0%be%d0%b9-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;В любой компьютерной программе всегда существует разделение кода на описание данных и на языковые конструкции для их обработки, т.е. фактически это разделение &lt;strong&gt;на данные&lt;/strong&gt; и &lt;strong&gt;на функции&lt;/strong&gt;. -Мне кажется, что основная сложность, которая не дает использовать разные стили программирования в рамках одного языка, это необходимость разделять описываемые сущности на «данные» и «управляющие конструкции». -Ведь это свойство (необходимость разделения сущностей на &amp;ldquo;данные&amp;rdquo; и &amp;ldquo;функции&amp;rdquo;), является неотъемлемой частью любого языка программирования.&lt;/p&gt; -&lt;p&gt;Это не удивительно, ведь на заре становления ИТ индустрии, создатели первых языков программирования ориентировались исключительно на императивный стиль, потому что назначением любого компилятора было - преобразовать исходный текст программы в машинные инструкции. И на примерах модульного, структурного и объекто-ориентированного подходах показана и доказана необходимость оформления исполняемого кода в выделенные процедуры с последующей их группировкой в модули и классы.&lt;/p&gt; -&lt;p&gt;А декларативный стиль написания программ стал появляться только после создания высокоуровневых языков программирования. -И основная цель создания данных языков сместилась на поиск решения конечного пользователя, а не на упрощение генерации бинарных файлов с машинными инструкциями. -Если внимательно посмотреть на приведенные выше примеры кода, то можно заметить, что в них определения данных и операторы для их обработки идут вперемешку, (для примера на С++ это определение лямбд функции), что кардинально отличается от императивного подхода.&lt;/p&gt; -&lt;p&gt;Так может быть, основная особенность декларативного стиля как раз и заключается в том, что в нем не разделяются «данные» и «действия над данными»? -Или как вариант, можно не указывать выполняемые действия над данными вовсе (как в некоторых SQL конструкциях)?&lt;/p&gt; -&lt;p&gt;Может быть как раз именно эта особенность (возможность последовательной записи программного кода в соответствии с собственными логическими рассуждениями, -в которых могут перемежаться «данные» и «функции», как это происходит при человеческом мыслительном процессе), -не дает в полной мере реализовать возможность совмещения императивных и декларативных стилей программирования?&lt;/p&gt; -&lt;p&gt;&lt;em&gt;И если это так, тогда можно попробовать разработать такой синтаксис, который будет поддерживать определение как данных, так и декларацию функций в рамках единого потока языковых конструкций!&lt;/em&gt;&lt;/p&gt; -&lt;h2 id=&#34;проверка-гипотезы-в-новом-языке-программирования&#34;&gt;Проверка гипотезы в новом языке программирования&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b0-%d0%b3%d0%b8%d0%bf%d0%be%d1%82%d0%b5%d0%b7%d1%8b-%d0%b2-%d0%bd%d0%be%d0%b2%d0%be%d0%bc-%d1%8f%d0%b7%d1%8b%d0%ba%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Для поверки данного предположения, я решил добавить в свой &lt;a href=&#34;http://localhost:1313/blog/2021/05/24/%D0%BD%D0%B5%D0%BE%D0%B1%D1%8B%D1%87%D0%BD%D0%B0%D1%8F-%D0%BA%D0%BE%D0%BD%D1%86%D0%B5%D0%BF%D1%86%D0%B8%D1%8F-%D1%81%D0%B8%D0%BD%D1%82%D0%B0%D0%BA%D1%81%D0%B8%D1%81%D0%B0-%D1%8F%D0%B7%D1%8B%D0%BA%D0%B0-%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F/&#34;&gt;новый язык программирования&lt;/a&gt; -(синтаксис которого допускает определение функций в одном потоке с описанием обрабатываемых данных), недостающие алгоритмические конструкции, которые позволяли бы реализовать императивный стиль программирования, -несмотря на изначальную ориентацию только на декларативную парадигму.&lt;/p&gt; -&lt;p&gt;Правда с учетом изначальных ограничений синтаксиса нового языка (запрет на применение операторов в виде зарезервированных ключевых слов), -в качестве оператора проверки условия была выбрана синтаксическая конструкция, соответствующая по смыслу термину «следует», -т.е. тире и угловая скобка «&lt;strong&gt;-&amp;gt;&lt;/strong&gt;».&lt;/p&gt; -&lt;p&gt;В результате, условный оператор получился практически математический, который легко объединяется в последовательности для реализации проверки множественных условий вида «else if». -А для объединения сразу нескольких логического операторов между собой и для отделения их от последующего действия, операторы проверки условия можно заключать в круглые скобки.&lt;/p&gt; -&lt;p&gt;В общем случае условный оператор в новом языке программирования имеет вид:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;условие&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;действие&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;или&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;условие&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;действие&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;или&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;условие&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;||&lt;/span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;условие&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;действие&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;действие&lt;/span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;иначе&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Или расширенный вариант, для наглядности записанный с отступами:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;условие&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;действие&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;условие&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;действие&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;условие&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;действие&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;действие&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;_иначе&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Тогда и операторы циклов можно будет записать практически аналогично, только выбрав в качестве оператора, не оператор следования, -а следование с возвратом (раз уж нужно указывать циклическое действие).&lt;/p&gt; -&lt;p&gt;Цикл пока:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;условие&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;тело&lt;/span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;цикла&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;счетный цикл для работы с итератором:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;счетчик&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;_или_данные&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;?&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;тело&lt;/span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;цикла&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;В этом случае, решение тестового примера декларативной программы на Прологе можно будет легко оформить, как в императивном, так и в декларативном стилях одновременно!&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; м :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;муж.&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ж :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;жен.&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; human @&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; term&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;пол&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;, &lt;span style=&#34;color:#000&#34;&gt;parent&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=[&lt;/span&gt;,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;])&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Tom @&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; human&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;пол&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;м&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Janna @&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; human&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;пол&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;ж&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Jake @&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; human&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;м, &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;Tom, &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;Janna,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;])&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Tim @&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; human&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;пол&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;м, &lt;span style=&#34;color:#000&#34;&gt;parent&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=[&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;Tom,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;])&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; brother&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;h1, h2&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;=&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;$h1&lt;/span&gt;!&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$h2&lt;/span&gt;, &lt;span style=&#34;color:#000&#34;&gt;$h1&lt;/span&gt;.пол&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;==&lt;/span&gt;м, &lt;span style=&#34;color:#000&#34;&gt;$h2&lt;/span&gt;.пол&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;==&lt;/span&gt;м, &lt;span style=&#34;color:#000&#34;&gt;$h1&lt;/span&gt;.parent &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;$h2&lt;/span&gt;.parent&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; // Оператор «&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;» побитовое «И» для чисел или операция пересечения для множеств -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; // Запись алгоритма поиска решения в императивном стиле -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;h1&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;human!, &lt;span style=&#34;color:#000&#34;&gt;h2&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;human!&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;? &amp;lt;-&amp;gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;brother&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;h1, h2&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;))&lt;/span&gt; -&amp;gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @print&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$h1&lt;/span&gt;, &lt;span style=&#34;color:#000&#34;&gt;$h2&lt;/span&gt;, «&lt;span style=&#34;color:#4e9a06&#34;&gt;\n&lt;/span&gt;»&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; // Краткая запись алгоритма поиска решения в императивном стиле -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;h1&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;human!, &lt;span style=&#34;color:#000&#34;&gt;h2&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;human!&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;? &amp;lt;-&amp;gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; brother&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$h1&lt;/span&gt;, &lt;span style=&#34;color:#000&#34;&gt;$h2&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; -&amp;gt; @print&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$h1&lt;/span&gt;, &lt;span style=&#34;color:#000&#34;&gt;$h2&lt;/span&gt;, «&lt;span style=&#34;color:#4e9a06&#34;&gt;\n&lt;/span&gt;»&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; // Запись поиска решения в декларативном стиле -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; brother&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;human!, human!&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;?&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Примерно это и требовалось показать!&lt;/p&gt; -&lt;h3 id=&#34;зы&#34;&gt;З.Ы.&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b7%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Я почти закончил эксперименты с синтаксисом языка. -И теперь, после добавления в него недостающих алгоритмический конструкций (ветвления и циклов), планирую, -что следующая статья о новом языке программирования будет посвящена описанию его полного синтаксиса и публикации исходников прототипа компилятора для возможности поиграться на реальных примерах.&lt;/p&gt; -&lt;h3 id=&#34;ззы&#34;&gt;З.З.Ы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b7%d0%b7%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;В &lt;a href=&#34;https://habr.com/company/timeweb/blog/569422/comments/#comment_23301086&#34;&gt;комментариях @gbg&lt;/a&gt; привел очень простой ответ на один из поднятых вопросов. -Причем в более элегантном виде и без написания кода!&lt;/p&gt; -&lt;blockquote&gt; -&lt;p&gt;Ну и пять копеечек про ООП. Как ни странно:&lt;/p&gt; -&lt;ol&gt; -&lt;li&gt;В нем таки есть декларативная часть, все эти pubic, private, virtual, etc&lt;/li&gt; -&lt;li&gt;Эта декларативная часть, внезапно, элегантно позволяет реализовывать декомпозицию и управление сложностью.&lt;/li&gt; -&lt;li&gt;При наличии перегрузок, можно поиграть в алгебраическое мышление, рассматривая взаимодействие двух объектов как бинарную операцию.&lt;/li&gt; -&lt;/ol&gt; -&lt;p&gt;Ух ты, ООП - это обкатанная практикой технология, которая совмещает декларатив с императивом и вроде позволяет освоившим ее вкусно кушать и мягко спать!&lt;/p&gt; -&lt;/blockquote&gt; -&lt;p&gt;&lt;a href=&#34;https://habr.com/companies/timeweb/articles/569422/&#34;&gt;Ссылка на первую публикаци&lt;/a&gt;&lt;/p&gt; - - </description> - </item> - - <item> - <title>Blog: Необычная концепция синтаксиса языка программирования</title> - <link>http://localhost:1313/blog/unusual-prog/</link> - <pubDate>Mon, 24 May 2021 00:00:00 +0000</pubDate> - - <guid>http://localhost:1313/blog/unusual-prog/</guid> - <description> - - - &lt;p&gt;&lt;img alt=&#34;КДПВ&#34; src=&#34;http://localhost:1313/blog/langs.jpeg&#34;&gt;&lt;/p&gt; - - -&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; -&lt;p&gt;Внимание!!!&lt;/p&gt; -&lt;p&gt;Данная статья содержит описание синтаксиса NewLnag предыдущей версии.&lt;/p&gt; -&lt;p&gt;Актуальную версию синтаксиса языка можно посмотреть &lt;a href=&#34;http://localhost:1313/docs/&#34;&gt;тут&lt;/a&gt;.&lt;/p&gt; - -&lt;/div&gt; - -&lt;p&gt;Хочу представить на обсуждение читателей немного необычный концепт языка программирования, в котором отсутствует проблема, -присущая практически всем промышленным языкам - постоянное увеличение сложности синтаксиса языка из-за его естественного развития по мере выхода новых версий и добавления новых фич. -Эта проблема описана в статье &lt;a href=&#34;http://localhost:1313/blog/complex-prog/&#34;&gt;&amp;ldquo;Простое сложное программирование&amp;rdquo;&lt;/a&gt; и &lt;a href=&#34;http://localhost:1313/blog/lang-final/&#34;&gt;Какая &amp;ldquo;идеальная&amp;rdquo; цель развития у языков программирования?&lt;/a&gt;&lt;/p&gt; -&lt;p&gt;После нескольких экспериментов с синтаксисом, хочется проверить выработанную идею на широкой аудитории &lt;a href=&#34;https://habr.com/companies/timeweb/articles/558738/&#34;&gt;Хабра&lt;/a&gt;, которая как нельзя лучше подходит для этих целей.&lt;/p&gt; -&lt;p&gt;Особенности языка:&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Низкий порог входа и естественное ограничение уровня сложности в течение длительного времени даже при условии постоянного развития самого языка.&lt;/li&gt; -&lt;li&gt;Возможность писать код программы как в декларативной, так и в императивной парадигме с использованием процедурного, модульного и объектно-ориентированного подхода.&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;Ну и в соответствии с собственным наблюдением &lt;a href=&#34;https://habr.com/post/539674/&#34;&gt;Хабр — ума палата&lt;/a&gt;, буду рад любым комментариям и предложениям, которые помогут протестировать или улучшить предлагаемое решение.&lt;/p&gt; -&lt;h2 id=&#34;введение&#34;&gt;Введение&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b2%d0%b2%d0%b5%d0%b4%d0%b5%d0%bd%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Первой необычной особенностью языка является полное отсутствие зарезервированных ключевых слов. -Точнее, планируется использовать только одно единственное ключевое слово (название языка), которое может быть как главной точкой входа в приложение, -так и способом доступа к настройкам языка под конкретную предметную область, например при необходимости реализации &lt;a href=&#34;https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%B4%D0%BC%D0%B5%D1%82%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D1%8F%D0%B7%D1%8B%D0%BA&#34;&gt;DSL парадигмы&lt;/a&gt;.&lt;/p&gt; -&lt;p&gt;В настоящий момент название языка не выбрано, поэтому для примеров используется просто слово &lt;em&gt;lang&lt;/em&gt;, которое в будущем будет изменено.&lt;/p&gt; -&lt;p&gt;Данная особенность (отсутствие зарезервированных ключевых слов) реализуется за счет того, грамматика языка основана на использовании общеупотребительных символов и классических знаков препинания, -а все остальные букво-символьные последовательности при парсинге программы рассматриваются как &amp;ldquo;токены&amp;rdquo;.&lt;/p&gt; -&lt;p&gt;Компилятор языка реализуется как &lt;a href=&#34;https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B0%D0%BD%D1%81%D0%BF%D0%B0%D0%B9%D0%BB%D0%B5%D1%80&#34;&gt;transpiler&lt;/a&gt; - преобразование исходного кода программы, -написанной на одном языке программирования, в эквивалентный исходный код на другом языке. -Первые эксперименты с синтаксисом я начинал на Python, но после осознания необходимости разработки не только интерпретатора, -но и компилятора непосредственно в исполняемый код, решил остановиться на C++. Хотя в принципе, язык реализации может быть любым.&lt;/p&gt; -&lt;p&gt;Использование &lt;a href=&#34;https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B0%D0%BD%D1%81%D0%BF%D0%B0%D0%B9%D0%BB%D0%B5%D1%80&#34;&gt;транспиляции&lt;/a&gt; при реализации компилятора решает сразу множество очевидных и не очень задач. -Сразу отпадает необходимость разрабатывать низкоуровневый компилятор в исполняемый процессорный код, -а в моем случае основным бонусом такого подхода становится возможность использования императивной парадигмы программирования за счет вставок кода непосредственно в исходный код приложения на языке реализации.&lt;/p&gt; -&lt;p&gt;И именно этот момент позволяет естественно разделить декларативный и императивный способ написания программы. -В этом случае в декларативной парадигме реализуется только одна из трех базовых управляющих конструкций, -необходимых и достаточных при реализации &lt;a href=&#34;https://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&#34;&gt;любого алгоритма&lt;/a&gt; — &lt;em&gt;следование&lt;/em&gt;.&lt;/p&gt; -&lt;p&gt;Другими словами, в декларативном стиле описывается только &lt;em&gt;последовательность&lt;/em&gt; операций, которые следуют одна за другой, -но отсутствует возможность запрограммировать циклы или ветвление (переходы) по условию. -Из-за этого в декларативном стиле можно записать только следующие типы языковых конструкций:&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;комментарий&lt;/li&gt; -&lt;li&gt;определение переменной и присвоение ей значения&lt;/li&gt; -&lt;li&gt;создание объекта и назначение его свойствам значений по умолчанию&lt;/li&gt; -&lt;li&gt;создание функции (метода для всего класса объектов)&lt;/li&gt; -&lt;li&gt;вызов функции или итератора&lt;/li&gt; -&lt;li&gt;непосредственная вставка кода на языке реализации&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;Так как цель текущей публикации - протестировать общую концепцию, то начну сразу с примеров без длинного описания подробностей, а некоторые нюансы буду комментировать по ходу дела. -Тем более, самая главная цель &amp;ldquo;низкий порог входа&amp;rdquo; само собой подразумевает возможность самостоятельно разобраться в синтаксисе. -Тем не менее, совсем без знаний языка реализации не обойтись и начальные знания в программировании на С/С++ все равно необходимы.&lt;/p&gt; -&lt;h2 id=&#34;привет-мир-в-императивной-парадигме&#34;&gt;&amp;ldquo;Привет, мир!&amp;rdquo; в императивной парадигме&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b8%d0%b2%d0%b5%d1%82-%d0%bc%d0%b8%d1%80-%d0%b2-%d0%b8%d0%bc%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d0%bf%d0%b0%d1%80%d0%b0%d0%b4%d0%b8%d0%b3%d0%bc%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Определение обычной функции выполняется с помощью оператора присвоения &amp;ldquo;:=&amp;rdquo;, а программный код на языке реализации (в данном случае на C++) -заключается в фигурные скобки. Простой пример вывода строки на экран выглядит примерно так:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;print&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;str&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;printf&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;%s&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;static_cast&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;*&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;str&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;));&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Функция &lt;strong&gt;print&lt;/strong&gt; с аргументом по умолчанию в виде пустой строки внутри себя вызывает обычный printf из стандартной библиотеки.&lt;/p&gt; -&lt;p&gt;Соответственно &amp;ldquo;Привет, мир!&amp;rdquo; в императивной парадигме программирования будет выглядеть тривиально:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;#!/bin/lang -&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;print&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;str&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;printf&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;%s&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;static_cast&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;*&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;str&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;));&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#a40000&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;print&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Привет, мир!&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Из примера видно, что обращение к аргументам внутри С++ кода происходит с использованием символа &lt;strong&gt;$&lt;/strong&gt;, который указывается вначале именованного аргумента. -Кроме этого, для доступа к аргументам функции можно обращаться по их порядковым номерам начиная с первого ($1, $2, $3 и т. д.). -Зарезервированный аргумент $0 содержит сам объект, метод которого вызывается или &lt;em&gt;nullptr&lt;/em&gt;, если функция не принадлежит объекту.&lt;/p&gt; -&lt;p&gt;&lt;em&gt;Обычные&lt;/em&gt; функции являются именно обычными функциями в понимании С/С++. -Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д. -Технически, код такой функции парсится на предмет замены использованных аргументов, -специальным образом декорируется её имя и добавляются специальные маркеры для идентификации содержимого. -После этого исходный текст готов для сборки обычным С++ компилятором для превращения в динамическую библиотеку -и после её загрузки функцию можно будет вызвать в любой момент (для вызова функции перед её именем необходимо указать символ &lt;strong&gt;&amp;quot;@&amp;quot;&lt;/strong&gt;).&lt;/p&gt; -&lt;p&gt;Непосредственное выполнение файла в режиме интерпретатора происходит в два этапа. На первом этапе из текста программы генерируется временный С++ файл с исходным кодом всех функций, этот файл компилируется gcc и собирается динамическая библиотека.&lt;/p&gt; -&lt;p&gt;На втором этапе, собранная динамическая библиотека загружается средой выполнения, а исходный текст программы начинает последовательно выполнятся интерпретатором (все строки, за исключением определений функций).&lt;/p&gt; -&lt;p&gt;Есть еще вариант, когда вместо интерпретации кода программы, генерируется С++ файл не только для функций, но и для основной части приложения. -Тогда на выходе компилятора будет уже обычный бинарный файл, хотя в том случае оперативно поправить текст программы уже не получится.&lt;/p&gt; -&lt;h2 id=&#34;логическое-программирование-в-декларативной-парадигме&#34;&gt;Логическое программирование в декларативной парадигме&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bb%d0%be%d0%b3%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%b2-%d0%b4%d0%b5%d0%ba%d0%bb%d0%b0%d1%80%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d0%bf%d0%b0%d1%80%d0%b0%d0%b4%d0%b8%d0%b3%d0%bc%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Так как самым известным языком логического программирования в декларативном стиле считается Prolog, -поэтому приведу простой пример программы Brother (поиска братьев) на Прологе и эквивалентный ему код на новом языке.&lt;/p&gt; -&lt;p&gt;Prolog:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; male&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Tom&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;. -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; male&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Tim&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;. -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; male&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Jake&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;. -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; female&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Janna&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;. -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; parent&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Tom&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Jake&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;. -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; parent&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Janna&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Jake&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;. -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; parent&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Tom&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#4e9a06&#34;&gt;&amp;#34;Tim&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;. -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; brother&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;X,Y&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;:- parent&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;Z,X&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;,parent&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;Z,Y&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;,male&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;X&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;,male&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;Y&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;,X&lt;span style=&#34;color:#4e9a06&#34;&gt;\=&lt;/span&gt;Y. -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Вывод: &lt;strong&gt;(Jake, Tim) (Tim, Jake)&lt;/strong&gt;&lt;/p&gt; -&lt;p&gt;Тот же самый пример:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;#!/bin/lang&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; human:&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;@term&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;sex&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;,parent&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Tom:&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;@human&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;male&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Janna:&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;@human&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;female&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Jake:&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;@human&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;male, &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;Tom, Janna,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Tim:&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;@human&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;sex&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;male, &lt;span style=&#34;color:#000&#34;&gt;parent&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=(&lt;/span&gt;Tom,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; human::brother&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;test&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;human!&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;=&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;$0&lt;/span&gt;!&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$test&lt;/span&gt;, &lt;span style=&#34;color:#000&#34;&gt;$0&lt;/span&gt;.sex&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;==&lt;/span&gt;male, @intersec&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;$0&lt;/span&gt;.parent, &lt;span style=&#34;color:#000&#34;&gt;$test&lt;/span&gt;.parent&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; human.brother? -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Вывод: &lt;strong&gt;[Tim.brother(Jake), Jake.brother(Tim),]&lt;/strong&gt;&lt;/p&gt; -&lt;p&gt;Надеюсь, что синтаксис интуитивно понятен, особенно при наличии эквивалентного кода на Прологе, но на всякий случай поясню отдельные моменты.&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; human:&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;@term&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;sex&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;,parent&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;В этой строке создается объект с именем &amp;ldquo;human&amp;rdquo; и двумя свойствами &amp;ldquo;sex&amp;rdquo; и &amp;ldquo;parent&amp;rdquo;, -значения которых по умолчанию не определены, а родителем является системный объект &amp;ldquo;term&amp;rdquo;. -Использование символа &lt;strong&gt;&amp;quot;@&amp;quot;&lt;/strong&gt; в начале термина обозначает вызов существующей функции с параметрами, указанными в скобках. -В данном случае вызывается конструктор системного объекта &amp;ldquo;term&amp;rdquo;, а возвращаемым результатом является новый термин &amp;ldquo;human&amp;rdquo;, -который можно воспринимать как один экземпляр класса, так и как имя целого класса, если он будет выступать в качестве родителя для других объектов.&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Tom:&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;@human&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;male&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Janna:&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;@human&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;female&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Jake:&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;@human&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;male, &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;Tom, Janna,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;))&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; Tim:&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;@human&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;parent&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=(&lt;/span&gt;Tom,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;, &lt;span style=&#34;color:#000&#34;&gt;sex&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt;male&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Первые две строки создают объекты &amp;ldquo;Tom&amp;rdquo; и &amp;ldquo;Janna&amp;rdquo;, у которых свойство &amp;ldquo;sex&amp;rdquo; установлено в значения &amp;ldquo;male&amp;rdquo; и &amp;ldquo;female&amp;rdquo; соответственно. -А в последней строке при создании объекта Tim значения свойств задается с указанием их имени.&lt;/p&gt; -&lt;p&gt;Конструкции &lt;em&gt;(Tom, Janna,)&lt;/em&gt; и &lt;em&gt;(Tom,)&lt;/em&gt;, это определение константного литерала с типом словарь, которые присваиваются указанным свойствам.&lt;/p&gt; -&lt;p&gt;Чтобы определение словаря не путать с указанием аргументов при вызове функции, в нем содержится обязательная финальная запятая перед закрывающей скобкой. -Это правило (финальная запятая перед закрывающей скобкой) действует и при определении литерала массива, только для записи которого используются скобки не круглые, а квадратные (например &lt;strong&gt;[,]&lt;/strong&gt; - пустой массив). -Основным отличием словаря от массива, заключаются в способах доступа к их элементам. -Для доступа к элементу массива используется целочисленный индекс, а в словаре может быть использован как индекс, так и имя элемента при его наличии. -Между словарем и массивом есть еще отличия, но сейчас они не принципиальны.&lt;/p&gt; -&lt;p&gt;И предпоследняя строка в примере:&lt;/p&gt; -&lt;p&gt;human::brother(test=human &lt;em&gt;!&lt;/em&gt;) &lt;strong&gt;&amp;amp;&amp;amp;=&lt;/strong&gt; &lt;em&gt;$0&lt;/em&gt; != &lt;em&gt;$test&lt;/em&gt;, &lt;em&gt;$0&lt;/em&gt;.sex==male, @intersec(&lt;em&gt;$0&lt;/em&gt;.parent, &lt;em&gt;$test&lt;/em&gt;.parent);&lt;/p&gt; -&lt;p&gt;это определение &lt;i&gt;простой чистой&lt;/i&gt; функции &amp;ldquo;brother&amp;rdquo; для всех объектов, производных от &amp;ldquo;human&amp;rdquo;. -Данная функция принимает один именованный аргумент &amp;ldquo;test&amp;rdquo;, значением по умолчанию которого является &lt;em&gt;итератор&lt;/em&gt; объектов класса &amp;ldquo;human&amp;rdquo;.&lt;/p&gt; -&lt;p&gt;Оператор &lt;strong&gt;&amp;amp;&amp;amp;=&lt;/strong&gt; означает определение &lt;em&gt;простой чистой&lt;/em&gt; функции, т. е. функции без внешних зависимостей, -которая не имеет доступа к глобальному контексту, а результат выполнения которой является логическое значение, -которое вычисляется по схеме &lt;a href=&#34;https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BD%D1%8A%D1%8E%D0%BD%D0%BA%D1%86%D0%B8%D1%8F&#34;&gt;логическое И&lt;/a&gt; для всех условий, указанных в теле функции через запятую.&lt;/p&gt; -&lt;p&gt;Выполнение и вывод результата выполнения программы происходит в строке -&lt;code&gt;human.brother?&lt;/code&gt;&lt;/p&gt; -&lt;p&gt;Восклицательный и вопросительный знаки обозначают &lt;a href=&#34;https://ru.wikipedia.org/wiki/%D0%98%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80&#34;&gt;итератор&lt;/a&gt;. Итератор &amp;ldquo;&lt;strong&gt;!&lt;/strong&gt;&amp;rdquo; возвращает один текущий элемент из коллекции и передвигает указатель на следующий, -а итератор &amp;ldquo;&lt;strong&gt;?&lt;/strong&gt;&amp;rdquo; возвращает сразу всю коллекцию объектов целиком.&lt;/p&gt; -&lt;p&gt;Другими словами при выполнении строки программы &lt;em&gt;human.brother &lt;strong&gt;?&lt;/strong&gt;&lt;/em&gt; происходит последовательный перебор всей коллекции объектов типа &amp;ldquo;human&amp;rdquo;, -где у каждого объекта выполняется функция &amp;ldquo;brother&amp;rdquo; с аргументами по умолчанию. -А так как в качестве аргумента по умолчанию указан итератор &lt;em&gt;human &lt;strong&gt;!&lt;/strong&gt;&lt;/em&gt;, то в качестве аргумента последовательно предается каждый из элементов указанного класса. -По сути, при выполнении этой строки происходит полный перебор всех возможных комбинаций объектов класса &amp;ldquo;human&amp;rdquo; каждый с каждым.&lt;/p&gt; -&lt;blockquote&gt; -&lt;p&gt;Более подробное описание работы итератора и причина выбора такого синтаксиса опубликовано в отдельной статье &lt;a href=&#34;https://habr.com/company/timeweb/blog/559916/&#34;&gt;Лаконичный итератор для декларативного синтаксиса&lt;/a&gt;&lt;/p&gt; -&lt;/blockquote&gt; -&lt;p&gt;Результат выполнения будет состоять из тех пар объектов, для которых функция &amp;ldquo;brother&amp;rdquo; вернет истину, т.е. результат выполнения будет массив из двух пар объектов &lt;strong&gt;[Tim.brother(Jake), Jake.brother(Tim),]&lt;/strong&gt;.&lt;/p&gt; -&lt;h2 id=&#34;формулировка-проверяемой-концепции&#34;&gt;Формулировка проверяемой концепции&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%84%d0%be%d1%80%d0%bc%d1%83%d0%bb%d0%b8%d1%80%d0%be%d0%b2%d0%ba%d0%b0-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d1%8f%d0%b5%d0%bc%d0%be%d0%b9-%d0%ba%d0%be%d0%bd%d1%86%d0%b5%d0%bf%d1%86%d0%b8%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Тестируемая концепция заключается в следующем. Синтаксис языка программирования состоит как бы из двух частей, -каждая из которых является относительно независимой и в тоже время они связаны между собой.&lt;/p&gt; -&lt;p&gt;Первая часть сложная — предназначена для описания алгоритмов в &lt;em&gt;императивном стиле&lt;/em&gt; на обычном языке программирования, -поэтому внутри функций разработчику доступны все возможности языка реализации.&lt;/p&gt; -&lt;p&gt;Вторая часть простая (по сравнению с первой) — предназначена только для логического описания задачи в &lt;em&gt;декларативном стиле&lt;/em&gt;. -Именно эта часть используется для начального уровня использования, а естественное ограничение только на последовательное выполнение операторов -(т.е. отсутствие циклов и ветвлений) не доставляет чрезмерных сложностей в понимании исходного текста программы даже в будущем по мере развития языка.&lt;/p&gt; -&lt;p&gt;Связь между двумя вариантами синтаксиса прозрачна и реализуется за счет совместного использования переменных и функций, -декларация и обращение к которым происходит в едином стиле в обоих случаях за счет унификации синтаксиса на уровне использования знаков препинания.&lt;/p&gt; -&lt;p&gt;Сейчас я специально не привожу полного синтаксиса и подробного описания остальных возможностей языка, т.к. компилятор пока не готов для публичной презентации. -Но буду крайне благодарен за любой отклик или дельные предложения в отношении предложенной концепции.&lt;/p&gt; -&lt;p&gt;Особенно это касается возможных конфликтов по синтаксису в представленных примерах.&lt;/p&gt; - - </description> - </item> - - <item> - <title>Blog: Простое сложное программирование</title> - <link>http://localhost:1313/blog/complex-prog/</link> - <pubDate>Thu, 15 Apr 2021 00:00:00 +0000</pubDate> - - <guid>http://localhost:1313/blog/complex-prog/</guid> - <description> - - - &lt;p&gt;&lt;img alt=&#34;КДПВ&#34; src=&#34;http://localhost:1313/blog/complex-prog/complex-prog.jpeg&#34;&gt;&lt;/p&gt; -&lt;p&gt;В очередной раз увидел на Хабре статью про сложное дело под названием «программирование». -И то, что программирование действительно является делом не простым воспринимается как факт и обычно не требует какого либо подтверждения.&lt;/p&gt; -&lt;p&gt;Но понятие «сложность» сродни термину «куча». -Для кого-то и пять кокосов это не куча, а кого-то съел один и «больше не хочется» - значит для него и единственного кокоса будет много.&lt;/p&gt; -&lt;p&gt;Так и со сложностью ПО. Вроде бы увеличение сложности является для всех очевидным и наблюдается во всех сферах применения IT технологий, -да и сами языки программирования по мере своего развития становятся все сложнее, -а вот оценивать «сложность» с помощью численных метрик — дело заведомо неблагодарное, но и «нельзя управлять тем, что невозможно измерить &amp;hellip;».&lt;/p&gt; -&lt;p&gt;Обычно разговоры о «сложности» включают в себя только оценочные суждения без какой либо численной оценки. -А так как лично меня интересует вопрос сложности языков программирования, -то я решил посчитать сложность реализации компилятора gcc в каких нибудь условных попугаях. -Вдруг можно будет увидеть какие нибудь закономерности?&lt;/p&gt; -&lt;h2 id=&#34;выбор-попугаев-для-измерения&#34;&gt;Выбор «попугаев» для измерения&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b2%d1%8b%d0%b1%d0%be%d1%80-%d0%bf%d0%be%d0%bf%d1%83%d0%b3%d0%b0%d0%b5%d0%b2-%d0%b4%d0%bb%d1%8f-%d0%b8%d0%b7%d0%bc%d0%b5%d1%80%d0%b5%d0%bd%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Я не стал придумывать свои или вычислять эмпирические метрики &lt;a href=&#34;https://habr.com/company/intel/blog/106082/&#34;&gt;программного кода&lt;/a&gt;, -и в качестве «попугая» решил взять самую простую метрику SLOC (англ. Source Lines of Code) — количество строк исходного текста компилятора, -которая очень легко вычисляется.&lt;/p&gt; -&lt;p&gt;Правда, с её помощью можно будет оценивать сложность языка только при следующем допущении — сложность языка должна находиться в прямой зависимости от сложности его реализации, -если для простых синтаксических конструкций будет требовать меньше кода, чем для более сложных.&lt;/p&gt; -&lt;p&gt;Конечно, использование метрики «количество строк исходного кода» имеет и свои недостатки, -т.к. она сильно зависит от используемого языка программирования, стиля оформления исходного кода и в общем случае не позволяет сравнивать несколько разных проектов между собой.&lt;/p&gt; -&lt;p&gt;Но для численной оценки сложности кода в рамках &lt;strong&gt;одного проекта&lt;/strong&gt;, метрика SLOC подходит хорошо.&lt;/p&gt; -&lt;h2 id=&#34;методика-подсчета-sloc&#34;&gt;Методика подсчета SLOC&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bc%d0%b5%d1%82%d0%be%d0%b4%d0%b8%d0%ba%d0%b0-%d0%bf%d0%be%d0%b4%d1%81%d1%87%d0%b5%d1%82%d0%b0-sloc&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Изначально попробовал использовать простой bash скрипт с поиском по маске и подсчетом числа строк в файлах исходника через &lt;code&gt;wc -l&lt;/code&gt;. -Но через некоторое время стало понятно, что приходится изобретать очередной велосипед.&lt;/p&gt; -&lt;p&gt;&lt;img alt=&#34;Ну вы поняли&#34; src=&#34;http://localhost:1313/blog/complex-prog/bag.jpeg&#34;&gt;&lt;/p&gt; -&lt;p&gt;Поэтому решил взять уже готовый. После быстрого поиска остановился на утилите &lt;a href=&#34;https://dwheeler.com/sloccount/&#34;&gt;SLOCCount&lt;/a&gt;, -которая умеет анализировать почти три десятка типов исходников.&lt;/p&gt; -&lt;h3 id=&#34;список-типов-файлов-для-автоматического-анализа&#34;&gt;Список типов файлов для автоматического анализа&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%bf%d0%b8%d1%81%d0%be%d0%ba-%d1%82%d0%b8%d0%bf%d0%be%d0%b2-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2-%d0%b4%d0%bb%d1%8f-%d0%b0%d0%b2%d1%82%d0%be%d0%bc%d0%b0%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%be%d0%b3%d0%be-%d0%b0%d0%bd%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; 1. Ada (.ada, .ads, .adb) - 2. Assembly (.s, .S, .asm) - 3. awk (.awk) - 4. Bourne shell and variants (.sh) - 5. C (.c) - 6. C++ (.C, .cpp, .cxx, .cc) - 7. C shell (.csh) - 8. COBOL (.cob, .cbl) as of version 2.10 - 9. C# (.cs) as of version 2.11 - 10. Expect (.exp) - 11. Fortran (.f) - 12. Haskell (.hs) as of version 2.11 - 13. Java (.java) - 14. lex/flex (.l) - 15. LISP/Scheme (.el, .scm, .lsp, .jl) - 16. Makefile (makefile) — not normally shown. - 17. Modula-3 (.m3, .i3) as of version 2.07 - 18. Objective-C (.m) - 19. Pascal (.p, .pas) - 20. Perl (.pl, .pm, .perl) - 21. PHP (.php, .php[3456], .inc) as of version 2.05 - 22. Python (.py) - 23. Ruby (.rb) as of version 2.09 - 24. sed (.sed) - 25. SQL (.sql) — not normally shown. - 26. TCL (.tcl, .tk, .itk) - 27. Yacc/Bison (.y) &amp;lt;/code&amp;gt; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Причем, считает не просто количество строк исходного текста, но и умеет игнорировать комментарии, -исключает из подсчета дубли файлов (сравнивает их хеш суммы), а также выводит расчетную трудоемкость, -примерную оценку стоимости разработки анализируемого проекта и другие характеристики.&lt;/p&gt; -&lt;p&gt;Меня изначально интересовал объем исходников на С/С++ и может быть еще на Ассемблере, если таких файлов окажется достаточно много. -Но после начала работы очень обрадовался, что не стал изобретать велосипед, а взял готовую тулзу, -т.к. она отдельно считала статистику исходных файлов синтаксического анализатора Yacc/Bison (.y), -который и определяет фактическую сложность парсера (читай сложность синтаксиса языка программирования).&lt;/p&gt; -&lt;p&gt;Старые исходники gcc брал с &lt;a href=&#34;https://gcc.gnu.org/mirrors.html&#34;&gt;https://gcc.gnu.org/mirrors.html&lt;/a&gt;, но перед запуском анализатора удалил каталоги других компиляторов (ada, fortran, java и т.д.), -чтобы они не попадали в итоговую статистику.&lt;/p&gt; -&lt;h2 id=&#34;результаты-в-попугаях&#34;&gt;Результаты в попугаях&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%80%d0%b5%d0%b7%d1%83%d0%bb%d1%8c%d1%82%d0%b0%d1%82%d1%8b-%d0%b2-%d0%bf%d0%be%d0%bf%d1%83%d0%b3%d0%b0%d1%8f%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;&lt;img src=&#34;http://localhost:1313/blog/complex-prog/graph1.jpeg&#34;&gt;&lt;/p&gt; -&lt;p&gt;&lt;strong&gt;Итоговая статистика&lt;/strong&gt;&lt;/p&gt; -&lt;p&gt;&lt;img src=&#34;http://localhost:1313/blog/complex-prog/graph2.png&#34;&gt;&lt;/p&gt; -&lt;p&gt;&lt;strong&gt;Объем кода синтаксического анализатора Yacc/Bison&lt;/strong&gt;&lt;/p&gt; -&lt;p&gt;&lt;img src=&#34;http://localhost:1313/blog/complex-prog/graph3.jpeg&#34;&gt;&lt;/p&gt; -&lt;p&gt;&lt;strong&gt;Объем общей которой базы GCC (только для языков C и C++)&lt;/strong&gt;&lt;/p&gt; -&lt;h2 id=&#34;выводы&#34;&gt;Выводы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b2%d1%8b%d0%b2%d0%be%d0%b4%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;К сожалению, синтаксический анализатор Yacc/Bison использовался только до 3 версии, а после его использование свелось на нет. -Поэтому оценить сложность синтаксиса С/С++ с помощью объема кода парсера можно лишь примерно до 1996-98 года, -после чего его стали постепенно выпиливать, т.е. чуть менее, чем за десять лет. -Но даже за этот период объем кодовой базы синтаксического анализатора вырос двукратно, что примерно соответствует по времени реализации стандарта C99.&lt;/p&gt; -&lt;p&gt;Но даже если не учитывать код синтаксического анализатора, то объем общей кодовой базы так же коррелирует с внедрением новых стандартов C++: C99, С11 и C14.&lt;/p&gt; -&lt;p&gt;На графике не видно выраженного пика для С+17 и следующих версий, но предполагаю, -что при текущем объеме кодой базы (более 4 миллионов строк только С и С++ кода), несколько тысяч строк, -необходимых для поддержки синтаксических конструкций новых стандартов просто незаметно.&lt;/p&gt; -&lt;h3 id=&#34;вывод-первый---очевидный-рост-сложности-инструментов-разработки&#34;&gt;Вывод первый - очевидный. Рост сложности инструментов разработки&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b2%d1%8b%d0%b2%d0%be%d0%b4-%d0%bf%d0%b5%d1%80%d0%b2%d1%8b%d0%b9---%d0%be%d1%87%d0%b5%d0%b2%d0%b8%d0%b4%d0%bd%d1%8b%d0%b9-%d1%80%d0%be%d1%81%d1%82-%d1%81%d0%bb%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b8%d0%bd%d1%81%d1%82%d1%80%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d1%80%d0%b0%d0%b7%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Фактически на примере проекта GCC можно видеть постоянный и неотвратимый рост сложности рабочих инструментов программистов.&lt;/p&gt; -&lt;p&gt;И как бы не говорили о деградации разработки в статье &lt;a href=&#34;https://habr.com/company/itelma/blog/550620/&#34;&gt;&amp;ldquo;Хорошие времена рождают слабаков&amp;rdquo;&lt;/a&gt;, -о системном кризисе программного обеспечения, который носит поколенческом характер, но мне кажется тут дело немного в другом.&lt;/p&gt; -&lt;p&gt;Обновление персонала и как следствие — необходимость обучения новых сотрудников старым наработкам, -тут дело не сколько в передаче знаний, сколько в возможности эти знания усваивать.&lt;/p&gt; -&lt;p&gt;Причем возможность усвоения знаний для разных поколений будет разная, но не из-за того, что предыдущее поколение было умнее, а у нового поколения не хватает толку в этом разобрать. -Просто изменяется окружение и усложняются рабочие инструменты, по сравнению с теми, которые были в ходу у предыдущего поколения.&lt;/p&gt; -&lt;h3 id=&#34;вывод-второй--порог--входа&#34;&gt;Вывод второй — порог входа&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b2%d1%8b%d0%b2%d0%be%d0%b4-%d0%b2%d1%82%d0%be%d1%80%d0%be%d0%b9--%d0%bf%d0%be%d1%80%d0%be%d0%b3--%d0%b2%d1%85%d0%be%d0%b4%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Представьте, что нужно «сделать свой сайт». Естественно нужно определить, какую CMS для него использовать и какой брать хостинг. -И если с хостингом вопрос решается очень просто, конечно же в TimeWeb, да еще и &lt;a href=&#34;https://timeweb.com/services/hosting?utm_source=rsashka&amp;utm_medium=timeweb&amp;utm_campaign=timeweb-bring-a-friend&#34;&gt;с бонусом по ссылке&lt;/a&gt;, то при выборе CMS приходится подумать.&lt;/p&gt; -&lt;p&gt;И если для простых сайтов существуют и простые решения, то для тех, кто не ищет легких путей существует CMS Drupal, -который примечателен тем, что имеет фантастически высокий порог входа для начала использования.&lt;/p&gt; -&lt;p&gt;&lt;img alt=&#34;Сложность внедрения Drupal&#34; src=&#34;http://localhost:1313/blog/complex-prog/drupal.jpeg&#34;&gt;&lt;/p&gt; -&lt;p&gt;Это я к чему? При использовании любого инструмента, как и языка программирования, существует некий минимальный уровень комфортного использования. -Причем этот уровень прямо пропорционально связан с размером той целевой аудитории, для которой он предназначен. -Точнее, размер возможной аудитории определяется в том числе и требованиями к уровню начальных знаний и квалификации потенциального пользователя.&lt;/p&gt; -&lt;h3 id=&#34;итоговый-вывод--не-утешительный&#34;&gt;Итоговый вывод — не утешительный&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b8%d1%82%d0%be%d0%b3%d0%be%d0%b2%d1%8b%d0%b9-%d0%b2%d1%8b%d0%b2%d0%be%d0%b4--%d0%bd%d0%b5-%d1%83%d1%82%d0%b5%d1%88%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d1%8b%d0%b9&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Если рассматривать увеличение сложности только самого ПО, то это одно дело. Вот к примеру:&lt;/p&gt; -&lt;p&gt;&lt;strong&gt;Статистика ядра Linux с вики&lt;/strong&gt;&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;17 сентября 1991: Linux версии 0.01 (10 239 строк кода). -14 марта 1994: Linux версии 1.0.0 (176 250 строк кода). -Март 1995: Linux версии 1.2.0 (310 950 строк кода). -9 июня 1996: Linux версии 2.0.0 (777 956 строк кода). -25 января 1999: Linux версии 2.2.0, изначально довольно недоработанный (1 800 847 строк кода). -4 января 2001: Linux версии 2.4.0 (3 377 902 строки кода). -18 декабря 2003: Linux версии 2.6.0 (5 929 913 строк кода). -23 марта 2009: Linux версии 2.6.29, временный символ Linux — тасманский дьявол Tuz (11 010 647 строк кода). -22 июля 2011: релиз Linux 3.0 (14,6 млн строк кода). -24 октября 2011: релиз Linux 3.1. -15 января 2012: релиз Linux 3.3 преодолел отметку в 15 млн строк кода. -23 февраля 2015: первый релиз-кандидат Linux 4.0 (более 19 млн строк кода). -7 января 2019: первый релиз-кандидат Linux 5.0 (более 26 млн строк кода). -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;А что делать, если сложность программного обеспечения накладывается на тенденцию постоянного усложнения самих рабочих инструментов? -Ведь постоянное развитие языков программирования неизбежно повышает порог входа для всех начинающих и только усугубляет проблему сложности разработки ПО.&lt;/p&gt; -&lt;p&gt;Другими словами, не зависимо от того, как хорошо документирован код и как полно он покрыт тестами, -через некоторое время устаревают используемые инструменты, завершаются жизненные циклы внешних зависимостей, -и самое главное, приходят новые люди взамен тех, кто разработал или сумел разобраться в системе.&lt;/p&gt; -&lt;p&gt;И у новых людей возникает необходимость разбираться в системе с самого начала, но в других начальных условиях. -И из-за этого, сложность изучения системы для всех новых людей будет выше просто по факту того, -что изменились внешние условия и усложнились рабочие инструменты, которыми приходится использовать новым сотрудникам.&lt;/p&gt; -&lt;p&gt;Понятно, что чем дальше, тем проще уже не будет. Ведь область IT , это среда с самой высокой конкуренцией. -И как уж тут не вспомнить Льюиса Кэррола, что его крылатое выражение&lt;/p&gt; -&lt;blockquote&gt; -&lt;p&gt;Нужно бежать со всех ног, чтобы только оставаться на месте, а чтобы куда-то попасть, надо бежать как минимум вдвое быстрее!&lt;/p&gt; -&lt;/blockquote&gt; -&lt;p&gt;Ведь это относится не только к Алисе в стране чудес, но и ко всем информационным технологиям в целом!&lt;/p&gt; -&lt;p&gt;&lt;a href=&#34;https://habr.com/companies/timeweb/articles/551754/&#34;&gt;Первоначальная публикация&lt;/a&gt;&lt;/p&gt; - - </description> - </item> - - <item> - <title>Blog: Какая «идеальная» цель развития у языков программирования?</title> - <link>http://localhost:1313/blog/lang-final/</link> - <pubDate>Wed, 07 Apr 2021 00:00:00 +0000</pubDate> - - <guid>http://localhost:1313/blog/lang-final/</guid> - <description> - - - &lt;p&gt;&lt;img alt=&#34;КДПВ&#34; src=&#34;http://localhost:1313/blog/lang-final/lang-final.jpeg&#34;&gt;&lt;/p&gt; -&lt;p&gt;С постоянной периодичностью появляется информация о выходе новой версии того или иного языка программирования. -И с каждой новой версией расширяются его возможности, добавляются новые синтаксические конструкции или иные улучшения.&lt;/p&gt; -&lt;p&gt;И это очень сильно напоминает развитие технологий, как и в любой другой области техники. -Когда с очередным этапом совершенствуются создаваемые творения. -Быстрее, выше, сильнее … и одновременно значительно сложнее.&lt;/p&gt; -&lt;p&gt;Об этой проблеме меня заставила задуматься первоапрельская статья &lt;a href=&#34;https://habr.com/post/550270/&#34;&gt;«Доказательное программирование»&lt;/a&gt;.&lt;/p&gt; -&lt;p&gt;Понятно, что дата публикации статьи говорит сама за себя. -Тем не менее, новые стандарты С++, постоянно выходящие спецификации Java или новый синтаксис у PHP 8, -невольно заставляют задуматься, а в нужную ли сторону идет развитие языков программирования? -Ведь большинство нововведений добавляют сложность в основной рабочий инструмент и решая одни проблемы, неявно добавляя множество других.&lt;/p&gt; -&lt;p&gt;А что должно быть в конце прогресса у развития такой дисциплины как программирование? -Или хотя бы у одного конкретного языка? Ради достижения какой конечной «идеальной» цели разрабатываются новые стандарты языков программирования?&lt;/p&gt; -&lt;p&gt;Если фантазировать об идеальной конечной цели развития, например транспорта, -то это будет мгновенное перемещение на любое расстояние с произвольной полезной нагрузкой и нулевым потреблением энергии.&lt;/p&gt; -&lt;p&gt;Или, например, какая может быть идеальная цель у медицины? &lt;del&gt;Бедные не болели, а богатые не выздоравливали,&lt;/del&gt; вероятно, лечение любых болезней и биологическое бессмертие.&lt;/p&gt; -&lt;p&gt;Конечно, «идеальная» цель это очень упрощенное понятие. Фактически, «идеальная» это синоним «недостижимая», -т.к. она всегда будет упираться необходимость соблюдать компромисс между различными взаимно-исключающими граничными условиями.&lt;/p&gt; -&lt;p&gt;Но сравнивать разработку средств программирования с процессом развития в других технических дисциплинах напрямую нельзя. -Ведь при создание конечного продукта в любой технической области, все сложные производственные операции, -которые требуют непосредственного участия человека, практически всегда можно разделить на отдельные, более простые части или этапы.&lt;/p&gt; -&lt;p&gt;Это делается, в том числе и для того, чтобы сложность одной выполняемой операции не была запредельной для исполнителя. -Но как это можно сделать при разработке программного обеспечения?&lt;/p&gt; -&lt;p&gt;В данном случае, я имею ввиду конечную ограниченность возможностей одного конкретного человека в противовес возможностям разделения технологических процессов на отдельные этапы, -каждый из которых может выполняться совершенно разными людьми (как пример, это обычный конвеер с его разделением труда на элементарные операции -или узкая специализация врачей-специалистов в одной конкретной области).&lt;/p&gt; -&lt;p&gt;Ведь даже сложно себе представить фантастическую организацию труда программистов в виде конвеера:&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Первый разработчик пишет только интерфейсы функций и их вызовы, после чего передает код второму сотруднику.&lt;/li&gt; -&lt;li&gt;Второй пишет в тексте программы только условия проверки и безусловные переходы и передает текст третьему.&lt;/li&gt; -&lt;li&gt;Третий отвечает за написание циклов и общее форматирование кода и т.д. -и результате ожидаемо получится полный бред.&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;Из-за этого индустрия разработки ПО вынуждена идти по экстенсивному пути развития (т.е. за счет увеличения используемых в производстве ресурсов). -Современные промышленные языки программирования имеют очень богатые возможности по разделению кода приложения на отдельные функции/модули/компоненты, -что позволяет вести разработку сложного программного продукта сразу множеству сотрудников одновременно.&lt;/p&gt; -&lt;p&gt;Но и такое развитие имеет естественное ограничение. И этим ограничением является сам человек, -так как каждый разработчик должен знать и уметь пользоваться своим рабочим инструментом, т.е. языком программирования.&lt;/p&gt; -&lt;p&gt;Если взять приведенную выше аналогию с конвеером, то в ней каждый рабочий должен был бы досконально знать б&lt;strong&gt;о&lt;/strong&gt;льшую часть используемых станков -и инструментов на всем заводе, независимо от того, какую &lt;strong&gt;одну&lt;/strong&gt; конкретную операцию он выполняет на своем рабочем месте.&lt;/p&gt; -&lt;p&gt;Ведь парадокс развития языков программирования заключается в том, что добавляя новые возможности и синтаксические конструкции, -мы усложняем рабочий инструмент, предназначенный как для совместного, так и для индивидуального использования!&lt;/p&gt; -&lt;p&gt;И получается, что одновременно с процессом постоянного наращивания возможностей средств разработки идет -и обратный процесс — увеличение сложности разработки кода отдельно взятым разработчиком. -Фактически, это и есть то самое взаимоисключающее непреодолимое противоречие.&lt;/p&gt; -&lt;p&gt;Может быть именно поэтому невозможно найти «серебряную пулю», которая бы повышала производительность труда одного программиста? -Ведь внимание и возможности человека не безграничны. -И любые новшества и улучшения рабочего инструмента программиста вынужденно толкают всю IT индустрию на экстенсивный путь развития.&lt;/p&gt; -&lt;p&gt;Возможно следует разрабатывать принципиально новые подходы, а не гнаться за синтаксическим сахаром в языках программирования из прошлого века? -Или и вовсе не париться, продолжать пользоваться тем, что есть, а теория дедушки Дарвина все сама расставит по своим местам?&lt;/p&gt; -&lt;p&gt;&lt;a href=&#34;https://habr.com/companies/timeweb/articles/551224/&#34;&gt;Первоначальная публикация&lt;/a&gt;&lt;/p&gt; - - </description> - </item> - - <item> - <title>Blog: Проблема логических языков программирования</title> - <link>http://localhost:1313/blog/logic-prog/</link> - <pubDate>Sat, 09 Jan 2021 00:00:00 +0000</pubDate> - - <guid>http://localhost:1313/blog/logic-prog/</guid> - <description> - - - &lt;p&gt;&lt;img alt=&#34;КДПВ&#34; src=&#34;http://localhost:1313/blog/langs.jpeg&#34;&gt;&lt;/p&gt; -&lt;p&gt;Некоторое время назад я писал про &lt;a href=&#34;http://localhost:1313/blog/inter-prog/&#34;&gt;«Интернациональное программирование на естественных языках»&lt;/a&gt;, -в которой попытался представить достойную цель для абстрактного языка программирования, -попробовав примерить на него роль связующего звена между миром программистов с компьютерами и не программистов.&lt;/p&gt; -&lt;p&gt;Но в результате оказалось, что это не нужно в принципе, т.к. «не программистам» просто не требуется учиться писать программы. -А если иногда такое желание и возникает, то вполне хватает обычных формализованных языков программирования, -которых уже сейчас насчитывается наверно более десяти тысяч.&lt;/p&gt; -&lt;p&gt;А пользователи, как программисты, так и не программисты, просто хотят решать возникающие перед ними задачи. -И хотя задачи бывают совершенно разные, но если способ (алгоритм) её решения известен, то выбрать язык для её решения не составит никакого труда.&lt;/p&gt; -&lt;p&gt;За исключением одного класса задач. Задач, решение которых нельзя описать в виде алгоритма. -Но можно указать некие критерии, которым должно удовлетворять искомое решение.&lt;br&gt; -Я имею ввиду логические языки программирования и &lt;a href=&#34;https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%BE%D0%BB%D0%BE%D0%B3_%28%D1%8F%D0%B7%D1%8B%D0%BA_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F%29&#34;&gt;Пролог&lt;/a&gt;, как самый яркий представитель этого класса.&lt;/p&gt; -&lt;p&gt;Еще помню воспоминание из юности, когда удалось достать дискету с этим языком. -Ух, с каким задором горели мои глаза, когда мне казалось, ну вот, еще чуть-чуть и будет создана система с базой знаний, -у которой и можно будет получить заветный ответ 42 на любой вопрос.&lt;/p&gt; -&lt;p&gt;Так почему этого так и не случилось? В чем проблема Пролога, да и любой системы / языка программирования, -назначение которых анализировать факты и искать ответы на вопросы?&lt;/p&gt; -&lt;p&gt;Эта проблема называется &lt;a href=&#34;https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BC%D0%B1%D0%B8%D0%BD%D0%B0%D1%82%D0%BE%D1%80%D0%BD%D1%8B%D0%B9_%D0%B2%D0%B7%D1%80%D1%8B%D0%B2&#34;&gt;«Комбинаторный взрыв»&lt;/a&gt; - экспоненциальная (или более) зависимость времени работы алгоритма от количества входных данных. -И есть как минимум два решения этой проблемы.&lt;/p&gt; -&lt;h2 id=&#34;подходы-к-написанию-программ&#34;&gt;Подходы к написанию программ&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d0%be%d0%b4%d1%85%d0%be%d0%b4%d1%8b-%d0%ba-%d0%bd%d0%b0%d0%bf%d0%b8%d1%81%d0%b0%d0%bd%d0%b8%d1%8e-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Прежде чем переходить к частностям, следует сказать пару слов про парадигмы программирования. -Обычно противопоставляют между собой два разных стиля в написании программ: &lt;a href=&#34;https://ru.wikipedia.org/wiki/%D0%98%D0%BC%D0%BF%D0%B5%D1%80%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&#34;&gt;императивный&lt;/a&gt; и &lt;a href=&#34;https://ru.wikipedia.org/wiki/%D0%94%D0%B5%D0%BA%D0%BB%D0%B0%D1%80%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5&#34;&gt;декларативный&lt;/a&gt;.&lt;/p&gt; -&lt;p&gt;Императивный — это классический вариант написания программы, при котором программист сам задает шаги алгоритма для получения конечного результата. -А сам текст программы состоит из последовательности команд, которые читают, сохраняют и обрабатывают данные или вызывают другие команды.&lt;/p&gt; -&lt;p&gt;Декларативный — в этом стиле программист описывает условия задачи и правила для получения требуемого результата, -но не требуется детально описывать все шаги работы алгоритма, оставляя их на усмотрения компьютера.&lt;/p&gt; -&lt;p&gt;Именно к декларативному стилю относится язык Пролог, да и все остальные логические языки программирования. -К декларативному стилю написания программ следует относить и язык структурированных запросов (SQL).&lt;/p&gt; -&lt;p&gt;И проблема под называнием &lt;a href=&#34;https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BC%D0%B1%D0%B8%D0%BD%D0%B0%D1%82%D0%BE%D1%80%D0%BD%D1%8B%D0%B9_%D0%B2%D0%B7%D1%80%D1%8B%D0%B2&#34;&gt;«комбинаторный взрыв»&lt;/a&gt; сильнее всего оказывает негативное влияние как раз на подобные языки. -Ведь в императивном подходе программист сам отвечает за последовательность выполняемых команд, и если он запрограммировал алгоритм полного перебора всех возможных вариантов решений, то он сам себе злобный Буратино.&lt;/p&gt; -&lt;p&gt;Другое дело, программирование в декларативном стиле. Разработчик хоть и может указать ограничения, которые следует применять при поиске решения, -но это возможно только в том случае, когда известен алгоритм решения задачи. -Но если алгоритм решения известен, то проще использовать императивный стиль, как раз и реализуя этот алгоритм!&lt;/p&gt; -&lt;p&gt;Поэтому основное применения языков программирования в декларативном стиле — отказаться от необходимости описания четкого алгоритма поиска решения, -отдав это компьютеру на откуп. Для которого самое простое решение «в лоб» - полный перебор возможных вариантов.&lt;/p&gt; -&lt;p&gt;Именно в этом случае и начинается экспоненциальный рост времени выполнения алгоритма. -И начиная с определенного порога, время ожидания ответа становится неприемлемым для реального использования. -Это и означает «Комбинаторный взрыв», резкий («взрывной») рост времени выполнения алгоритма при увеличении размера входных данных.&lt;/p&gt; -&lt;h2 id=&#34;проблема-поиска-решений&#34;&gt;Проблема поиска решений&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%be%d0%b1%d0%bb%d0%b5%d0%bc%d0%b0-%d0%bf%d0%be%d0%b8%d1%81%d0%ba%d0%b0-%d1%80%d0%b5%d1%88%d0%b5%d0%bd%d0%b8%d0%b9&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;В языке Пролог эта проблема решалась за счет использования механизма отката и отсечений. -Иногда еще уточняли про «красное» и «зеленое» отсечение решений. -Но в любом случае, это были &lt;strong&gt;алгоритмические&lt;/strong&gt; механизмы для ограничения количества размера дерева возможных решений, -а необходимость их применения все равно остается на программисте.&lt;/p&gt; -&lt;p&gt;Но чтобы их правильно реализовывать, нужно знать алгоритм решения, что опять возвращает нас к утверждению о том, -что если известен алгоритм, то и программировать его удобнее в императивном стиле.&lt;/p&gt; -&lt;p&gt;А если полный алгоритм решения задачи не известен (или не подходит, например из-за большого времени для его работы), -то в результате остается либо увеличивать производительность системы, чтобы сократить время выполнения алгоритма, -либо искать другое решение, в том числе, сокращая вычислительную сложность поиска решений, например, исключая заведомо не подходящие данные, -чтобы уменьшить возможные комбинации их перебора.&lt;/p&gt; -&lt;h3 id=&#34;масштабирование-производительности&#34;&gt;Масштабирование производительности&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bc%d0%b0%d1%81%d1%88%d1%82%d0%b0%d0%b1%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d0%bf%d1%80%d0%be%d0%b8%d0%b7%d0%b2%d0%be%d0%b4%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d0%be%d1%81%d1%82%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Увеличение производительности тоже бывает разным и работает не во всех случаях. -Вертикальное масштабирование производительности одного узла вычислительной среды имеет свой естественный предел. -И даже многократное увеличение скорости работы компьютера может лишь отдалить порог терпения пользователя при ожидании получения результата, -но не в состоянии принципиально решить саму проблему.&lt;/p&gt; -&lt;p&gt;Другое дело горизонтальное масштабирование, при котором выполнение алгоритма запускается на отдельных узлах, которые параллельно решают одну и ту же задачу. -Такой способ масштабирования позволяет уже значительно сократить время получения итогового результата для сложных вычислительных задач. -И хотя это способ является решением «в лоб», но успехи в области data science доказывают успешность такого подхода.&lt;/p&gt; -&lt;p&gt;Конечно, у горизонтального масштабирования тоже есть подводные камни. -В первую очередь, сам алгоритм должен допускать возможность параллельного выполнения независимо от других узлов. -Также требуется автоматизация управления заданиями, самими вычислительными узлами, да и всей системой в целом.&lt;/p&gt; -&lt;p&gt;Тут частично может помочь парадигма функционального программирования, которая ограничивает результат вычисления функций только входными параметрами -и результатом выполнения других функций, но сам результат не зависит от состояния системы или иных внешних данных.&lt;/p&gt; -&lt;h3 id=&#34;поиск-обобщенного-решения&#34;&gt;Поиск обобщенного решения&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d0%be%d0%b8%d1%81%d0%ba-%d0%be%d0%b1%d0%be%d0%b1%d1%89%d0%b5%d0%bd%d0%bd%d0%be%d0%b3%d0%be-%d1%80%d0%b5%d1%88%d0%b5%d0%bd%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Вторым способом решения решения проблемы комбинаторного взрыва является уменьшение вычислительной сложности решения. -Тут имеется ввиду не выбор другого алгоритма или решение задачи в символьном виде. -Если такое возможно, то все опять сразу сведется к императивному стилю программированию.&lt;/p&gt; -&lt;p&gt;Я имею ввиду возможность поиска самого алгоритма решения. -Точнее не совсем алгоритма, а возможность применения к входным данным различные методы отбора, чтобы исключить необходимость их полного перебора. -По сути, это сводится к применению различных методов и механизмов обработки входных данных с учетом различных закономерностей.&lt;/p&gt; -&lt;p&gt;Это возможно как алгоритмическими методами (откат и отсечение в Прологе), так и с применением машинного обучения, -которое очень хорошо справляется с поиском различных закономерностей.&lt;/p&gt; -&lt;p&gt;Естественно, такой способ подходит не для всех классов задач. Он не подходит для выявления &lt;strong&gt;ВСЕХ возможных решений&lt;/strong&gt;. -Но там где это не требуется, подобные способы уменьшения вычислительной сложности имеют право на существование.&lt;/p&gt; -&lt;p&gt;Например, не требуется искать все возможные лекарства от конкретной болезни, достаточно &lt;strong&gt;одного&lt;/strong&gt;, с учетом определенных ограничений, которое гарантированно подействует.&lt;/p&gt; -&lt;p&gt;К тому же, даже при нахождении частных решений, всегда существует шанс, что с их помощью получится увидеть не очевидные на первый взгляд закономерности, -которые помогут показать новые пути алгоритмического уменьшения вычислительной сложности основной задачи.&lt;/p&gt; -&lt;h2 id=&#34;область-не-решаемых-задач&#34;&gt;Область не решаемых задач&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bd%d0%b5-%d1%80%d0%b5%d1%88%d0%b0%d0%b5%d0%bc%d1%8b%d1%85-%d0%b7%d0%b0%d0%b4%d0%b0%d1%87&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;blockquote&gt; -&lt;p&gt;Как вы считает, а реально ли создать язык логического программирования, который бы сам умел автоматизировать поиск решений для задач подобных классов? Или хотя бы имел в своем арсенале встроенные механизмы для автоматизации подобной деятельности?&lt;/p&gt; -&lt;/blockquote&gt; -&lt;h3 id=&#34;результаты-опроса-из-оригинальной-публикацииhttpshabrcomarticles536268&#34;&gt;Результаты опроса из &lt;a href=&#34;https://habr.com/articles/536268/&#34;&gt;оригинальной публикации&lt;/a&gt;&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%80%d0%b5%d0%b7%d1%83%d0%bb%d1%8c%d1%82%d0%b0%d1%82%d1%8b-%d0%be%d0%bf%d1%80%d0%be%d1%81%d0%b0-%d0%b8%d0%b7-%d0%be%d1%80%d0%b8%d0%b3%d0%b8%d0%bd%d0%b0%d0%bb%d1%8c%d0%bd%d0%be%d0%b9-%d0%bf%d1%83%d0%b1%d0%bb%d0%b8%d0%ba%d0%b0%d1%86%d0%b8%d0%b8httpshabrcomarticles536268&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;- 57.47% Ха-ха! То, что хочет автор и называется искусственным интеллектом (50 голосов) -- 27.59% Поиск решений нельзя автоматизировать (24 голоса) -- 19.54% Это уже есть и все давно придумано (17 голосов) -- 9.2% Такой язык не нужен, т.к. нейросети могут всё (8 голосов) -- 3.45% Свой вариант написал в комменатрии (3 голоса) -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Проголосовали 87 пользователей. Воздержались 62 пользователя.&lt;/p&gt; - - </description> - </item> - - <item> - <title>Blog: Интернациональное программирование на естественных языках</title> - <link>http://localhost:1313/blog/inter-prog/</link> - <pubDate>Sat, 05 Dec 2020 00:00:00 +0000</pubDate> - - <guid>http://localhost:1313/blog/inter-prog/</guid> - <description> - - - &lt;p&gt;&lt;img alt=&#34;КДПВ&#34; src=&#34;http://localhost:1313/blog/langs.jpeg&#34;&gt;&lt;/p&gt; - - -&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; -&lt;p&gt;Внимание!!!&lt;/p&gt; -&lt;p&gt;Данная статья содержит описание синтаксиса NewLnag предыдущей версии.&lt;/p&gt; -&lt;p&gt;Актуальную версию синтаксиса языка можно посмотреть &lt;a href=&#34;http://localhost:1313/docs/&#34;&gt;тут&lt;/a&gt;.&lt;/p&gt; - -&lt;/div&gt; - -&lt;p&gt;В последнее время часто попадаются на глаза статьи о новых языках программирования, -а так же различные рейтинги и прогнозы, связанные с популярностью компьютерных языков.&lt;/p&gt; -&lt;p&gt;Заявляют о себе и новые &lt;a href=&#34;https://habr.com/company/testo_lang/blog/521682/&#34;&gt;инструментальные средства&lt;/a&gt;, -которые в своей работе используют собственные форматы описания конфигурационных файлов или последовательности выполняемых команд, -которые так же очень сильно приближает их к понятию «язык программирования».&lt;/p&gt; -&lt;p&gt;Цель написания данной статьи — формулировка ожиданий и возможной реализации абстрактного языка программирования, -который может стать универсальным инструментом для общения между компьютером и человеком.&lt;/p&gt; -&lt;h2 id=&#34;о-программистах&#34;&gt;О программистах&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%81%d1%82%d0%b0%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Если начинать с самого начала, то когда-то давно я слышал перефразированное высказывание, -«каждый программист должен написать свою базу данных, текстовый редактор и язык программирования». -И если первые две вещи я уже давным давно написал, то с языком программирования пока не сложилось.&lt;/p&gt; -&lt;p&gt;Ведь как обычно создаются языки программирования?&lt;/p&gt; -&lt;p&gt;У каждого программиста всегда есть какой-то своей предыдущий опыт:&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;знания одного или нескольких языков программирования (как же без этого)&lt;/li&gt; -&lt;li&gt;негативный опыт от их использования (в противном случае, если все устраивает, то зачем придумывать что-то новое?)&lt;/li&gt; -&lt;li&gt;желания получить новые возможности (когда в существующих языках чего-то не хватает)&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;А перед тем, как описывать синтаксис, выбирать ключевые слова и начинать основную работу: -лексер, парсер, базовые библиотеки, нужно дать ответ на основные вопросы:&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Компилятор/интерпретатор/транспилятор(transpiler)?&lt;/li&gt; -&lt;li&gt;Статическая или динамическая типизация?&lt;/li&gt; -&lt;li&gt;Ручное управление памятью или автоматическое со сборщиком мусора?&lt;/li&gt; -&lt;li&gt;Модель программирования: ООП, функциональное, структурное или что-то новое?&lt;/li&gt; -&lt;li&gt;Разрешены ли вставки из других языков программирования и т. д.?&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;У меня, наверно, как и у большинства читателей, присутствует опыт использования нескольких языков программирования. -Поэтому давно сложилось практика, что для решения задачи лучше взять известный язык или даже выучить новый, вместо того, -чтобы начинать писать собственный.&lt;/p&gt; -&lt;p&gt;Тем более, что не хочется придумывать еще один язык просто ради галочки или ради самого языка. -Я считаю, что цель его создания должна быть за пределами потребностей самого разработчика.&lt;/p&gt; -&lt;p&gt;И мне кажется, что удалось определить область, для которой разработка языка программирования может быть востребованной, -а потраченные на него усилия могут принести реальную пользу.&lt;/p&gt; -&lt;h2 id=&#34;о-не-программистах&#34;&gt;О не программистах&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be-%d0%bd%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%81%d1%82%d0%b0%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Эта область — программирование для «не программистов» на «естественном» языке. -Я специально взял слова «не программистов» и «естественном» в кавычки, т.к. эти термины являются очень условными.&lt;/p&gt; -&lt;p&gt;Ведь если не программист начинает программировать, то сам того не осознавая, он автоматически становится программистом ;-). -А «естественным» язык программирования быть не может по определению. -Точнее для компьютеров скорее всего «естественным» будет язык Assembler или набор машинных команд.&lt;/p&gt; -&lt;blockquote&gt; -&lt;p&gt;Поэтому, цель максимум — приблизить язык программирования к естественному человеческому языку.&lt;/p&gt; -&lt;/blockquote&gt; -&lt;p&gt;Это не только сделает чтение текста программы более понятным для не профессионалов, -но и позволит начинать составлять программы просто освоив письменную речь, используя самый минимум основных правил.&lt;/p&gt; -&lt;p&gt;Но в подобной формулировке кроется очень большая проблема!&lt;/p&gt; -&lt;blockquote&gt; -&lt;p&gt;Любой язык программирования является интернациональным, т.к. его синтаксис не зависит от естественного языка, на котором общается программист.&lt;/p&gt; -&lt;/blockquote&gt; -&lt;p&gt;А если текст программы будет на &amp;ldquo;естественном&amp;rdquo; языке, то она станет понятной только для знающих этот язык, -одновременно становясь непонятной для всех остальных.&lt;/p&gt; -&lt;p&gt;В качестве иллюстрации: &lt;a href=&#34;http://espressocode.top/natural-language-programming/&#34;&gt;раз&lt;/a&gt; или &lt;a href=&#34;https://habr.com/post/268401/&#34;&gt;два&lt;/a&gt;. -Если пофантазировать насчет хотелок к такому языку, то видятся следующие требования и ограничения:&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Так как каждый пользователь является носителем своего родного естественного языка (или даже нескольких), то жестко задавать ключевые слова невозможно, из чего следует, что основой такого языка должны стать только правила пунктуации, но никак не лексика или грамматика.&lt;/li&gt; -&lt;li&gt;Компилятор/транслятор должен уметь преобразовывать исходный текст программы не только в машинный код для компьютера, но в другой вариант &amp;ldquo;естественного&amp;rdquo; языка, чтобы пользователь мог работать с исходным текстом на известном ему &amp;ldquo;естественном&amp;rdquo; языке.&lt;/li&gt; -&lt;li&gt;Очень хочется видеть в новом языке &lt;del&gt;толерантность&lt;/del&gt; терпимость к очепяткам. Подобная «фича» присутствует в письме на естественном языке, и несмотря на наличие опечаток, практически всегда сохраняется смысл. Естественно, в данном случае не стоит доходить до фанатизма. Компилятор не читает мысли и не может в действительности «понять», что имел ввиду пользователь, и все же довольно часто можно игнорировать опечатки в тексте программы исходя из контекста (пусть и с выводом предупреждающих сообщений).&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;Тем не менее, такой язык должен оставаться именно языком программирования со всеми возможностями создания программ любого уровня сложности, -включая функциональное и объектно-ориентированное программирование и однозначное понимание написанного.&lt;/p&gt; -&lt;h2 id=&#34;о-гипотетическом-языке&#34;&gt;О гипотетическом языке&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be-%d0%b3%d0%b8%d0%bf%d0%be%d1%82%d0%b5%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%be%d0%bc-%d1%8f%d0%b7%d1%8b%d0%ba%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Если взять за основу правила письменной речи, то основные соглашения и пунктуация для нового языка могут выглядеть примерно так:&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Любой текст состоит из предложений и комментариев. Предложения обрабатываются, а комментарии игнорируются.&lt;/li&gt; -&lt;li&gt;Предложение состоит из последовательности терминов, литералов и символов, разделенных пробелами и знаками препинания и завершается символом конца предложения.&lt;/li&gt; -&lt;li&gt;Термин — слитно написанная последовательность букв, цифр и символов &amp;ldquo;:&amp;rdquo; и &amp;ldquo;_&amp;rdquo;.&lt;/li&gt; -&lt;li&gt;Литерал — константы, включаемые непосредственно в текст программы, тип которой определяется однозначно. Это символьные строки в кавычках, целые и вещественные числа, и некоторые специальные форматы (время, дата).&lt;/li&gt; -&lt;li&gt;Символы — все остальное символы, которые не относятся к знакам препинания, пробельным символам, цифрам и буквам.&lt;/li&gt; -&lt;li&gt;Знаки препинания — символы пунктуации, имеющие специальное значение при разборе текста программы: -&lt;ul&gt; -&lt;li&gt;«.»,«;»,«!»,«?»,«…» — конец предложения.&lt;/li&gt; -&lt;li&gt;«=» — присвоение значения.&lt;/li&gt; -&lt;li&gt;&amp;quot;&amp;quot; (кавычки) — определение символьной строки.&lt;/li&gt; -&lt;li&gt;«()» - передача параметров/аргументов или группировка операторов для определения приоритета выполнения операций.&lt;/li&gt; -&lt;li&gt;«[]» - массив или обращение к элементу массива.&lt;/li&gt; -&lt;li&gt;«{}» - включение в текст исходного кода программы на обычном языке программирования.&lt;/li&gt; -&lt;li&gt;«$» — системная переменная.&lt;/li&gt; -&lt;li&gt;«@» — системная функция.&lt;/li&gt; -&lt;li&gt;«,» (запятая) — перечисление.&lt;/li&gt; -&lt;li&gt;«:» (двоеточие) — список или логическая связь.&lt;/li&gt; -&lt;/ul&gt; -&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;Если с символом присвоения, кавычками, круглыми и квадратными скобками все должно быть более-менее понятно, -т.к. их назначение соответствует аналогичному в подавляющем большинстве языков программирования, -то про назначение остальных символов (фигурных скобок, двоеточия, запятой и системных функций/переменной), следует немного пояснить.&lt;/p&gt; -&lt;p&gt;Раз цель гипотетического языка программирования все же написание программ, -то необходимо предусмотреть возможность делать вставки обычного программного кода без учета всех возможностей и неоднозначностей, -которые присущи любому естественному языку.&lt;/p&gt; -&lt;p&gt;Так же эта возможность требуется для реализации низкоуровневых функций и для взаимодействия с внешними библиотеками.&lt;/p&gt; -&lt;p&gt;При создании подобных вставок и могут использоваться фигурные скобки, весь текст между которыми будет вставляться в итоговый файл практически без обработки.&lt;/p&gt; -&lt;p&gt;Для похожих целей служат и символы «$» — системная переменная и «@» — системная функция. Если такой символ поставить в начале слова, -тогда он станет обозначать объект с соответствующим назначением. Например «@exit» — будет означать функцию, -а «$var» — переменную с соответствующими именами, а сами объекты станут доступны как в обычном коде, -так и в программных вставках внутри фигурных скобок.&lt;/p&gt; -&lt;p&gt;Аналогичным образом организуется и доступ к отдельным полям/методам объектов: -«объект@метод» или «объект$поле».&lt;/p&gt; -&lt;p&gt;Символ запятая «,» применяется для указание последовательности равноправных логических блоков в одном предложении или для создания списков.&lt;/p&gt; -&lt;p&gt;Символ двоеточия «:» используется для создания списков и для обозначения логической связи между двумя частями слова/текста, в том числе для указания полного пути модуля.&lt;/p&gt; -&lt;p&gt;Например, создание списка:&lt;/p&gt; -&lt;p&gt;&lt;code&gt;В_строку: элемент 1, элемент 2, последний элемент.&lt;/code&gt;&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Форматированный_список: -- элемент 1; -- элемент 2; -- последний элемент. -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Логическое следствие/указание связи:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;module:calc //термин «calc», который находится в модуле «module» -super:module:example$var //переменная «$var» которая находится в указанной иерархии. -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Как можно заметить, использование знаков препинания взято из их прямого назначения, принятого в письменной речи, -что должно обеспечить определенный компромисс между синтаксисом в стандартных языках программирования и письмом на естественном языке.&lt;/p&gt; -&lt;h2 id=&#34;о-компьютерах&#34;&gt;О компьютерах&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be-%d0%ba%d0%be%d0%bc%d0%bf%d1%8c%d1%8e%d1%82%d0%b5%d1%80%d0%b0%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Так как речь идет все же о языке программирования, то не обойтись без стандартных алгоритмических конструкций: следования, ветвления и циклов.&lt;/p&gt; -&lt;p&gt;Следование легко описывается обычными правилам письма на естественном языке. -В случае последовательного выполнения в одном предложении, операции и вызовы функций записываются последовательно через запятую. -Если они располагаются в разных предложениях, то они записываются так же друг за другом. -Причем форматирование по абзацам служит только для лучшего восприятия текста и логического разделения отдельных фрагментов.&lt;/p&gt; -&lt;p&gt;При создании условных и циклических управляющих конструкций уже потребуются ключевые слова. -Но так как согласно исходным пожеланиям к языку, резервировать обычные термины для записи алгоритмических конструкций нельзя, -то перед ключевыми словами достаточно указывать символ системной функции, что позволит отличить обычный термин от ключевого (управляющего) слова.&lt;/p&gt; -&lt;p&gt;Естественно, при программировании, данными терминами хоть и можно будет пользоваться, но делать это совсем не обязательно. -Так как при настройке под конкретный естественный язык, системным функциям и ключевым словам нужно обязательно присвоить конкретные термины и пользоваться уже ими, например:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;перейти = @goto, -метка = @label, -продолжить = @continue, -прервать=@break и т.д. -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;И последняя по очереди, но наверно самая важная по сути конструкция: передача параметров при вызовах функций. -Если стремиться к полностью естественному синтаксису, тогда мы получим тот самый естественный язык, который очень сложно анализировать.&lt;/p&gt; -&lt;p&gt;Тем не менее, мне кажется, что можно скомбинировать оба два подхода, если отказаться от обязательного использования круглых скобок, -там, где это допустимо по синтаксису.&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Компьютерный: функция(параметр1, функция2(), параметр3=значение). -Естественный: функция параметр1 функция2 параметр3=значение. -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Но:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Компьютерный: функция( функция2(параметр) ). -Естественный: функция функция2(параметр). -Или так: функция (функция2 параметр). -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Другими словами, для естественного порядка указания аргументов, скобки для функций и запятые между параметрами могут быть опущены. -Хотя их использование должно определяться в первую очередь целевым естественным языком, а не синтаксисом.&lt;/p&gt; -&lt;h2 id=&#34;о-возражениях&#34;&gt;О возражениях&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be-%d0%b2%d0%be%d0%b7%d1%80%d0%b0%d0%b6%d0%b5%d0%bd%d0%b8%d1%8f%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Предвижу обоснованные возражения против использования подобного языка со стороны программистов. -Программа на нем по любому получится значительно многословнее, чем с использованием строгого формального синтаксиса обычных компьютерных языков.&lt;/p&gt; -&lt;p&gt;Поэтому напомню про его обязательное свойство - умение преобразовывать текст программы с одного языка на другой. -Это позволяет писать программы как с использованием строго формального синтаксиса без использования переопеределенных терминов на естественном языке, -так и преобразовывать исходный текст в &amp;ldquo;естественный&amp;rdquo; язык для &amp;ldquo;не программиста&amp;rdquo;.&lt;/p&gt; -&lt;p&gt;&lt;a href=&#34;https://habr.com/articles/531400/&#34;&gt;Ссылка на первую публикаци&lt;/a&gt;&lt;/p&gt; - - </description> - </item> - </channel> </rss> diff --git a/docs/offline-search-index.json b/docs/offline-search-index.json index b9b937a8..cc4dce2a 100644 --- a/docs/offline-search-index.json +++ b/docs/offline-search-index.json @@ -1 +1 @@ -[{"body":" Операторы разделяются точкой с запятой «;». Отступы и переводы строк игнорируются. Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash. Многострочные комментарии соответствуют стилю С/С++ и должны располагаться между символами /* и */. Многосточные комментарии могут быть вложенными. Последовательность команд (блок кода) заключаются в фигурные скобки “{” и “}”. Большинство операторов являются выражениями и возвращают результат выполнения последней операции. ","categories":"","description":"Правила синтаксиса и основные понятия языка программирования NewLang \n","excerpt":"Правила синтаксиса и основные понятия языка программирования NewLang \n","ref":"/docs/syntax/","tags":"","title":"Синтаксис"},{"body":" Операторы разделяются точкой с запятой «;». Отступы и переводы строк игнорируются. Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash. Многострочные комментарии соответствуют стилю С/С++ и должны располагаться между символами /* и */. Многосточные комментарии могут быть вложенными. Последовательность команд (блок кода) заключаются в фигурные скобки “{” и “}”. Большинство операторов являются выражениями и возвращают результат выполнения последней операции. ","categories":"","description":"Правила синтаксиса и основные понятия языка программирования NewLang \n","excerpt":"Правила синтаксиса и основные понятия языка программирования NewLang \n","ref":"/ru/docs/syntax/","tags":"","title":"Синтаксис"},{"body":"NewLang является языком с динамической типизацией и явное указание типа переменной не обязательно и на прямую не влияет на размер памяти, котрую она занимает. Тип переменных используется при проверке их совместимости, когда существующему объекту присваивается другое значение.\nПрисвоение нового значения переменной возможно только тогда, когда типы данных между собой совместимы или допускают автоматическое приведение. Это справедливо как во время компиляции исходного теста, так и во время выполнения.\nNewLang имеет закрытую иерархическую систему типов, т.е. любой новый тип данных, которые создает пользователь, обязательно должен быть наследником от уже существующего. Это напоминает реализуцию ООП в яызке Java, где каждый класс имеет в своем составе наследников Object.\nЗа счет закрытой иерархии типов реализуется и парадигма обобщённого программирования (generics).\nКаждый тип данных имеет краткое имя и функцию - конструктор.\nКраткое имя типа всегда начинается с символа двоеточия “:” и определяется в глобальной области видимости.\nФункция - конструктора типа, имеет тоже самое краткое имя типа, но без символа двоеточия “:”, и как и любая функция может располагаться в пользовательском пространстве имен.\nСоздать новый экземпляр типа нужно вызвать функцию - конструтор типа.\nСоздать новый экземпляр типа данных можно записав краткое имя типа как вызов функции, либо вызвать непосредственно функцию - конструтор типа, с указанием её полного пространства имен.\nТипы данных могут быть синонимами, т.е. два типа данных могут иметь одинаковое краткое имя, (соответствено, и одитнаковые функции конструкторы), но сами функции должны располагаться в разных областях пространства имен.\nВ этом случае, создание объекта - синонима типа, требует вызова функции конструктора с указанием её полного пространства имен, в противном случае будет вызвана функция согласно алгоритму разрешения имен (name lookup). .\nВозможно явное приведение одного типа данных к дргуому. Для этого применяется краткое имя (которое начинается с символа двоеточия “:”), как вызов функции, в параметрах которой передается один или несколько объектов, тип которых нужно привести к требуемому.\nТипы данных разделяются на простые и сложные (составные).\nПростые типы данных не могут Поля у простых типов данных не могут быть расширены\nСоздание типов происходит согласно правилам синтаксиса. Имя типа всегда начинается с символа двоеточия “:” и определяется в глобальной области видимости. Создание сложных типов (классов), может располагаться в пользовательском пространстве имен.\n, в том числе и конструктор классов, ","categories":"","description":"","excerpt":"NewLang является языком с динамической типизацией и явное указание …","ref":"/docs/types/","tags":"","title":"Типы данных"},{"body":"NewLang является языком с динамической типизацией и явное указание типа переменной не обязательно и на прямую не влияет на размер памяти, котрую она занимает. Тип переменных используется при проверке их совместимости, когда существующему объекту присваивается другое значение.\nПрисвоение нового значения переменной возможно только тогда, когда типы данных между собой совместимы или допускают автоматическое приведение. Это справедливо как во время компиляции исходного теста, так и во время выполнения.\nNewLang имеет закрытую иерархическую систему типов, т.е. любой новый тип данных, которые создает пользователь, обязательно должен быть наследником от уже существующего. Это напоминает реализуцию ООП в яызке Java, где каждый класс имеет в своем составе наследников Object.\nЗа счет закрытой иерархии типов реализуется и парадигма обобщённого программирования (generics).\nКаждый тип данных имеет краткое имя и функцию - конструктор.\nКраткое имя типа всегда начинается с символа двоеточия “:” и определяется в глобальной области видимости.\nФункция - конструктора типа, имеет тоже самое краткое имя типа, но без символа двоеточия “:”, и как и любая функция может располагаться в пользовательском пространстве имен.\nСоздать новый экземпляр типа нужно вызвать функцию - конструтор типа.\nСоздать новый экземпляр типа данных можно записав краткое имя типа как вызов функции, либо вызвать непосредственно функцию - конструтор типа, с указанием её полного пространства имен.\nТипы данных могут быть синонимами, т.е. два типа данных могут иметь одинаковое краткое имя, (соответствено, и одитнаковые функции конструкторы), но сами функции должны располагаться в разных областях пространства имен.\nВ этом случае, создание объекта - синонима типа, требует вызова функции конструктора с указанием её полного пространства имен, в противном случае будет вызвана функция согласно алгоритму разрешения имен (name lookup). .\nВозможно явное приведение одного типа данных к дргуому. Для этого применяется краткое имя (которое начинается с символа двоеточия “:”), как вызов функции, в параметрах которой передается один или несколько объектов, тип которых нужно привести к требуемому.\nТипы данных разделяются на простые и сложные (составные).\nПростые типы данных не могут Поля у простых типов данных не могут быть расширены\nСоздание типов происходит согласно правилам синтаксиса. Имя типа всегда начинается с символа двоеточия “:” и определяется в глобальной области видимости. Создание сложных типов (классов), может располагаться в пользовательском пространстве имен.\n, в том числе и конструктор классов, ","categories":"","description":"","excerpt":"NewLang является языком с динамической типизацией и явное указание …","ref":"/ru/docs/types/","tags":"","title":"Типы данных"},{"body":"Один из самых недооценных операторов, которй отсутствует в большинстве высокоуровневых языков программирования, это переменная с результатом выполнения предыдущей операции. В NewLang это системная переменная $^ (или DSL макрос @result), в которой всегда хранится результат выполнения последней операции (оператора).\nЭто чем-то похоже на глобальное значние error(), но не только для кода ошибки, а для значения любого оператора.\nПри её использовании многие синтаксические конструкции языка значительно упрощаются, так как не требуется предусматривать определение локальных переменных для сохранения промежуточных данных, например при возникновении ошибки.\n","categories":"","description":"","excerpt":"Один из самых недооценных операторов, которй отсутствует в большинстве …","ref":"/docs/ops/","tags":"","title":"Операторы и управляющие конструкции"},{"body":"Один из самых недооценных операторов, которй отсутствует в большинстве высокоуровневых языков программирования, это переменная с результатом выполнения предыдущей операции. В NewLang это системная переменная $^ (или DSL макрос @result), в которой всегда хранится результат выполнения последней операции (оператора).\nЭто чем-то похоже на глобальное значние error(), но не только для кода ошибки, а для значения любого оператора.\nПри её использовании многие синтаксические конструкции языка значительно упрощаются, так как не требуется предусматривать определение локальных переменных для сохранения промежуточных данных, например при возникновении ошибки.\n","categories":"","description":"","excerpt":"Один из самых недооценных операторов, которй отсутствует в большинстве …","ref":"/ru/docs/ops/","tags":"","title":"Операторы и управляющие конструкции"},{"body":"Ключем поиска объектов явялется строка с полным именем в иерархии имен относительно корня\nСистема классов реализации RunTime - единственный класс для приложения (процесса) - интерфейс для взаимодействия с операционной системой\nЗагружат и выгружает модули и является их владельцем (shared_ptr) Хранит глобальные объекты (ObjPtr) для глобальных объектов (встроенных типов и функций). Ключем явялется строка с полным именем объекта в иерархии имен относительно корня Хранит список глобальных объектов (типы данных и прототипы функций в TermPtr, которые создаются на этапе компиляции). Используется парсером и компилятором для разбора исходного текста и создания исполняемого файла. Module - класс для модуля\nХранение объектов модуля (shared_ptr) и добавляет weak_ptr в глобальный список объектов в RunTime Context - класс для хранения временных данных при выполнении программы\nОдин класс создается сразу при создании RunTime В дальнейшем создается по одному объекту для каждого нового потока (:Thread) Хранение списка объектов (weak_ptr) Хранение локальных объектов (ObjPtr), которые создаются на этапе выполнения Исходный текст -\u003e Парсинг -\u003e AST (TermPtr) -+-\u003e Компиляция в модуль (LLVM) -\u003e Выполнение модуля | +-\u003e Интерпретация (Выполнение AST)\nРеализация загрузки модулей и пакетов Загрузка модулей происодит следующим образом. Когда во время парсинга исходного текста встречается команда загруки модуля, создается отдельный экземпляр парсера, которому на вход подается исходный текст загружаемого модуля.\nЗагружаемый модуль парсится как обучный файл (включая обработку вложенных модулей), после чего парсер завершает работу. В результате получается отдельное AST загружаемого модуля и общая база макросов. После этого в AST модуля раскрываются области имен, производится проверка имен объетов и создание единой базы глобальных объектов.\nПосле проверки отдельного AST модуля, обработка текущего файла моедт быть прожолжена. После завершения обарботки файла раскрываются области имен, производится проверка имен объетов и создание единой базы глобальных объектов как и в случае с обработко отдельного AST модуля.\nПри такой схеме работы, компиляция отдельных AST у каждого модуля может производиться параллельно с остальными моделями, а создание общего исоплняемого файла после компиляции всех используемых модулей.\nЗагрузка пакета обработывается точто таким же образом, как и загрузка моделя.\nШаги сборки компилятора Сборка nlc Генерация с помощью nlc --no-runtime --no-dsl -emit-cpp модуля dsl Сборка модуля dsl Генерация с помощью nlc --no-runtime -emit-cpp пакета runtime Сборка пакета runtime В результате имеем готовый nlc с модулями runtime.nlm и dsl.nlm, а заодно и проверяем:\nгенерацию С++ кода без макросов сборку модуля загрузку модуля генерацию С++ кода с макросами сборку пакета загрузку пакета Выполнение тестов с модулями runtime.nlm и dsl.nlm\nОпции компилятора -no-dsl - не использовать автоматически загружаемый модуль dsl -no-runtime - не использовать автоматически загружаемый модуль runtime -emit-cpp - генерировать выходной *.cpp файл 5.5. alignas(N) Этот спецификатор появился в C++11. Применяется к простым переменным, массивам и классам. N — это выражение, вычисляемое при компиляции, его значение должно быть степенью двойки. Переменная при этом будет размещена по адресу, кратному значению N. Например:\nalignas(64) char cacheline[64]; cacheline:Int8[64](__alignas__=64) := _; constexpr Этот спецификатор появился в C++11. Применяется к простым переменным, массивам, функциям и функциям-членам. Для простой переменной или массива это означает, что ее значение вычисляется на этапе компиляции и не может быть изменено. Для функции это означает, что ее возвращаемое значение вычисляется на этапе компиляции, если значения аргументов известно на стадии компиляции. (Но такую функцию можно использовать и с обычными аргументами.) Вот пример:\nconstexpr double PI = 3.1415926535897932; constexpr int Square(int x) { return x * x; } PI^:Double = 3.1415926535897932; Square^(x:Int64):Int64 ::= { return x * x; } 5.7. consteval Этот спецификатор появился в C++20. Применяется к функциям и функциям-членам. Это более строгий вариант constexpr, при вызове такой функции значения аргументов должны быть всегда известны на стадии компиляции.\n????????????????????????????????????? Square^(x^:Int64):Int64 ::= { return x * x; } 5.8. noexcept Этот спецификатор появился в C++11. Применяется к функциям и функциям-членам и располагается в конце инструкции, после списка параметров. Этот спецификатор гарантирует отсутствие исключений в процессе выполнения тела функции.\nfunc() ::= {* *}; 5.9. mutable Применяются к нестатическим членам класса, такие члены можно изменять в константных функциях-членах (см. раздел 5.10.1).\nВ C++20 для агрегатных типов появилась еще назначенная инициализация (designated initialization): struct Point { int X; int Y; };\nPoint pt = { .X = 1, .Y = 2 };\nЭта инициализация позаимствована из C. Инициализируемые члены могут быть опущены и не только в конце, для них гарантируется инициализация по умолчанию. В отличие от C, порядок членов изменять нельзя, он должен быть таким же, как и при объявлении.\n","categories":"","description":"Описание реализация архитектуры для лучшего понимания отдельных важных моментов\n","excerpt":"Описание реализация архитектуры для лучшего понимания отдельных важных …","ref":"/docs/arch/","tags":"","title":"Архитектура"},{"body":"Система классов реализации RunTime - единственный класс для приложения (процесса) - интерфейс для взаимодействия с операционной системой\nЗагружат и выгружает модули и является их владельцем (shared_ptr) Хранит сслыки на глобальные объекты (WeakPtr) и непосредственно глобальные объекты (встроенные типы и функции). Ключем явялется строка с внутренним именем объекта Хранит список глобальных объектов (типы данных и прототипы функций, которые создаются на этапе компиляции). Используется парсером и компилятором для разбора исходного текста и создания исполняемого файла. Module - класс для модуля\nХранение объектов модуля (shared_ptr) и добавляет weak_ptr в глобальный список объектов в RunTime Context - класс для хранения временных данных при выполнении программы\nОдин класс создается сразу при создании RunTime В дальнейшем создается по одному объекту для каждого нового потока (:Thread) Хранение списка объектов (weak_ptr) Хранение локальных объектов (ObjPtr), которые создаются на этапе выполнения Исходный текст -\u003e Парсинг -\u003e AST (TermPtr) -+-\u003e Компиляция в модуль (LLVM) -\u003e Выполнение модуля | +-\u003e Интерпретация (Выполнение AST)\nРеализация загрузки модулей и пакетов Загрузка модулей происодит следующим образом. Когда во время парсинга исходного текста встречается команда загруки модуля, создается отдельный экземпляр парсера, которому на вход подается исходный текст загружаемого модуля.\nЗагружаемый модуль парсится как обучный файл (включая обработку вложенных модулей), после чего парсер завершает работу. В результате получается отдельное AST загружаемого модуля и общая база макросов. После этого в AST модуля раскрываются области имен, производится проверка имен объетов и создание единой базы глобальных объектов.\nПосле проверки отдельного AST модуля, обработка текущего файла моедт быть прожолжена. После завершения обарботки файла раскрываются области имен, производится проверка имен объетов и создание единой базы глобальных объектов как и в случае с обработко отдельного AST модуля.\nПри такой схеме работы, компиляция отдельных AST у каждого модуля может производиться параллельно с остальными моделями, а создание общего исоплняемого файла после компиляции всех используемых модулей.\nЗагрузка пакета обработывается точто таким же образом, как и загрузка моделя.\nШаги сборки компилятора Сборка nlc Генерация с помощью nlc --no-runtime --no-dsl -emit-cpp модуля dsl Сборка модуля dsl Генерация с помощью nlc --no-runtime -emit-cpp пакета runtime Сборка пакета runtime В результате имеем готовый nlc с модулями runtime.nlm и dsl.nlm, а заодно и проверяем:\nгенерацию С++ кода без макросов сборку модуля загрузку модуля генерацию С++ кода с макросами сборку пакета загрузку пакета Выполнение тестов с модулями runtime.nlm и dsl.nlm\nОпции компилятора -no-dsl - не использовать автоматически загружаемый модуль dsl -no-runtime - не использовать автоматически загружаемый модуль runtime -emit-cpp - генерировать выходной *.cpp файл 5.5. alignas(N) Этот спецификатор появился в C++11. Применяется к простым переменным, массивам и классам. N — это выражение, вычисляемое при компиляции, его значение должно быть степенью двойки. Переменная при этом будет размещена по адресу, кратному значению N. Например:\nalignas(64) char cacheline[64]; cacheline:Int8[64](__alignas__=64) := _; constexpr Этот спецификатор появился в C++11. Применяется к простым переменным, массивам, функциям и функциям-членам. Для простой переменной или массива это означает, что ее значение вычисляется на этапе компиляции и не может быть изменено. Для функции это означает, что ее возвращаемое значение вычисляется на этапе компиляции, если значения аргументов известно на стадии компиляции. (Но такую функцию можно использовать и с обычными аргументами.) Вот пример:\nconstexpr double PI = 3.1415926535897932; constexpr int Square(int x) { return x * x; } PI^:Double = 3.1415926535897932; Square^(x:Int64):Int64 ::= { return x * x; } 5.7. consteval Этот спецификатор появился в C++20. Применяется к функциям и функциям-членам. Это более строгий вариант constexpr, при вызове такой функции значения аргументов должны быть всегда известны на стадии компиляции.\n????????????????????????????????????? Square^(x^:Int64):Int64 ::= { return x * x; } 5.8. noexcept Этот спецификатор появился в C++11. Применяется к функциям и функциям-членам и располагается в конце инструкции, после списка параметров. Этот спецификатор гарантирует отсутствие исключений в процессе выполнения тела функции.\nfunc() ::= {* *}; 5.9. mutable Применяются к нестатическим членам класса, такие члены можно изменять в константных функциях-членах (см. раздел 5.10.1).\nВ C++20 для агрегатных типов появилась еще назначенная инициализация (designated initialization): struct Point { int X; int Y; };\nPoint pt = { .X = 1, .Y = 2 };\nЭта инициализация позаимствована из C. Инициализируемые члены могут быть опущены и не только в конце, для них гарантируется инициализация по умолчанию. В отличие от C, порядок членов изменять нельзя, он должен быть таким же, как и при объявлении.\n","categories":"","description":"Описание архитектуры компилятора для и конкретных технических решений\n","excerpt":"Описание архитектуры компилятора для и конкретных технических решений\n","ref":"/ru/docs/arch/","tags":"","title":"Архитектура"},{"body":"NewLang имеет закрытую систему типов. т.е. любой новый тип данных, которые создает пользователь, обязательно должен быть наследником одного из уже существующих, т.е. расширять один из них. Такой поход напоминает создание классов в языке Java, в котором каждый новый класс имеет в своих родителях класс Object.\nС помощью обобщений (generics) можно писать код, который может работать с любым совместимым типом данных.\nФрагмент иерархии типов данных (строки и числа, а в скобках указаны синонимы типов):\n:Any -+-\u003e :Arithmetic -+-\u003e :Tensor -+-\u003e :Integer --\u003e :Int64 ... --\u003e :Int8 --\u003e :Bool | | | (:DWord64) (:Char) | | | (:Byte) | | | | | +-\u003e :Number --\u003e :Float64 --\u003e :Float32 --\u003e :Float16 --\u003e ... | | | (:Double) (:Single) | | | | | +-\u003e :Complex ... | | | +-\u003e :Rational | +-\u003e :String -+-\u003e :StrChar | | (:FmtChar) | | | +-\u003e :StrWide | (:FmtWide) | | ... Обобщенные типы :Any - обобщенный тип для всех остальных типов данных :Arithmetic - обобщенный тип для всех числовых типов :Tensor - обобщенный тип для чисел, которые можно представить в машинном формате :Integer - обощенный тип для всех целочисленных типов данных :Number - обощенный тип для всех чисел с плавающей точкой :Complex - обощенный тип для всех комплексных чисел :String - обощенный тип для текстовых строк Примеры определения функций с обобщенными типами only_int8(arg:Int8):Int8 := ... ; # Функиця принимает и возвращает только :Int8 any_int(arg:Integer):Integer := ... ; # Функиця принимает и возвращает только целые числа any_tensor(arg:Tensor):Tensor := ... ;# Функиця принимает и возвращает любые машинные типы чисел any_any1(arg:Any):None := ... ; # Функиця принимает любой тип аргумента и ничего не возвращает any_any2(arg) := ... ; # Тип не указан - функиця можен принимать и возвращать любой тип ","categories":"","description":"","excerpt":"NewLang имеет закрытую систему типов. т.е. любой новый тип данных, …","ref":"/docs/types/generics/","tags":["типы данных","ООП","коллекции"],"title":"Иерархия типов и обобщения"},{"body":"NewLang имеет закрытую систему типов. т.е. любой новый тип данных, которые создает пользователь, обязательно должен быть наследником одного из уже существующих, т.е. расширять один из них. Такой поход напоминает создание классов в языке Java, в котором каждый новый класс имеет в своих родителях класс Object.\nС помощью обобщений (generics) можно писать код, который может работать с любым совместимым типом данных.\nФрагмент иерархии типов данных (строки и числа, а в скобках указаны синонимы типов):\n:Any -+-\u003e :Arithmetic -+-\u003e :Tensor -+-\u003e :Integer --\u003e :Int64 ... --\u003e :Int8 --\u003e :Bool | | | (:DWord64) (:Char) | | | (:Byte) | | | | | +-\u003e :Number --\u003e :Float64 --\u003e :Float32 --\u003e :Float16 --\u003e ... | | | (:Double) (:Single) | | | | | +-\u003e :Complex ... | | | +-\u003e :Rational | +-\u003e :String -+-\u003e :StrChar | | (:FmtChar) | | | +-\u003e :StrWide | (:FmtWide) | | ... Обобщенные типы :Any - обобщенный тип для всех остальных типов данных :Arithmetic - обобщенный тип для всех числовых типов :Tensor - обобщенный тип для чисел, которые можно представить в машинном формате :Integer - обощенный тип для всех целочисленных типов данных :Number - обощенный тип для всех чисел с плавающей точкой :Complex - обощенный тип для всех комплексных чисел :String - обощенный тип для текстовых строк Примеры определения функций с обобщенными типами only_int8(arg:Int8):Int8 := ... ; # Функиця принимает и возвращает только :Int8 any_int(arg:Integer):Integer := ... ; # Функиця принимает и возвращает только целые числа any_tensor(arg:Tensor):Tensor := ... ;# Функиця принимает и возвращает любые машинные типы чисел any_any1(arg:Any):None := ... ; # Функиця принимает любой тип аргумента и ничего не возвращает any_any2(arg) := ... ; # Тип не указан - функиця можен принимать и возвращать любой тип ","categories":"","description":"","excerpt":"NewLang имеет закрытую систему типов. т.е. любой новый тип данных, …","ref":"/ru/docs/types/generics/","tags":["типы данных","ООП","коллекции"],"title":"Иерархия типов и обобщения"},{"body":"Objects and data types can be named using letters, numbers, and underscores in any combination, provided that the first character of the name is not a digit.\nAll identifiers must be unique, and to avoid collisions, you can use namespaces and a modular code structure supported simultaneously by NewLang.\nOverloading functions based on argument types is absent in NewLang, so defining multiple functions with the same name but different arguments is not possible, but you can override a function, including extending the types of accepted arguments or increasing their number.\nAn object identifier can contain one or more special characters - qualifiers (or sigils), which represent specific values. An object identifier that does not contain a qualifier is called simple:\nName Qualifiers: ‘@’ - the at sign prefix is used to specify the name of a macro, which is processed by the preprocessor before the start of the program’s syntactic analysis. ‘@’ - the at prefix is used to specify the name of a macro that is processed by the preprocessor before the start of the syntactic analysis of the source code of the program. ‘$’ - the dollar sign at the beginning of an object’s name denotes an automatic name for a temporary variable, the memory space for which is dynamically allocated during the application’s execution, and the lifetime is limited by the language semantics. ‘::’ - the double colon serves as a separator for namespaces and indicates a static object, the memory space for which is allocated during the compilation of the application or module. If the name starts with ‘::’, the object’s scope will be global and it will be accessible throughout the application. Otherwise, the object’s visibility will be limited to the current program module. ‘.’ - the dot prefix is used when accessing a module or class field (limits the scope to the current object). The dot prefix can be used when defining (calling) a function to explicitly identify a named argument, preventing it from being overridden by a preprocessor macro. ‘\\’ - the backslash at the beginning of a term denotes the name of a program module, and also separates directory names in the hierarchy of program module placement. ‘:’ — colon at the beginning of the term denotes the name of a data type or a class constructor ‘%’ — the percent sign prefix is used for imported symbols (native variables and functions) ‘^’ — the caret symbol after the name is used to give immutability (constancy, non-modifiability) to the object. Name Lookup If the object name does not contain a qualifier, it is called simple. Creating an object with a simple name is equivalent to creating a local object.\nIn other cases, when NewLang encounters a simple object name without a qualifier (sigil), a special algorithm comes into play that associates the simple name found in the source code of the program with its declaration or a specific object by its internal name.\nResolution of simple names without a qualifier (name lookup for function/variable names) always occurs in a strictly defined order:\nFirst, the search for the name is among macros Next, the search is among local objects up to objects of the current module Lastly, the search is among global objects with a gradual expansion of the namespace search scope from current to global Such a sequence of name resolution always provides the opportunity to redefine global/local objects or argument names in functions for existing code without serious changes.\nFor example, for the name name in the namespace ns, the search occurs in the following sequence: @name -\u003e $name -\u003e ns::name -\u003e ::ns::name -\u003e ::name, and for the name arg, only @arg is checked:\nns:: { name(arg=\"value\"); }; And at the same time, there will always be the possibility to specify a specific object regardless of the algorithm for resolving simple names. It is sufficient to explicitly specify the qualifier in the object name.\nFor example, to access the global object name from the namespace ns in the above example, you need to use the full object name ::ns::name, and the named argument ’. arg’ will not be replaced by the @arg macro if it is defined:\n::ns::name(.arg=\"value\"); Forward Declaration In the program text, you can only refer to actually existing (created) objects. But in cases where it is necessary to refer to an object that is created in another module or will be created later, you can make a preliminary declaration, in which the compiler registers the name and type of the object without its actual creation.\nBy means of a forward declaration, one can refer only to static objects (data types), or local class fields that the compiler does not yet know about but which will be defined during the compilation process later.\nFor a forward declaration, only the fully qualified name can be used, which must exactly match the object’s name when it is subsequently created.\nThe same syntax is used for a forward declaration as for the actual creation of an object, only an ellipsis should be specified to the right of the creation operator.\nThe scope of a forward declaration corresponds to the scope of its placement, not the actual scope of the object (even for global objects).\n# Preliminary definition of a module variable # Applies to the entire module var_module:Int32 := ...; func() ::= { # Preliminary announcement using DSL # (only works inside a function body) @declare( func2(arg:Int32):Int32 ); var_module = func2(var_module); @return var_module; }; func2(arg:Int32):Int32 ::= { @return $arg*$arg; } var_module:Int32 := 1; Argument Names, Special, System Names The notation of argument names in functions is very similar to referencing arguments in bash scripts, where “$1” or “$name” represents the ordinal number or name of the corresponding argument.\nThe reserved name “$0” denotes the current object, and the name “$$” denotes the parent object.\nAll function arguments are collected in a single dictionary with the special name $*\nThe immutable variable “$^” contains the result of the last operator or code block execution.\nThe full name of the current module is contained in the variable @\\\\, and the current namespace in the variable @::, i.e.:\n# File name filename.src in directory dir ns:: { # Use namespace ns name:: { # Preprocessor command \"@#\" - convert to a string ns_str := @# @::; # String with namespase \"::ns::name::\" mod_str := @# @\\\\; # String with module name \"\\\\dir\\filename\" }; }; Scope The underscore symbol, as well as an underscore at the beginning of a name or double underscores at the beginning and end of a name, have special meanings.\nA single underscore corresponds to a protected, and two underscores to a private scope of an object within a module or class, in accordance with the conventions in the Python language.\nHowever, just like in Python, scopes are more of a “gentleman’s agreement,” and with explicit naming, access to protected objects can be obtained by simply specifying the full object name.\nIn addition, there are also system fields and objects that start and end with two underscores.\n‘$’ - The dollar sign at the beginning of a name denotes a system (local) name of a temporary variable, the memory space for which is allocated during execution, and the lifetime is limited by the language semantics. ‘::’ - Double colons serve as a separator when specifying namespaces. Explicit namespace specification is a sign of a static object, the memory space for which is allocated during the compilation of the application or module. ","categories":"","description":"Rules for naming variables, functions, and data types","excerpt":"Rules for naming variables, functions, and data types","ref":"/docs/syntax/naming/","tags":"","title":"Naming Objects"},{"body":"NewLang is a language with dynamic typing, and explicit type declaration does not affect the memory size occupied by a variable. Type information is used when checking their compatibility, when assigning a value of a different type to an existing object. This operation is possible only when the types are compatible and allow for automatic conversion. This is true both during parsing/compilation of the source text and during execution in interpreter and/or compiled file modes.\nArithmetic types All numbers (except rational) in NewLang are tensors, i.e. arrays of one type with an arbitrary number of dimensions and the same column size in each. A unit number is also a tensor of zero size.\nOnly signed integers are supported, as there is no special need for unsigned numbers, and there are many problems with them that can be found very easily.\nIssues with unsigned numbers (from the internet): First, subtracting two unsigned numbers, for example 3 and 5. 3 minus 5 equals 4294967294 because -2 cannot be represented as an unsigned number. Second, unexpected behavior may occur when mixing signed and unsigned integer values. C++ can freely convert signed and unsigned numbers, but does not check the range to ensure that you are not overflowing your data type.\nThe names of the built-in arithmetic types: :Int8, :Int16, :Int32, :Int64, :Float16, :Float32, :Float64, :Complex16, :Complex32, :Complex64 speak for themselves. And although among them there are names that are inherent to unsigned numbers (:Byte, :Word, :DWord, etc.), they are synonyms and are used for interaction with native C++ code.\nLogical type A separate type is the logical type: Bool, which can only take values 0 or 1 (false/true respectively), and depending on the operation being performed, it can also be classified as integer types, or not included in their composition (this approach to interpreting the logical data type was taken from the Torch library).\n// Treat bool as a distinct \"category,\" to be consistent with type promotion // rules (e.g. `bool_tensor + 5 -\u003e int64_tensor`). If `5` was in the same // category as `bool_tensor`, we would not promote. Differing categories // implies `bool_tensor += 5` is disallowed. // // NB: numpy distinguishes \"unsigned\" as a category to get the desired // `bool_tensor + 5 -\u003e int64_tensor` behavior. We don't, because: // * We don't want the performance hit of checking the runtime sign of Scalars. // * `uint8_tensor + 5 -\u003e int64_tensor` would be undesirable. Tensor Indexing Access to tensor elements is done by an integer index starting from 0. For a multidimensional tensor, element indices are listed in square brackets separated by commas. Access to elements through a negative index is supported, which is handled in the same way as in Python (-1 is the last element, -2 is the second to last, and so on).\nRanges can be used as tensor indices, which are handled the same way as in Python, as well as the value :None and ellipsis .... The value :None, meaning absence of an index, signifies an arbitrary size of the tensor in one specific dimension, while the ellipsis ... denotes an arbitrary dimension in any number of dimensions (hence, it can appear in the tensor index only once).\nThe tensor literal in the program text is written in square brackets with a mandatory closing comma, i.e. [1, 2,] - this is a literal one-dimensional tensor of two numbers. After the closing bracket, the tensor type can be explicitly specified. If the type is not specified, it is automatically output based on the specified data and the minimum possible byte size that allows all values to be saved without loss of accuracy is selected.\nExamples of creating tensors and transforming their dimensions can be found here.\nRational Numbers For calculations with unlimited precision in NewLang, a separate type is used - rational numbers. They are written in the form of a common fraction, in which the numerator must be an integer, and the denominator natural (an integer without zero).\nA backslash is used as the fraction separator, i.e. 1\\1 - rational number 1, -5\\1 - rational number -5, etc.\n","categories":"","description":"","excerpt":"NewLang is a language with dynamic typing, and explicit type …","ref":"/docs/types/numbers/","tags":"","title":"Numbers"},{"body":"В качестве имен объектов и типов данных можно использовать буквы, цифры и знаки подчеркивания в любых комбинациях, при условии, что первый символ имени не является цифрой.\nВсе идентификаторы должны быть уникальны, а для избежания коллизий можно использовать пространство имен и модульную структуру кода, которые NewLang поддерживает одновременно.\nПерегрузка функций по типам аргументов NewLang отсуствует, поэтому несколько функций с однинаковым именем но разными аругментами определить нельзя, но можно переопределить функцию, в том числе и расширив типы принимаемых аргументов или увеличив их количество.\nИдентификатор объекта может содержать один или несколько специальных символов - квалификаторов (или сигилов), за которыми закрепелено определенное значение. Идентификатор объекта который не содержит квалификатора, называется простым:\nКвалификаторы имен: ‘@’ — префикс собачка используется для указания имени макроса, который обрабатыватся препроцессором до начала синтаксического анализа исходного текста программы. ‘$’ — знак доллара в начале имени объекта обозначает автоматичекое имя временной переменной, область памяти для которой выделяется динамически во время выполнения приложения, а время жизни ограничено семантикой яызка ‘::’ — двойное двоеточие является разделителем пространства имен, и является признаком статического объекта, область памяти для которого выделяется во время компиляции приложения или модуля. Если имя начинается на ‘::’, то область видимости объекта будет глобальной и он будет доступен в рамках всего приложения. В противном случае, видимость объекта будет ограничена только текущим программным модулем. ‘.’ — префикс точка используется при обращении к полю модуля или класса (ограничивает область видимости текущим объектом). Префикс точка может использоваться при определении (вызове) функции для явной идентификации именованного аргумента, чтобы его нельзя было перекрыть макросом препроцессора. ‘\\’ — обратный слеш в начале термина обозначает имя программного модуля, а так же разделяет имена каталогов в иерархии размещения программных модулей. ‘:’ — двоеточие в начале термина обозначает имя типа данных или конструктор класса ‘%’ — префикс знак процента указывается для импортируемых символов (нативных переменных и функций) ‘^’ — символ карет (крышечка/домик) после имени используется для придания объекту иммутабельности (константности, не изменяемости). Разрешение имен (name lookup) Если имя объекта не содержит квалификатора, оно называется простым. Создание объекта с указанием простого имени равнозначно созданию локального объекта.\nВ других случаях, когда NewLang встречает простое имя объекта без квалификатора (сигила), то в дело вструпает специальный алгоритм, который связывает простое имя, встретившееся в исходном тексте программы, с его декларацией или конкретным объектом по его внутреннему имени.\nРазрешение простых имен без квалификатора (name lookup, или поиск имени функции/переменной) происходит всегда в строго определенном порядке:\nв первую очередь происходит поиск имени среди макросов далее выполняется поиск имени среди локальных объектов до объектов текущего модуля в последнюю очередь выполняется поиск среди глобальных объетов с постепенным расширением пространства имен области поиска от текущей до глобальной Такая последовательность разрешение имен всегда предоставляет возможность переопределить глобальные/локальные объекты или имена аргументов у функций для уже существующего кода без его серъезных изменений.\nНапример, для имени name в области имен ns поиск происходит в следующей последовательности: @name -\u003e $name -\u003e ns::name -\u003e ::ns::name -\u003e ::name, а для имени arg проверяется только @arg:\nns:: { name(arg=\"value\"); }; И в тоже время, всегда остатся возможность указать конкретный объект не зависимо от работы алгоритма разрешение простых имен. Достаточно указать квалификатор в имени объекта в явном виде.\nНапример, обратиться к глобальному объекту name из пространства имен ns из примера выше, нужно по полному имени объекта ::ns::name, а именованнй аргумент ’. arg’ не будет заменен макросом @arg, если такой будет определен:\n::ns::name(.arg=\"value\"); Предварительное объявление В тексте программы можно ссылаться только на реально существующие (созданные) объекты. Но для тех случаев, когда требуется сослаться на объект, который создан в другом модуле или будет создан позже, можно сделать предварительное объявление, при котором компилятор регистриурет имя и тип объекта без его реального создания.\nЗа счет предварительного объявления можно ссылаться только на статические объекты (типы данных), или локальные поля класса о которых компилятор ещё не знает, но которые будут определены в процессе компиляции позже.\nДля предварительного объявления можно использовать только полное квалифцированное имя, которое должно будет в точности совпадать с именем обекта при его последующем создании.\nДля предварительного объявления используется точто такой же синтаксис, как и при реальном создании объекта, только с права от операторо создания должно быть указано многоточие.\nОбласть видимости предварительное объявения соответствует области видимости его размещенея, а не реальвой области видимости объекта (это касается даже глобальных объектов).\n# Предварительное определение переменной модуля # Действует для всего модуля var_module:Int32 := ...; func() ::= { # Предварительное объявление с помощью DSL # (действует только внутри тела функции) @declare( func2(arg:Int32):Int32 ); var_module = func2(var_module); @return var_module; }; func2(arg:Int32):Int32 ::= { @return $arg*$arg; } var_module:Int32 := 1; Имена аргументов, специальные, системные имена Обозначение имен аргументов у функций очень похоже на обращение к аргументы в bash скриптах, где “$1” или “$name” — порядковый номер или имя соответствующего аргумента.\nЗарезервированное имя “$0” обозначает текущий объект, а именем “$$” обозначается родительский объект.\nВсе аргументы функции собранны в одном словаре со специальным имеенм $*\nНеизменяемая переменная “$^” содержит результат выполнения последнего оператора или блока кода.\nПолное имя текущего модуля содержится в переменной @\\\\, а текущая область имен в переменной @::, т.е.:\n# Имя файла filename.src в каталоге dir ns:: { # Использовать пространство имен ns name:: { # Команда препроцессора \"@#\" - преобразовать в символьную строку ns_str := @# @::; # Строка с областью имен \"::ns::name::\" mod_str := @# @\\\\; # Строка с именем модуля \"\\\\dir\\filename\" }; }; Области видимости Символ подчерка, а так же подчерк в начале имени или двойные подчерки в начале и в конце имени имеют специальное значение.\nОдин подчерк соответствует защищенной, а два подчерка - приватной области видимости объекта в модуле или классе, что соответствует принятым соглашениям в языке Python.\nНо так же, как и в языке Python, области видимости больше соответствуют “джентльменской” договоренности и при явном указании имени, доступ к защищенным объектам можно получить, просто указав полное имя объекта.\nВ дополнении к этому, существуют еще системные поля и объекты, которые начинаются и заканчиваются на два подчерка.\n‘$’ — знак доллара в начале имени обозначает системное (локальное) имя временной переменной, область памяти для которой выделяется во время выполнения, а время жизни ограничено семантикой яызка ‘::’ — двойное двоеточие являются разделителем при указании пространства имен. Явное указание пространства имен является признаком статического объекта, область памяти для которого выделяется во время компиляции приложения или модуля. ","categories":"","description":"Правила именования переменных, функций и типов данных","excerpt":"Правила именования переменных, функций и типов данных","ref":"/ru/docs/syntax/naming/","tags":"","title":"Именование объектов"},{"body":" Область видимости объекта =/= время жизни объекта Область видимости объекта определяется его расположением в программном коде (блоки кода, пространство имен, модели и т.д.) Объект может существовать, но может быть не доступен из текущей области видимости.\nИмя объекта, создание объекта и его расположение Имя объекта - его уникальный идентификатор, который однозначно определяется местом его расположения (нахождение сильной ссылки на объект). Имя у объекта может быть всегда, даже тогда, когда сам объект физически еще не создан (например при предварительном объявлении).\nСоздания объектов и присвоения новых значений Для создания объектов и присвоения им новых значений в NewLang используется несколько операторов:\n“::=” или “::-” - используется для создания только новых объектов. Если объект с таким именем был определен ранее, то произойдет ошибка компиляции. “:=” или “:-” - используется для создания новых объектов с возможностью перекрытия имен. Если локальный объект с таким именем был определен ранее, то новый объект будет его перекрывать. “=” - применяется только для присвоения значения уже существующим объектам. Если объект с указанным именем отсутствует, то возникает ошибка компиляции. “:=:” - Оператор не создает нового объекта, а обменивает значения уже существуюих (переменные должны иметь одинаковые/совместимые типы данных). ?????????????????????????????????????\n“[]=” - добавлеят новый элемент к словарю или переопределяет созданное ранее имя функции или метод класса. Похож на оператор присвоения значения “=”, но в отличии от него не удаляет старое значение, а сохраняет его в стек переопределнных имен, и к старому значению можно обратиться по системному имени “$$” ????????????????? *). Не может применяться к макросам. Использование трех разных видов операторов для создания/изменения объектов позволяет более гибко контролировать подобные операции и выявлять логические ошибки в коде на более раннем этапе.\nНапример, при определении класса :NewClass2:\n:NewClass := :Class() { # Базовый класс filed ::= 2; # Однократная инициализация (статическоого) члена класса method() ::= {}; # Регистрация метода }; :NewClass2 := :NewClass() { filed ::= 2; # Будет ошибка, т.к. field уже есть в базовом классе method() = {}; # Аналог override, т.к. method должен существовать в базовом классе }; Если же контролировать момент создание объектов и присвоения им значений не требуется, то можно пользоваться единственным оператором :=.\nvar := 1.0; # Создать новую переменную var без явного указания типа var := 100; # Присвоить новое значение уже существующей переменной printf(format:FmtChar, ...):Int32 ::= %printf...; # Создать новый или переопределить printf ??????????????????????????????????????????? Присваивание значения сразу нескольким переменным и оператор распаковки словаря NewLang поддерживает операцию присваивания значения сразу нескольким переменным, которые должны быть перечислены через запятую слева от оператора присвоения. С правой стороны от оператора присвоения может находится только одно значение. А для обмена занчениями двух переменных, вместо традиционной записи:\na,b = b,a; Нужно использовать отдельный оператор обмена:\na :=: b; В качестве правого операнда в операторе присвоения допускается использовать оператор распаковки словаря … (многоточие), который можно использовать и при передаче аргументов в функцию.\nargs := (arg1=1, arg2=2, 3,4,); call(arg=0, ... args); # Что равносильно вызову call(arg=0, arg1=1, arg2=2, 3, 4); Словарь может быть указан и с левой стороны от оператора присвоения. Таким образом можно записать самый простой способ перебора всех его элементов: item, dictionary := ... dictionary;, т.е. когда первый элемент словаря сохраняется в переменную item, а из самого словаря удаляется, и так в цикле пока словарь не станет пустым.\nПример реализации цикла foreach для суммирования всех элементов словаря (или одномерного тензора) с использованием оператора раскрытия словаря (списка):\nsumma := 0; dictionary := (1,2,3,4,5,); @while( dictionary ) { # Первый элемент словаря перемещается в item item, dictionary := ... dictionary; summa += item; }; Заполнение данными При заполнении данными размерных тензоров существует краткий способ указания их начальных значений. Для этого используется многоточие в следующих вариантах:\n:Tensor[10](2,3, ...) - повторение всех предыдущих данных до полного заполнения тензора, что равносильно записи :Tensor[10](2,3, 2,3, 2,3, 2,3, 2,3).\n:Tensor[10](2, 3, ... 42 ...) - заполнение значением 42 до конца тензора, что равносильно записи :Tensor[10](2,3, 42,42,42,42,42,42,42,42).\n:Tensor[10](2, 3, ... rand() ...) - заполнение до конца тензора значением, которое будет возвращать функция. Указанная функция будет вызываться для каждого элемента до полного заполнения тензора (8 раз).\n:Tensor[10]( rand(), rand(), ...) - заполнение тензора двумя произвольными заначениями, то есть функция rand() будет вызвана дважды для двух первых элементов, после чего эти значения будут использоваться до полного заполнения тензора (как в первом примере).\n:Tensor[10]( ... 0..0.99..0.1 ) - заполнение тензора элементами диапазона, что равносильно записи\n:Tensor[10](0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9). Раскрытие диапазона создает фиксированное количество значений. Поэтому в данном примере размерность тензора можно не указывать, так как она будет создана автоматически.\n:Tensor[15]( ... 0..5 , ... ) - заполнение тензора элементами диапазона с их повторением до заданного размера тензора: :Tensor(0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4)\nЗаполнение данными в словарях и аргументах функций Предыдущие способы заполнения данными возможны только для тензоров фиксированного размера, так как позволяют получить произвольное количество значений, но их можно применять только в конце списка значения для инициализации.\nОператоры раскрытия словаря или диапазона создают ограниченное количество значений, но за счет этого их можно использовать не только для инициализации тензоров, но и в качестве начальных значений у словарей или создания аргументов при вызове функций, причем в произвольном месте, а не только в конце списка инициализации:\n:Tensor( ... 0..0.99..0.1 ) - заполнение тензора без указания его размера элементами диапазона, что равносильно записи :Tensor(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9)\nfuntcion( 0, ... dict, 42 ) - раскрытие словаря как индивидуальных не именованных аргументов функции, к примеру funtcion( 0, 1, 2, 3, 42), если словарь dict содержал три элемента 1, 2 и 3.\nfuntcion( ... ... dict, end=4) - раскрытие словаря как индивидуальных именованных аргументов функции. Если словарь dict будет содержать элементы (1, two=2, three=3,), то это будет равносильно вызову функции funtcion( 1, two=2, three=3, end=4).\n","categories":"","description":"","excerpt":" Область видимости объекта =/= время жизни объекта Область видимости …","ref":"/docs/ops/create/","tags":"","title":"Создание объектов"},{"body":" Область видимости объекта =/= время жизни объекта Область видимости объекта определяется его расположением в программном коде (блоки кода, пространство имен, модели и т.д.) Объект может существовать, но может быть не доступен из текущей области видимости.\nИмя объекта, создание объекта и его расположение Имя объекта - его уникальный идентификатор, который однозначно определяется местом его расположения (нахождение сильной ссылки на объект). Имя у объекта может быть всегда, даже тогда, когда сам объект физически еще не создан (например при предварительном объявлении).\nСоздания объектов и присвоения новых значений Для создания объектов и присвоения им новых значений в NewLang используется несколько операторов:\n“::=” или “::-” - используется для создания только новых объектов. Если объект с таким именем был определен ранее, то произойдет ошибка компиляции. “:=” или “:-” - используется для создания новых объектов с возможностью перекрытия имен. Если локальный объект с таким именем был определен ранее, то новый объект будет его перекрывать. “=” - применяется только для присвоения значения уже существующим объектам. Если объект с указанным именем отсутствует, то возникает ошибка компиляции. “:=:” - Оператор не создает нового объекта, а обменивает значения уже существуюих (переменные должны иметь одинаковые/совместимые типы данных). ?????????????????????????????????????\n“[]=” - добавлеят новый элемент к словарю или переопределяет созданное ранее имя функции или метод класса. Похож на оператор присвоения значения “=”, но в отличии от него не удаляет старое значение, а сохраняет его в стек переопределнных имен, и к старому значению можно обратиться по системному имени “$$” ????????????????? *). Не может применяться к макросам. Использование трех разных видов операторов для создания/изменения объектов позволяет более гибко контролировать подобные операции и выявлять логические ошибки в коде на более раннем этапе.\nНапример, при определении класса :NewClass2:\n:NewClass := :Class() { # Базовый класс filed ::= 2; # Однократная инициализация (статическоого) члена класса method() ::= {}; # Регистрация метода }; :NewClass2 := :NewClass() { filed ::= 2; # Будет ошибка, т.к. field уже есть в базовом классе method() = {}; # Аналог override, т.к. method должен существовать в базовом классе }; Если же контролировать момент создание объектов и присвоения им значений не требуется, то можно пользоваться единственным оператором :=.\nvar := 1.0; # Создать новую переменную var без явного указания типа var := 100; # Присвоить новое значение уже существующей переменной printf(format:FmtChar, ...):Int32 ::= %printf...; # Создать новый или переопределить printf ??????????????????????????????????????????? Присваивание значения сразу нескольким переменным и оператор распаковки словаря NewLang поддерживает операцию присваивания значения сразу нескольким переменным, которые должны быть перечислены через запятую слева от оператора присвоения. С правой стороны от оператора присвоения может находится только одно значение. А для обмена занчениями двух переменных, вместо традиционной записи:\na,b = b,a; Нужно использовать отдельный оператор обмена:\na :=: b; В качестве правого операнда в операторе присвоения допускается использовать оператор распаковки словаря … (многоточие), который можно использовать и при передаче аргументов в функцию.\nargs := (arg1=1, arg2=2, 3,4,); call(arg=0, ... args); # Что равносильно вызову call(arg=0, arg1=1, arg2=2, 3, 4); Словарь может быть указан и с левой стороны от оператора присвоения. Таким образом можно записать самый простой способ перебора всех его элементов: item, dictionary := ... dictionary;, т.е. когда первый элемент словаря сохраняется в переменную item, а из самого словаря удаляется, и так в цикле пока словарь не станет пустым.\nПример реализации цикла foreach для суммирования всех элементов словаря (или одномерного тензора) с использованием оператора раскрытия словаря (списка):\nsumma := 0; dictionary := (1,2,3,4,5,); @while( dictionary ) { # Первый элемент словаря перемещается в item item, dictionary := ... dictionary; summa += item; }; Заполнение данными При заполнении данными размерных тензоров существует краткий способ указания их начальных значений. Для этого используется многоточие в следующих вариантах:\n:Tensor[10](2,3, ...) - повторение всех предыдущих данных до полного заполнения тензора, что равносильно записи :Tensor[10](2,3, 2,3, 2,3, 2,3, 2,3).\n:Tensor[10](2, 3, ... 42 ...) - заполнение значением 42 до конца тензора, что равносильно записи :Tensor[10](2,3, 42,42,42,42,42,42,42,42).\n:Tensor[10](2, 3, ... rand() ...) - заполнение до конца тензора значением, которое будет возвращать функция. Указанная функция будет вызываться для каждого элемента до полного заполнения тензора (8 раз).\n:Tensor[10]( rand(), rand(), ...) - заполнение тензора двумя произвольными заначениями, то есть функция rand() будет вызвана дважды для двух первых элементов, после чего эти значения будут использоваться до полного заполнения тензора (как в первом примере).\n:Tensor[10]( ... 0..0.99..0.1 ) - заполнение тензора элементами диапазона, что равносильно записи\n:Tensor[10](0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9). Раскрытие диапазона создает фиксированное количество значений. Поэтому в данном примере размерность тензора можно не указывать, так как она будет создана автоматически.\n:Tensor[15]( ... 0..5 , ... ) - заполнение тензора элементами диапазона с их повторением до заданного размера тензора: :Tensor(0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4)\nЗаполнение данными в словарях и аргументах функций Предыдущие способы заполнения данными возможны только для тензоров фиксированного размера, так как позволяют получить произвольное количество значений, но их можно применять только в конце списка значения для инициализации.\nОператоры раскрытия словаря или диапазона создают ограниченное количество значений, но за счет этого их можно использовать не только для инициализации тензоров, но и в качестве начальных значений у словарей или создания аргументов при вызове функций, причем в произвольном месте, а не только в конце списка инициализации:\n:Tensor( ... 0..0.99..0.1 ) - заполнение тензора без указания его размера элементами диапазона, что равносильно записи :Tensor(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9)\nfuntcion( 0, ... dict, 42 ) - раскрытие словаря как индивидуальных не именованных аргументов функции, к примеру funtcion( 0, 1, 2, 3, 42), если словарь dict содержал три элемента 1, 2 и 3.\nfuntcion( ... ... dict, end=4) - раскрытие словаря как индивидуальных именованных аргументов функции. Если словарь dict будет содержать элементы (1, two=2, three=3,), то это будет равносильно вызову функции funtcion( 1, two=2, three=3, end=4).\n","categories":"","description":"","excerpt":" Область видимости объекта =/= время жизни объекта Область видимости …","ref":"/ru/docs/ops/create/","tags":"","title":"Создание объектов"},{"body":"NewLang является языком с динамической типизацией и явное указание типа не влияет на размер памяти, занимаемой переменной. Информация о типах используется при проверке их совместимости, когда существующему объекту присваивается значение другого типа. Такая операция возможна только тогда, когда типы совместимы между собой и допускают автоматическое приведение. Это справедливо как во время парсинга/компиляции исходного теста, так и во время выполнения в режимах интерпретатора и/или скомпилированного файла.\nАрифметические типы Все числа (кроме рациональных) в NewLang являются тензорами, т.е. массивами одного типа с произвольным количеством измерений и одинаковым размером столбцов в каждом. Единичное число, это тоже тензор нулевого размера.\nПоддерживаются только знаковые целые числа, т.к. в без знаковых числах особая нужда отсутствует, а проблем с ними можно найти очень много на ровном месте.\nПроблемы без знаковых чисел (из интернета):\nВо-первых, вычитание двух без знаковых чисел, например 3 и 5. 3 минус 5 равно 4294967294, т.к. -2 не может быть представлено как без знаковое число. Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных значений со знаком и без знака. С++ может свободно преобразовывать числа со знаком и без знака, но не проверяет диапазон, чтобы убедиться, что вы не переполняете свой тип данных.\nИмена встроенных арифметических типов: :Int8, :Int16, :Int32, :Int64, :Float16, :Float32, :Float64, :Complex16, :Complex32, :Complex64 говорят сами за себя. И хотя среди них присуствуют названия, присущие беззнаковым числам (:Byte, :Word, :DWord и т.д.), они являются синонимами и применяются для взаимодействия с нативным C++ кодом.\nЛогический тип Отдельным типом идет логический тип :Bool, который может принимать значения только 0 или 1 (false/true соответственно), и в зависимости от выполняемой операции тоже может быть отнесен к целочисленным типам, так и не входить в их состав (данный подход интерпретации логического типа данных был взят из библиотеки Torch).\n// Treat bool as a distinct \"category,\" to be consistent with type promotion // rules (e.g. `bool_tensor + 5 -\u003e int64_tensor`). If `5` was in the same // category as `bool_tensor`, we would not promote. Differing categories // implies `bool_tensor += 5` is disallowed. // // NB: numpy distinguishes \"unsigned\" as a category to get the desired // `bool_tensor + 5 -\u003e int64_tensor` behavior. We don't, because: // * We don't want the performance hit of checking the runtime sign of Scalars. // * `uint8_tensor + 5 -\u003e int64_tensor` would be undesirable. Индексация тензоров Доступ к элементам тензора происходит по целочисленному индексу, который начинается с 0. Для многомерного тензора, индексы элемента перечисляются в квадратных скобках через запятую. Поддерживается доступ к элементам через отрицательный индекс, который обрабатывается точно так же, как в Python (-1 последний элемент, -2 предпоследний и т.д.).\nВ качесте индекса тензора могут быть использованы диапазоны которые обработываются точно так же как и в Python, а так же значение :None и многоточие .... Значение :None, т.е. отсуствие индекса, означает произвольный размер тензора в одном конкретном измерении, тогда как многоточие ... обозначет произвольную размерность в любом количестве измерений (поэтому может встречаться в индексе тензора только однократно).\nЛитерал тензор в тексте программы записывается в квадратных скобках с обязательной завершающей запятой, т.е. [1, 2,] — это литерал одномерный тензор из двух чисел. После закрывающей скобки тип тензора может быть указан в явном виде. Если тип не указан, то он выводится автоматически на основании указанных данных и выбирается минимально возможный байтовый размер, который позволяет сохранить все значения без потери точности.\nПримеры создания тензоров и преобразования их размерности можно посмотреть тут.\nРациональные числа Для вычислений с неограниченной точностью в NewLang используются отдельный тип - рациональные числа. Они записываются в форме обыкновенной дроби, в которой числитель должен быть целым числом, а знаменатель натуральным (целым без нуля). В качестве разделителя дроби используется обратная косая черта, т.е. 1\\1 - рациональное число 1, -5\\1 - рациональное числа -5 и т.д.\n","categories":"","description":"","excerpt":"NewLang является языком с динамической типизацией и явное указание …","ref":"/ru/docs/types/numbers/","tags":"","title":"Числа"},{"body":"Блок кода, это сгруппированный набор идущих подряд инструкций, которые выполняются как единое целое с возвращением результата выполнения последней из них. Блок кода, как и любая синтаксическая конструкция языка, должен завершаться точкой с запятой “;”.\nБлоки кода используются для ограничения области видимости переменных. С их помощью определяется иерархия области имен и реализуется система именования свойств и методов для классов. Именованные блоки кода могут выступать в качестве локальных меток для передачи потока выполнения.\nЗа счет того, что к блоку кода можно обратится как к единой инструкции, они могут использоваться в других операторах. Тело функции, также представляет собой блока кода, который располагается в пространстве имен определения этой функции.\nns:: { # Пространство имен ns name { # Пространство имен ns::name # В конце имени \"::\" можно не указывать }; :: { # Глобальное пространство имен ... }; { # Локальная переменная до завершения блока кода $local ::= 0; }; $local; # \u003c-- Ошибка! Локальная переменная не видна }; func_name(val) ::= { # Блок кода func_name:: @if($val) { ... } @else { ... }; }; Оформление блока кода Блок кода всегда начинается и заканчивается на фигурные скобки («{» и «}») и завершается точкой с запятой “;”. Существуют блоки кода, которые перехватывают потоки выполнения, с помощью которых реализуются возврат и обработка ошибок.\nТип возвращаемого значения блоком кода можно указать в явном виде. Для этого, после завершающей фигурной скобки, нужно указать разрешенный тип, после чего компилятор будет проверят корретность данных внутрие блока кода, которые могут быть возвращены.\nМожно указать сразу несколько типов, перечислив их через запятую в угловых скобрах.\n{ op1; op2; }; # \u003c--- Контроль типа возврата не производится { op1; op2; # \u003c--- Проверка типа возвращаемого значения } :Type; # \u003c--- Разрешенный тип { op1; op2; ... }: \u003c:Type1, :Type2, :Type3\u003e; # \u003c--- Несколько разрешенных типов возврата { op1; op2; ... }: \u003c ... \u003e; # \u003c--- Разрешен любой тип возвращаемого значения Расширенный синтаксис Расширенный синтаксис с нативным исходным кодом на языке реализации (С++), это тоже блок кода. Он начинается и заканчивается на фигурные скобки со знаком процента («{%» и «%}»).\nВнутри блока кода с расширенным синтаксисом можно применять произвольные элементы языка реализации (С++), но нужно иметь ввиду, что расширенный синтаксис является исходным текстом программы и напрямую подстваляется и выходной текст трансплайтера во время компиляции файла.\nС помощью блока кода с расширенным синтаксисом можно реализовать разные элементы, которые отсуствуют в основном синтаксисе, например, безусловный переход на заданную метку.\n@@ label $name @@ ::= @@@ {% @$name:; %} @@@; @@ goto $label @@ ::= @@@ {% goto @$label; %} @@@; @goto label_for_goto; # Skip this code @label label_for_goto; Взаимодействие расширенного синтаксиса с основным кодом программы происходит путем обращения к локальным объектам или макросам программы изнутри блока кода. Но для этого, имя объекта должно быть указано полностью, включая все квалификаторы имени.\nЕсли есть необходимость обратится к статическому объекту, его имя нужно заменить макросом, так как символ двоеточия используется в синтаксисе языков C/C++.\nНачиная с версии C++26 взаимодействие с расширенным синтаксисом может быть нарушено!\nAdd the same characters @, $, and ` to the basic character set [C++26] P2558R2\nfactorial := 1000; ::result := 1\\1; /* Rational number */ @@ res @@ ::= ::result; {% // Source on the C++ for( int i=2; i \u003c= static_cast\u003cunsigned int\u003e( $factorial ); i++ ){ @res *= i; } printf(\"\\nFactorial %i! = %s\\n\", static_cast\u003cunsigned int\u003e( $factorial ), static_cast\u003cconst char *\u003e( @res )); # std::cout \u003c\u003c \"Factorial \" \u003c\u003c static_cast\u003cunsigned int\u003e( $factorial ); # std::cout \u003c\u003c \"! = \" \u003c\u003c static_cast\u003cconst char *\u003e( @res ) \u003c\u003c std::endl; %} ","categories":"","description":"","excerpt":"Блок кода, это сгруппированный набор идущих подряд инструкций, которые …","ref":"/docs/ops/block/","tags":"","title":"Блоки кода"},{"body":"Блок кода, это сгруппированный набор идущих подряд инструкций, которые выполняются как единое целое с возвращением результата выполнения последней из них. Блок кода, как и любая синтаксическая конструкция языка, должен завершаться точкой с запятой “;”.\nБлоки кода используются для ограничения области видимости переменных. С их помощью определяется иерархия области имен и реализуется система именования свойств и методов для классов. Именованные блоки кода могут выступать в качестве локальных меток для передачи потока выполнения.\nЗа счет того, что к блоку кода можно обратится как к единой инструкции, они могут использоваться в других операторах. Тело функции, также представляет собой блока кода, который располагается в пространстве имен определения этой функции.\nns:: { # Пространство имен ns name { # Пространство имен ns::name # В конце имени \"::\" можно не указывать }; :: { # Глобальное пространство имен ... }; { # Локальная переменная до завершения блока кода $local ::= 0; }; $local; # \u003c-- Ошибка! Локальная переменная не видна }; func_name(val) ::= { # Блок кода func_name:: @if($val) { ... } @else { ... }; }; Оформление блока кода Блок кода всегда начинается и заканчивается на фигурные скобки («{» и «}») и завершается точкой с запятой “;”. Существуют блоки кода, которые перехватывают потоки выполнения, с помощью которых реализуются возврат и обработка ошибок.\nТип возвращаемого значения блоком кода можно указать в явном виде. Для этого, после завершающей фигурной скобки, нужно указать разрешенный тип, после чего компилятор будет проверят корретность данных внутрие блока кода, которые могут быть возвращены.\nМожно указать сразу несколько типов, перечислив их через запятую в угловых скобрах.\n{ op1; op2; }; # \u003c--- Контроль типа возврата не производится { op1; op2; # \u003c--- Проверка типа возвращаемого значения } :Type; # \u003c--- Разрешенный тип { op1; op2; ... }: \u003c:Type1, :Type2, :Type3\u003e; # \u003c--- Несколько разрешенных типов возврата { op1; op2; ... }: \u003c ... \u003e; # \u003c--- Разрешен любой тип возвращаемого значения Расширенный синтаксис Расширенный синтаксис с нативным исходным кодом на языке реализации (С++), это тоже блок кода. Он начинается и заканчивается на фигурные скобки со знаком процента («{%» и «%}»).\nВнутри блока кода с расширенным синтаксисом можно применять произвольные элементы языка реализации (С++), но нужно иметь ввиду, что расширенный синтаксис является исходным текстом программы и напрямую подстваляется и выходной текст трансплайтера во время компиляции файла.\nС помощью блока кода с расширенным синтаксисом можно реализовать разные элементы, которые отсуствуют в основном синтаксисе, например, безусловный переход на заданную метку.\n@@ label $name @@ ::= @@@ {% @$name:; %} @@@; @@ goto $label @@ ::= @@@ {% goto @$label; %} @@@; @goto label_for_goto; # Skip this code @label label_for_goto; Взаимодействие расширенного синтаксиса с основным кодом программы происходит путем обращения к локальным объектам или макросам программы изнутри блока кода. Но для этого, имя объекта должно быть указано полностью, включая все квалификаторы имени.\nЕсли есть необходимость обратится к статическому объекту, его имя нужно заменить макросом, так как символ двоеточия используется в синтаксисе языков C/C++.\nНачиная с версии C++26 взаимодействие с расширенным синтаксисом может быть нарушено!\nAdd the same characters @, $, and ` to the basic character set [C++26] P2558R2\nfactorial := 1000; ::result := 1\\1; /* Rational number */ @@ res @@ ::= ::result; {% // Source on the C++ for( int i=2; i \u003c= static_cast\u003cunsigned int\u003e( $factorial ); i++ ){ @res *= i; } printf(\"\\nFactorial %i! = %s\\n\", static_cast\u003cunsigned int\u003e( $factorial ), static_cast\u003cconst char *\u003e( @res )); # std::cout \u003c\u003c \"Factorial \" \u003c\u003c static_cast\u003cunsigned int\u003e( $factorial ); # std::cout \u003c\u003c \"! = \" \u003c\u003c static_cast\u003cconst char *\u003e( @res ) \u003c\u003c std::endl; %} ","categories":"","description":"","excerpt":"Блок кода, это сгруппированный набор идущих подряд инструкций, которые …","ref":"/ru/docs/ops/block/","tags":"","title":"Блоки кода"},{"body":"","categories":"","description":"","excerpt":"","ref":"/blog/","tags":"","title":"Articles"},{"body":"NewLang supports two types of strings:\n:StrChar - universal byte UTF-8 strings :StrWide - system character (wide characters) The single element of a universal UTF-8 string is one byte, while the single element of a system character string is a wide character wchar_t. And although the strings differ in the types of single string elements, the internal representation of both types of strings is the same. All data of character strings is stored as a universal byte UTF-8 sequence.\nByte Strings :StrChar The basic element of a universal byte string is one byte (specifically :Int8, i.e. an 8-bit signed integer). The number of characters in a byte string is returned in bytes, and accessing a string element by index is done by the byte of the character sequence.\nSince these strings are interpreted as a sequence of UTF-8 characters, caution must be taken when modifying individual bytes!\nSystem Strings :StrWide The individual element of the system string is a wide character wchar_t, and the number of elements in the system character string is returned in wide characters. The size of the wchar_t type depends on the operating system, so the size of one character :StrWide in Windows will be 2 bytes, and in Linux 4 bytes, which is related to their implementation specifics.\nThe main purpose of system strings is to simplify working in a text terminal, as one character always corresponds to one character cell without the need for constant conversion of UTF-8 code points.\nString Formatting Any variable can be accessed as a function (by specifying parentheses after its name) to create a copy/clone of the object, and for strings, this operation can be used as a template for formatting data.\nString formatting can be done in two ways:\nSpecify a format string with the types of data to be output (the format string corresponds to formatting in the standard printf function). To apply this formatting variant, the format string must specify the corresponding data type (: FmtChar or : FmtWide for regular and wide characters, respectively).\nWith this formatting method, named arguments cannot be used, and the compiler checks the types of the passed values for compliance with the format string only during compilation of the program text. This type of format string can be used as the last argument of a function to check the types of all subsequent arguments for compliance with the format string.\nIn all other cases, any strings and named arguments can be used as the format string, and the format itself corresponds to the format string from the {fmt} library. The only difference is the ability to specify not only the positional number of the argument, but also its name. Argument validation against the format string is performed during string cloning both at compile time and during program execution.\nThe formatting method is used by default for any type of string, but the format string is not checked in the function arguments.\nFor example:\n$fmt := '%s: %d':FmtChar; # Formatting like in printf $result := $fmt('value', 123); # \"value: 123\" - Check compile time only! $template := \"{name} {0}\"; # fmt::format equivalent \"{1} {0}\" $result := $template(\"template\", name = \"String\"); # result = \"String template\" ","categories":"","description":"","excerpt":"NewLang supports two types of strings:\n:StrChar - universal byte UTF-8 …","ref":"/docs/types/strings/","tags":"","title":"Character Strings"},{"body":"Основные материалы по языку программирования NewLang.\nОписание акутально для текущей версии 4.0\nclang-17 не поддерживает:\nFeature Proposal Available Coroutines P0912R5 Partial Fully supported on all targets except Windows, which still has some stability and ABI issues. Extended floating-point types and standard names P1467R9 No Concepts P0848R3 Clang 16 (Partial) Modules No Начиная с C++ should adopt the same characters for C++26. Add @, $, and ` to the basic character set P2558R2 Yes ","categories":"","description":"","excerpt":"Основные материалы по языку программирования NewLang.\nОписание …","ref":"/docs/","tags":"","title":"Documentation"},{"body":"NewLang supports namespaces, where the separator, like in C++, is a double colon “::”.\nA namespace can be specified for an individual identifier or for an entire code block.\nUnlike namespace in C++, namespaces in NewLang are used not only to organize code into logical groups and avoid name conflicts, but also to associate an identifier, explicitly specifying the namespace, with static objects (memory allocated during the compilation stage of the program).\nThe global name cannot be overridden by a macro or local variable during name lookup. To create a global (static) variable in the current namespace, you can specify the variable with the @:: preprocessor.\nTo use a namespace in a code block, it must be specified before the opening curly brace. In such a named code block, it is not necessary to specify the closing “::”.\n::var ::= 0; # Name of global variable explicitly (cannot be overridden) ns { # Equivalent to ns:: var ::= 0; # Name ns::var (can be overridden by macro or local variable) @::var ::= 0; # Name of global variable ::ns::var (cannot be overridden) name:: { var = 0; # Reference to variable ns::var var2 ::= 0; # Name of variable will be ns::name::var2 ::var = 1; # Variable from global namespace }; :: { # Global namespace var = 1; # Name of global variable ::var (can be overridden) ::ns::var = 0; # Name of another global variable (cannot be overridden) }; }; Namespaces, Modules, and Packages The namespace in NewLang supports both a modular code structure like in Java and Python languages, and when specifying the full name of an object, program modules and namespaces can be combined.\nFor example, the full name of a variable can be written with the indication of the program module \\root\\dir\\module::ns::name::var, where root and dir are directories in the file system relative to the current module, and module is the file name, i.e. root/dir/module.src.\nNamespace and OOP In NewLang, name decoration (mangling) based on function argument types is not used.\nHowever, when creating unique identifiers for class methods, NewLang uses an approach similar to that used in the Python language. When creating a class method, a global function is created with the class name and method name combined with the separator “::”.\nFor example, for the class :NewClass, when creating the method method, a function named NewClass::method will be created.\nThis method naming scheme fully corresponds to the naming of functions in the namespace, allowing class methods to be defined outside the body of the class simply by specifying the desired name in the namespace or explicitly.\nExample of creating a method of the class NewClass in the namespace:\nNewClass:: { method() := { }; } Example of creating a method of the class NewClass with specifying the full name:\nNewClass::method() := { }; ","categories":"","description":"","excerpt":"NewLang supports namespaces, where the separator, like in C++, is a …","ref":"/docs/syntax/namespace/","tags":"","title":"Namespaces"},{"body":"Именование объектов основано на правилах и выбирается из расчёта удобства для программиста. Название переменной или функции должно нести смысл, понятные параметры и тип возвращаемого значения, которые упрощают понимание алгоритма при последующем чтении исходного текста программы.\nНо обычные имена мало о чём говорят компьютеру. Поэтому при компиляции программы, имена объектов преобразуются для удобства машинной обработки и к ним добавляется служебная информация.\nВнутреннее имя объекта Каждый объект имеет свое внутреннее имя, уникальное в рамках текущего модуля, с помощью которого комипилятор языка однозначно связывает объект с данными в памяти компьютера.\nВнутреннее имя формируется во время анализа синтаксического дерева программы. Оно включает в себя имя объекта, его квалификатор и полное пространство имен, в котором объект был опеределен.\nУ статических объектов (типов и классов), внутренее имя соотвествует полному имени объекта с учетом всех областей имен, тогда как внутреннее имя автоматичеких объектов включает в себя и пустые (не именованные) блоки кода, которые заменяются на монотонно возрастающий порядковый номер блока (т.е. ::1::, ::2:: и т.д.). Включение в пространство имен пустых блоков кода необходимо для реализации возможности перекрытия имен у объектов, определенных в разных областях видимости.\nКроме этого, все квалификаторы объектов переносятся в конец имени, что и является отличительным признаком внутреннего имени (последний символ должен быть “$” или “:”).\nПримеры внутренних имен:\n# Глобальный статический объект ::var ::= 0; # ::var:: # Локальный объект модуля $var := 0; # var$ # Статический объект модуля @::var ::= 0; # var:: # Глобальные тип и конструктор класса :: :type := :Type; # ::type::: :: :cls := Class(){}; # ::cls::: # Синоним типа или конструктор класса модуля :type := :Type; # type::: :cls := Class(){}; # cls::: # Тип или конструктор класса всегда статические @:: :type := :Type; # type::: @:: :cls := Class(){}; # cls::: ns { $var := 0; # ns::var$ var ::= 0; # ns::var$ @::var ::= 0; # ns::var:: - статический объект :type := :Type; # ns::type::: :cls := Class(){}; # ns::cls::: @::func1() ::= {}; # ns::func1:: func2() ::= {}; # ns::func2:: # Не именованный блок кода { # Локальные имена перекрывают объявления выше $var := 0; # ns::1::var$ var := 0; # ns::1::var$ # Статический объект соответствует области имен @::var ::= 0; # ns::var:: # Типы данных всегда статические :type := :Type; # ns::type::: :cls := Class(){}; # ns::cls::: @::func3() := {}; # ns::func3:: # Локальная функция с ограниченной областью видимости ????? func4() := {}; # ns::1::func4$ } }; # Не именованный блок кода { $var := 0; # 2::var$ var ::= 0; # 2::var$ @::var = 0; # var:: - статический объект :type := :Type; # type::: :cls := Class(){}; # cls::: }; Манглинг внутренних имен Внутреннее имя уникально только в рамках одного модуля, но внутренние имена в разных модулях могут пересекаться.\nМанглинг внутренних имя предназначен для объединения нескольких модулей в рамках одной программы, и используется как способ кодирования имени функции, структуры, класса или другого типа данных при передачи дополнительной семантической информации от компилятора компоновщику.\nВнутреннее имя объекта после манглинга является корректным идентификатором для языков C/C++, что позволяет обращатся к объектам NewLang из внешних библиотек и приложений на языке реализации (C/C++) по семантически похожему имени (в отличии от манглинга имен в С++).\nМанглинг внутреннего имени заключается в замене каждого символа двоеточия на символ $, а у имени типа квалификатор заменяется тремя символами ‘$’, т.е. ’type $$$’.\nПри манглинге, к внутренним именам объектов добавляется специальный префикс, который кодирует имя компилируемого модуля. Имя текущего модуля находится в переменной препроцессора \"@$$\" и по умолчанию, содержит имя файла модуля (у главного модуля приложения имя модуля отсутствует).\nИмя модуля может быть однократно переопределено самым первым оператором модуля или заменено во время импорта модуля с помощью системного параметра __package__.\n# Задать имя модуля @$$ = \"\\dir\\file\"; # Импорт модуля с переопределением имени \\dir\\file(__package__=\"\\new\\module\\name\"); Тоже само с использвоанием DSL:\n@package \\dir\\name; # @$$ = \"\\dir\\file\"; @import \\dir\\name as \\new\\module\\name; # \\dir\\file(__package__=\"\\new\\module\\name\"); При манглинге имя модуля, по умолчанию имя файла отностительно каталога главного файла программы, размещается в начале внутреннего системного имени. Так как имя модуля, согласно правилам синтаксиса, может содерждать только строчные буквы и цифры, то разделитель каталогов (обратный слеш) заменяется на подчерк, а начало и конец имени модуля отмечаются комбинациями символов “_$” и “$_” соответственно.\nТак как локальной переменной с одним подчерком в качестве имени быть не может, то начало строки на “_$” служит отличительным признаком манглинга внутреннего имени объекта.\n@$$ = \"\\dir\\file\"; # Глобальный статический объект ::var ::= 0; # _$dir_file$_$$var$$ # Локальный объект модуля $var := 0; # _$dir_file$_var$ # Статический объект модуля @::var ::= 0; # _$dir_file$_var$$ # Глобальные тип и конструктор класса :: :type := :Type; # _$dir_file$_$$type$$$ :: :cls := Class(){}; # _$dir_file$_$$cls$$$ # Синоним типа или конструктор класса модуля :type := :Type; # _$dir_file$_type$$$ :cls := Class(){}; # _$dir_file$_cls$$$ ns { $var := 0; # _$dir_file$_ns$$var$ var ::= 0; # _$dir_file$_ns$$var$ @::var ::= 0; # _$dir_file$_ns$$var$$ - статический объект :type := :Type; # _$dir_file$_ns$$type$$$ :cls := Class(){}; # _$dir_file$_ns$$cls$$$ @::func() ::= {}; # _$dir_file$_ns$$func$$ func() ::= {}; # _$dir_file$_ns$$func$ # Не именованный блок кода { # Локальные имена перекрывают обяъявления выше $var := 0; # _$dir_file$_ns$$1$$var$ var := 0; # _$dir_file$_ns$$1$$var$ # Статический объект соответствует области имен @::var ::= 0; # _$dir_file$_ns$$var$$ # Типы данных и функции всегда статические :type := :Type; # _$dir_file$_ns$$type$$$ :cls := Class(){}; # _$dir_file$_ns$$cls$$$ @::func() := {}; # _$dir_file$_ns$$func$$ func() := {}; # _$dir_file$_ns$$1$$func$ ???????? } }; # Не именованный блок кода { $var := 0; # _$dir_file$_2::var$ var ::= 0; # _$dir_file$_2::var$ @::var = 0; # _$dir_file$_var$$ - статический объект :type := :Type; # _$dir_file$_type$$$ :cls := Class(){}; # _$dir_file$_cls$$$ }; Манглинг имен блока кода главного модуля программы:\n{ $var := 0; # _$$_1::var$ var ::= 0; # _$$_1::var$ @::var = 0; # _$$_var$$ - статический объект :type := :Type; # _$$_type$$$ :cls := Class(){}; # _$$_cls$$$ }; Встроенный блок кода и вызов функций В расширенном синатксисе с исходным кодом языка реализации можно взаимодействовать с другим кодом программы за счет обращения к локальным объектам или макросам изнутри блока кода.\nЭто досупкается как для обычных переменных, так и для имен функций, реализованных в NewLang, и для того, что бы компилятор C/C++ имел возможность создать правильный код, при раскрытии встроенного блока кода перед ним добавляются сигнатуры переменных и функций, которые используются во строенном блоке кода.\nДля имен переменных дополнительный манглинг имен не производится, а для функций автоматичсеки создается дополнительная сигнатура с описанием типов аргументов и их значений по умолчанию, если таковые используются.\nКаждая функция NewLang имеет две сигнатуры, первая (основная) принимает все аргументы в виде словаря, а вторая (дополнительная) с развернутым списком аргументов, чтобы её можно было вызывать как обычную C++ функцию и проверка типов могла происходить С/С++ непосредственно компилятором.\nМанглинг второго (дополнительного) имени функции заключается в добавлении в конец имени двух символов “_$”.\n# Определение функции в NewLang ::func_embed(int64_t arg_long, uint8_t arg_byte = 10): Int64 ::= { @return arg_long + arg_byte; } # С/С++ прототип для первого (основоного) имени # extern \"C\" _$$_func_embed$( Obj \u0026args ); # С/С++ прототип для второго (дополнительного) имени # extern \"C\" _$$_func_embed$_$(int64_t arg_long, uint8_t arg_byte = 10); # Тогда при раскрытии блока с расширенным синтаксисом # $func_embed заменяется на _$$_func_embed$_$, а компилятор С/С++ # будет в состоянии проверить её аргументы {% int64_t value = $func_embed(10, 20); %} Хотя может имеет смысл сделать inline шаблон для подобного вызова, а не создавать кополнительное имя?\n./object.h:732:25: error: deduced conflicting types ('int' vs 'const char *') for initializer list element type auto list = {args...}; ^~~~~ test/object_test.cpp:131:21: note: in instantiation of function template specialization 'newlang::Obj::operator()\u003cint, const char *\u003e' requested here str3 = (*format)(-1, \"222\"); ^ ","categories":"","description":"","excerpt":"Именование объектов основано на правилах и выбирается из расчёта …","ref":"/docs/arch/mangling/","tags":"","title":"Внутреннее имя и манглинг имен"},{"body":"Именование объектов основано на правилах и выбирается из расчёта удобства для программиста. Название переменной или функции должно нести смысл, понятные параметры и тип возвращаемого значения, которые упрощают понимание алгоритма при последующем чтении исходного текста программы.\nНо обычные имена мало о чём говорят компьютеру. Поэтому при компиляции программы, имена объектов преобразуются для удобства машинной обработки и к ним добавляется служебная информация.\nВнутреннее имя объекта Каждый объект имеет свое внутреннее имя, уникальное в рамках текущего модуля, с помощью которого комипилятор языка однозначно связывает объект с данными в памяти компьютера.\nВнутреннее имя формируется во время анализа синтаксического дерева программы. Оно включает в себя имя объекта, его квалификатор и полное пространство имен, в котором объект был опеределен.\nУ статических объектов (типов и классов), внутренее имя соотвествует полному имени объекта с учетом всех областей имен, тогда как внутреннее имя автоматичеких объектов включает в себя и пустые (не именованные) блоки кода, которые заменяются на монотонно возрастающий порядковый номер блока (т.е. ::1::, ::2:: и т.д.). Включение в пространство имен пустых блоков кода необходимо для реализации возможности перекрытия имен у объектов, определенных в разных областях видимости.\nКроме этого, все квалификаторы объектов переносятся в конец имени, что и является отличительным признаком внутреннего имени (последний символ должен быть “$” или “:”).\nПримеры внутренних имен:\n# Глобальный статический объект ::var ::= 0; # ::var:: # Локальный объект модуля $var := 0; # var$ # Статический объект модуля @::var ::= 0; # var:: # Глобальные тип и конструктор класса :: :type := :Type; # ::type::: :: :cls := Class(){}; # ::cls::: # Синоним типа или конструктор класса модуля :type := :Type; # type::: :cls := Class(){}; # cls::: # Тип или конструктор класса всегда статические @:: :type := :Type; # type::: @:: :cls := Class(){}; # cls::: ns { $var := 0; # ns::var$ var ::= 0; # ns::var$ @::var ::= 0; # ns::var:: - статический объект :type := :Type; # ns::type::: :cls := Class(){}; # ns::cls::: @::func1() ::= {}; # ns::func1:: func2() ::= {}; # ns::func2:: # Не именованный блок кода { # Локальные имена перекрывают объявления выше $var := 0; # ns::1::var$ var := 0; # ns::1::var$ # Статический объект соответствует области имен @::var ::= 0; # ns::var:: # Типы данных всегда статические :type := :Type; # ns::type::: :cls := Class(){}; # ns::cls::: @::func3() := {}; # ns::func3:: # Локальная функция с ограниченной областью видимости ????? func4() := {}; # ns::1::func4$ } }; # Не именованный блок кода { $var := 0; # 2::var$ var ::= 0; # 2::var$ @::var = 0; # var:: - статический объект :type := :Type; # type::: :cls := Class(){}; # cls::: }; Манглинг внутренних имен Внутреннее имя уникально только в рамках одного модуля, но внутренние имена в разных модулях могут пересекаться.\nМанглинг внутренних имя предназначен для объединения нескольких модулей в рамках одной программы, и используется как способ кодирования имени функции, структуры, класса или другого типа данных при передачи дополнительной семантической информации от компилятора компоновщику.\nВнутреннее имя объекта после манглинга является корректным идентификатором для языков C/C++, что позволяет обращатся к объектам NewLang из внешних библиотек и приложений на языке реализации (C/C++) по семантически похожему имени (в отличии от манглинга имен в С++).\nМанглинг внутреннего имени заключается в замене каждого символа двоеточия на символ $, а у имени типа квалификатор заменяется тремя символами ‘$’, т.е. ’type $$$’.\nПри манглинге, к внутренним именам объектов добавляется специальный префикс, который кодирует имя компилируемого модуля. Имя текущего модуля находится в переменной препроцессора \"@$$\" и по умолчанию, содержит имя файла модуля (у главного модуля приложения имя модуля отсутствует).\nИмя модуля может быть однократно переопределено самым первым оператором модуля или заменено во время импорта модуля с помощью системного параметра __package__.\n# Задать имя модуля @$$ = \"\\dir\\file\"; # Импорт модуля с переопределением имени \\dir\\file(__package__=\"\\new\\module\\name\"); Тоже само с использвоанием DSL:\n@package \\dir\\name; # @$$ = \"\\dir\\file\"; @import \\dir\\name as \\new\\module\\name; # \\dir\\file(__package__=\"\\new\\module\\name\"); При манглинге имя модуля, по умолчанию имя файла отностительно каталога главного файла программы, размещается в начале внутреннего системного имени. Так как имя модуля, согласно правилам синтаксиса, может содерждать только строчные буквы и цифры, то разделитель каталогов (обратный слеш) заменяется на подчерк, а начало и конец имени модуля отмечаются комбинациями символов “_$” и “$_” соответственно.\nТак как локальной переменной с одним подчерком в качестве имени быть не может, то начало строки на “_$” служит отличительным признаком манглинга внутреннего имени объекта.\n@$$ = \"\\dir\\file\"; # Глобальный статический объект ::var ::= 0; # _$dir_file$_$$var$$ # Локальный объект модуля $var := 0; # _$dir_file$_var$ # Статический объект модуля @::var ::= 0; # _$dir_file$_var$$ # Глобальные тип и конструктор класса :: :type := :Type; # _$dir_file$_$$type$$$ :: :cls := Class(){}; # _$dir_file$_$$cls$$$ # Синоним типа или конструктор класса модуля :type := :Type; # _$dir_file$_type$$$ :cls := Class(){}; # _$dir_file$_cls$$$ ns { $var := 0; # _$dir_file$_ns$$var$ var ::= 0; # _$dir_file$_ns$$var$ @::var ::= 0; # _$dir_file$_ns$$var$$ - статический объект :type := :Type; # _$dir_file$_ns$$type$$$ :cls := Class(){}; # _$dir_file$_ns$$cls$$$ @::func() ::= {}; # _$dir_file$_ns$$func$$ func() ::= {}; # _$dir_file$_ns$$func$ # Не именованный блок кода { # Локальные имена перекрывают обяъявления выше $var := 0; # _$dir_file$_ns$$1$$var$ var := 0; # _$dir_file$_ns$$1$$var$ # Статический объект соответствует области имен @::var ::= 0; # _$dir_file$_ns$$var$$ # Типы данных и функции всегда статические :type := :Type; # _$dir_file$_ns$$type$$$ :cls := Class(){}; # _$dir_file$_ns$$cls$$$ @::func() := {}; # _$dir_file$_ns$$func$$ func() := {}; # _$dir_file$_ns$$1$$func$ ???????? } }; # Не именованный блок кода { $var := 0; # _$dir_file$_2::var$ var ::= 0; # _$dir_file$_2::var$ @::var = 0; # _$dir_file$_var$$ - статический объект :type := :Type; # _$dir_file$_type$$$ :cls := Class(){}; # _$dir_file$_cls$$$ }; Манглинг имен блока кода главного модуля программы:\n{ $var := 0; # _$$_1::var$ var ::= 0; # _$$_1::var$ @::var = 0; # _$$_var$$ - статический объект :type := :Type; # _$$_type$$$ :cls := Class(){}; # _$$_cls$$$ }; Встроенный блок кода и вызов функций В расширенном синатксисе с исходным кодом языка реализации можно взаимодействовать с другим кодом программы за счет обращения к локальным объектам или макросам изнутри блока кода.\nЭто досупкается как для обычных переменных, так и для имен функций, реализованных в NewLang, и для того, что бы компилятор C/C++ имел возможность создать правильный код, при раскрытии встроенного блока кода перед ним добавляются сигнатуры переменных и функций, которые используются во строенном блоке кода.\nДля имен переменных дополнительный манглинг имен не производится, а для функций автоматичсеки создается дополнительная сигнатура с описанием типов аргументов и их значений по умолчанию, если таковые используются.\nКаждая функция NewLang имеет две сигнатуры, первая (основная) принимает все аргументы в виде словаря, а вторая (дополнительная) с развернутым списком аргументов, чтобы её можно было вызывать как обычную C++ функцию и проверка типов могла происходить С/С++ непосредственно компилятором.\nМанглинг второго (дополнительного) имени функции заключается в добавлении в конец имени двух символов “_$”.\n# Определение функции в NewLang ::func_embed(int64_t arg_long, uint8_t arg_byte = 10): Int64 ::= { @return arg_long + arg_byte; } # С/С++ прототип для первого (основоного) имени # extern \"C\" _$$_func_embed$( Obj \u0026args ); # С/С++ прототип для второго (дополнительного) имени # extern \"C\" _$$_func_embed$_$(int64_t arg_long, uint8_t arg_byte = 10); # Тогда при раскрытии блока с расширенным синтаксисом # $func_embed заменяется на _$$_func_embed$_$, а компилятор С/С++ # будет в состоянии проверить её аргументы {% int64_t value = $func_embed(10, 20); %} Хотя может имеет смысл сделать inline шаблон для подобного вызова, а не создавать кополнительное имя?\n./object.h:732:25: error: deduced conflicting types ('int' vs 'const char *') for initializer list element type auto list = {args...}; ^~~~~ test/object_test.cpp:131:21: note: in instantiation of function template specialization 'newlang::Obj::operator()\u003cint, const char *\u003e' requested here str3 = (*format)(-1, \"222\"); ^ ","categories":"","description":"","excerpt":"Именование объектов основано на правилах и выбирается из расчёта …","ref":"/ru/docs/arch/mangling/","tags":"","title":"Внутреннее имя и манглинг имен"},{"body":"Основные материалы по языку программирования NewLang.\nОписание акутально для текущей версии 4.0\nclang-17 не поддерживает:\nFeature Proposal Available Coroutines P0912R5 Partial Fully supported on all targets except Windows, which still has some stability and ABI issues. Extended floating-point types and standard names P1467R9 No Concepts P0848R3 Clang 16 (Partial) Modules No Начиная с C++ should adopt the same characters for C++26. Add @, $, and ` to the basic character set P2558R2 Yes ","categories":"","description":"","excerpt":"Основные материалы по языку программирования NewLang.\nОписание …","ref":"/ru/docs/","tags":"","title":"Документация"},{"body":"Все математические операторы имеют парный аналог с присвоением значения:\n+ и += — сложение арифметических типов данных; - и -= — вычитание арифметических типов данных; / и /= — деление (результат число с плавающей точкой); // и //= — целочисленное деление с округлением к меньшему числу (как в Python); * и *= — умножение (он же используется и для повторения текстовых строк); % и %= — остаток от целочисленного деления; Отдельный оператор для возведения в степень отсуствует.\nОператоры двоичного сдвига *) пока не реализованы .\u003c. - Битовый сдвиг влево .\u003e. - Битовый сдвиг вправо .\u003e\u003e. - Битовый сдвиг вправо с заполнением знакового бита .\u0026. - Битовый оператор И .|. - Битовый оператор ИЛИ .^. - Битовый оператор ИСКЛЮЧАЮЩЕЕ ИЛИ .~. - Битовый унарный оператор НЕ (инверсии) ","categories":"","description":"","excerpt":"Все математические операторы имеют парный аналог с присвоением …","ref":"/docs/ops/math/","tags":"","title":"Математические операторы"},{"body":"Все математические операторы имеют парный аналог с присвоением значения:\n+ и += — сложение арифметических типов данных; - и -= — вычитание арифметических типов данных; / и /= — деление (результат число с плавающей точкой); // и //= — целочисленное деление с округлением к меньшему числу (как в Python); * и *= — умножение (он же используется и для повторения текстовых строк); % и %= — остаток от целочисленного деления; Отдельный оператор для возведения в степень отсуствует.\nОператоры двоичного сдвига *) пока не реализованы .\u003c. - Битовый сдвиг влево .\u003e. - Битовый сдвиг вправо .\u003e\u003e. - Битовый сдвиг вправо с заполнением знакового бита .\u0026. - Битовый оператор И .|. - Битовый оператор ИЛИ .^. - Битовый оператор ИСКЛЮЧАЮЩЕЕ ИЛИ .~. - Битовый унарный оператор НЕ (инверсии) ","categories":"","description":"","excerpt":"Все математические операторы имеют парный аналог с присвоением …","ref":"/ru/docs/ops/math/","tags":"","title":"Математические операторы"},{"body":"NewLang поддерживает пространства имен, разделителем в которых, как и в С++, выступает двойное двоеточие “::”.\nОбласть имен может быть указана как для отдельного индетификатора, так и для целого блока кода.\nВ отличии от namespace в С++, области имен в NewLnag используются не только для организации кода в виде логических групп и с целью избежания конфликтов имен, но и для отнесения идентификатора, в котором явно указана область имен, к статическим объектам (память под которые выделяется на этапе комиляции программы).\nГлобальное имя не может быть перекрыто макросом или локальной переменной при разрешении имен (name lookup). Создать глобальную (статическую) переменную в текущем пространстве имен можно указав переменную препроцессора @::.\nДля использования пространства имен в блоке кода, его нужно указать перед открывающейся фигурной скобкой. В таком именованном блоке кода завершающие “::” указывать не обязательно.\n::var ::= 0; # Имя глобальной переменной в явном виде (не может быть перекрыто) ns { # Можно указать равнозначное ns:: var ::= 0; # Имя ns::var (может быть перекрыто макросом или локальной переменной) @::var ::= 0; # Имя глобальной переменной ::ns::var (не может быть перекрыто) name:: { var = 0; # Обращение к переменной ns::var var2 ::= 0; # Имя переменной будет ns::name::var2 ::var = 1; # Переменная из глобального пространства имен }; :: { # Глобальное пространство имен var = 1; # Имя глобальной переменной ::var (может быть перекрыто) ::ns::var = 0; # Имя другой глобальной переменной (не может быть перекрыто) }; }; Пространство имен, модули и пакеты Пространство имен в NewLang поддерживает одновременно с модульной структурой кода как в языках Java и Python и при указании полного имени объекта, программные модули и пространства имен можно объединять.\nНапример, полное имя переменой можно записать с указанием программного модуля \\root\\dir\\module::ns::name::var, где root и dir это каталоги в файловой системе относительно текущего модуля, а module — имя файла, т.е. root/dir/module.nlp.\nПространство имен и ООП В NewLang не применяется декорирование (манглинг) имен, основанный на типах аргументов функций.\nТем не менее при создания уникальных идентификаторов для методов классов NewLang использует подход, похожий на применяемый в языке Python. При создании метода класса создается глобальная функция с именем класса и именем метода, объединенные через разделитель “::”.\nНапример, для класса :NewClass при создании метода method будет создана функция с именем NewClass::method.\nТакая схема наименований методов полностью соответствует именованию функций в пространстве имен, и тем самым позволяет определять методы класса вне тела самого класса, просто указав нужное имя в пространстве имен или в явном виде.\nПример создания метода класса NewClass в области имен:\nNewClass:: { method() := { }; } Пример создания метода класса NewClass с указанием полного имени:\nNewClass::method() := { }; ","categories":"","description":"","excerpt":"NewLang поддерживает пространства имен, разделителем в которых, как и …","ref":"/ru/docs/syntax/namespace/","tags":"","title":"Пространства имен"},{"body":"Символьные строки NewLang поддерживает два типа строк:\n:StrChar - универсальные байтовые UTF-8 строки :StrWide - системные символьные (широкие символы) Единичным элементом универсальной UTF-8 строки является один байт, тогда как у системных символьных строк единичным элементом строки является широкий символ wchar_t.\nИ хотя строки различаются типами единичного элемента строки, но внутреннее представление у обоих типов строк одинаковое. Все данные символьных строки хранятся в виде универсальной байтовой UTF-8 последовательности.\nБайтовые строки :StrChar Единичным элементом универсальной байтовой строки является один байт (точнее :Int8, т.е. 8-ми битное целое число со знаком). Количество символов байтовой строки возвращается в байтах и обращение к элементу строки по индексу происходит к байту символьной последовательности. Так как данные строки интерпретируется как последовательность UTF-8 символов, нужно соблюдать осторожность при изменении отдельных байт!\nСистемные строки :StrWide Единичным элементом системной строки является широкий символ wchar_t, а количество элементов системной символьной строки возвращается в широких символах. Размер типа wchar_t зависит от операционной системы, поэтому размер одного символа :StrWide в Windows будет 2 байта, а в Linux 4 байта, что связано с их особенностями реализации.\nОсновоне назначение системных строк - упрощение работы в текстовом терминале, так как один символ всегда соответствует одному знакоместу без необходимости постоянного конвертирования кодовых точек UTF-8.\nФорматирование строк К любой переменной можно обратиться как к функции (указав после её имени круглые скобки) для создания копии/клона объекта, а для строк, такую операцию можно использовать как шаблон при форматировании данных.\nФорматирование строк можно сделать двумая способами:\nЗадать строку формата с указанием типов выводимых данных (строка формата соотвествует форматированию в стандартной функции printf). Для применения такого варината форматирования у строки формата необходимо указать соответствующий тип данных (:FmtChar или :FmtWide для обычных и широких символов соответствено).\nПри таком способе форматирования, именнованные аргументы использовать нельзя, а компилятор проверяет типы передаваемых значений на соответствие строке формата только во время компиляции текста программы.\nДанный тип форматной строки можно использовать как последний аргумент функции для проверки типов всех последующих аргументов на соотвестие строки формата.\nВо всех остальных случаях в качестве строки формата можно использовать любые строки и именованные аргументы, а сам формат соотвествует строке формата из библиотеки {fmt}.\nЕдинствено отличие заключается в возможности указания не только порядкового номера аргумента, но и его имени.\nПроверка аргументов на соответствие строки формата производится во время клонирования строки как во время компиляции, так и во время выполняения программы.\nДанный способ форматирования используется по умолчанию для любых типов строк, но проверка строки формата не выполняется в аргументах функции.\nНапример:\n$fmt := '%s: %d':FmtChar; # Форматирование как в printf $result := $fmt('value', 123); # \"value: 123\" - Check compile time only! $template := \"{name} {0}\"; # fmt::format equivalent \"{1} {0}\" $result := $template(\"шаблон\", name = \"Строка\"); # result = \"Строка шаблон\" ","categories":"","description":"","excerpt":"Символьные строки NewLang поддерживает два типа строк:\n:StrChar - …","ref":"/ru/docs/types/strings/","tags":["типы данных","строки"],"title":"Символьные строки"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/blog/","tags":"","title":"Статьи"},{"body":"Примеры программ на NewLang\nSelect an exmaple... Hello, world! Rational numbers without limitation of precision Factorial 40 Factorial 40 with DSL syntax Tensor example Playground run 0% Playground version: Output: ","categories":"","description":"","excerpt":"Примеры программ на NewLang\nSelect an exmaple... Hello, world! …","ref":"/playground/","tags":"","title":"Playground and example code"},{"body":"Примеры программ на NewLang\nSelect an exmaple... Hello, world! Rational numbers without limitation of precision Factorial 40 Factorial 40 with DSL syntax Tensor example Playground run 0% Playground version: Output: ","categories":"","description":"","excerpt":"Примеры программ на NewLang\nSelect an exmaple... Hello, world! …","ref":"/ru/playground/","tags":"","title":"Playground and example code"},{"body":"В NewLang реализована концепция программных модулей и пакетов - которая повторяет идею иерархического расположения файлов в каталогах файловой системы, примерно так же, как это сделано в языке Python, но разделителем имен выступает не точка, а символ “\\” (как разделитель каталогов в Windows).\nИмя модуля может содержать только строчные английские буквы или цифры. Данное ограничение связано с прямым отображением имен модулей на объекты в файловой системе, так как у разных файловых систем могут быть различные возможности с поддержкой кодировок и разные требования к преобразованию регистров символов.\nПод модулем в NewLang понимается файл исходным кодом (с расширением *.src). Модули предназначены для того, чтобы в них хранить часто используемые функции, классы, константы и т.п. Их можно условно разделить на модули и программы: программы предназначены для непосредственного запуска, а модули для импортирования их в другие программы, но функционально модули и программы ничем между собой не отличаются.\nОбъекты модуля Все объекты, определенные внутри одного модуля без указания глобального простанства имен, видны только в рамках текущего файла.\nВремя жизни статической и локальной переменных модуля одинаковые, и ограничены временм жизни самого модуля, но статическая и локальная переменные модуля отличаются с точки зрения многопоточности.\nСтатическая переменная модуля всегда будет в единственном экземпляре для всех потоков, тогда как локальная переменная модуля будет для каждого потока своя (аналог thread_local (C++11)).\nКак импортировать модули? Относительное имя программного модуля начинается на символ “\\”, и в этом случае расположение файла программного модуля указывается относительно текущего файла.\nАбсолютное имя программного модуля начинается на два символа “\\\\” и указывает на файл модуля относительно каталога текущего исполняемого файла (или в списке каталогов для поиска программных модулей, который можно переопределить, например, с помощью аргументов командной строки).\nПолное имя текущего модуля (файла) содержится в переменной препроцессора ‘@\\\\’.\nСамый простой способ импортировать модуль, это записать его имя со скобками как при вызове функции. Причем в скобках можно передать аргументы для инициализации модуля, список импортируемых функций и т.д.\nТак как NewLang разрабатывается как компилируемый язык, то загрузка модулей возможна как статически, так и динамически (очень похоже на статическую и динамическую ликновку с dll библиотеками).\n\\dir\\module() - статическая загрузка модуля по относительному пути \\\\root\\dir\\module() - статическая загрузка модуля по абсолютному пути \\\\(\"каталог\\файл\") - динамическая загрузка модуля во время выполнения программы При динамической линковке, компиляция исходного кода модуля и все проверки будут выполнятся только во время выполнения приложения, тогда как статическая загрузка модуля позволяет выявить возможные ошибки еще на этапе компиляции программы.\nПо умолчанию, при статической линковке модуля, импортируются все его макросы, функции и переменные модуля, тогда как при динамической загрузке моуля, макросы не импортируются. ?????????????????????????????????????????????????????????????\nЧто такое пакет в NewLang? Пакет в NewLang – это имя каталога, который включает в себя другие каталоги и модули и при этом содержит дополнительный файл __init__.src.\nПакеты используются как дополнение к пространству имен, что позволяет работать с модулями через указание уровня вложенности (через символ \\). Но в отличии от Python и Java, где модули и пакеты заменяют собой пространство имен (namespace), в NewLang модульная структура и области имен используются одновременно и при указании полного имени объекта, программные модули и пространства имен можно объединять.\nНапример, полное имя переменой можно записать с указанием программного модуля \\root\\dir\\module::ns::name::var, где root и dir это каталоги в файловой системе относительно текущего моделя, а module — имя файла, т.е. root/dir/module.src\nДля импортирования пакетов используется тот же синтаксис, что и для работы с модулями.\nИспользование пакетов Рассмотрим следующую структуру пакета:\nfincalc |-- __init__.src |-- simper.src |-- compper.src |-- annuity.src Пакет fincalc содержит в себе модули для работы с простыми процентами (simper.src), сложными процентами (compper.src) и аннуитетами (annuity.src). Файл __init__.src в отличии от Python, не может быть пустым, а должен в явном виде содержать команды загрузки модулей, входящих в пакет\nНапример для нашего случая содержимое __init__.src может быть вот таким:\n\\simper(); \\compper(); \\annuity(); Для использования функции fp из модуля для работы с простыми процентами, можно использовать один из следующих вариантов (для сравнения приведен аналогичный код на Python, когда это возможно):\nИмпорт одного модуля без указания псевдонима: Python:\nimport fincalc.simper fv = fincalc.simper.fv(pv, i, n) NewLang:\n\\fincalc\\simper(); fv := \\fincalc\\simper::fv(pv, i, n); С указанием псевдонима имени модуля: Python:\nimport fincalc.simper as sp fv = sp.fv(pv, i, n) NewLang:\nsp := \\fincalc\\simper(); fv := sp.fv(pv, i, n); Импорт одной конкретной функции: Python:\nfrom fincalc import fv result = fv(pv, i, n) NewLang:\n\\fincalc\\simper(__import__=\"fv\"); result := fv(pv, i, n); Импорт всего пакета: NewLang:\n\\fincalc(); result := fv(pv, i, n); ","categories":"","description":"","excerpt":"В NewLang реализована концепция программных модулей и пакетов - …","ref":"/docs/syntax/modules/","tags":"","title":"Модули и пакеты"},{"body":"В NewLang реализована концепция программных модулей и пакетов - которая повторяет идею иерархического расположения файлов в каталогах файловой системы, примерно так же, как это сделано в языке Python, но разделителем имен выступает не точка, а символ “\\” (как разделитель каталогов в Windows).\nИмя модуля может содержать только строчные английские буквы или цифры. Данное ограничение связано с прямым отображением имен модулей на объекты в файловой системе, так как у разных файловых систем могут быть различные возможности с поддержкой кодировок и разные требования к преобразованию регистров символов.\nПод модулем в NewLang понимается файл исходным кодом (с расширением *.src). Модули предназначены для того, чтобы в них хранить часто используемые функции, классы, константы и т.п. Их можно условно разделить на модули и программы: программы предназначены для непосредственного запуска, а модули для импортирования их в другие программы, но функционально модули и программы ничем между собой не отличаются.\nОбъекты модуля Все объекты, определенные внутри одного модуля без указания глобального простанства имен, видны только в рамках текущего файла.\nВремя жизни статической и локальной переменных модуля одинаковые, и ограничены временм жизни самого модуля, но статическая и локальная переменные модуля отличаются с точки зрения многопоточности.\nСтатическая переменная модуля всегда будет в единственном экземпляре для всех потоков, тогда как локальная переменная модуля будет для каждого потока своя (аналог thread_local (C++11)).\nКак импортировать модули? Относительное имя программного модуля начинается на символ “\\”, и в этом случае расположение файла программного модуля указывается относительно текущего файла.\nАбсолютное имя программного модуля начинается на два символа “\\\\” и указывает на файл модуля относительно каталога текущего исполняемого файла (или в списке каталогов для поиска программных модулей, который можно переопределить, например, с помощью аргументов командной строки).\nПолное имя текущего модуля (файла) содержится в переменной препроцессора ‘@\\\\’.\nСамый простой способ импортировать модуль, это записать его имя со скобками как при вызове функции. Причем в скобках можно передать аргументы для инициализации модуля, список импортируемых функций и т.д.\nТак как NewLang разрабатывается как компилируемый язык, то загрузка модулей возможна как статически, так и динамически (очень похоже на статическую и динамическую ликновку с dll библиотеками).\n\\dir\\module() - статическая загрузка модуля по относительному пути \\\\root\\dir\\module() - статическая загрузка модуля по абсолютному пути \\\\(\"каталог\\файл\") - динамическая загрузка модуля во время выполнения программы При динамической линковке, компиляция исходного кода модуля и все проверки будут выполнятся только во время выполнения приложения, тогда как статическая загрузка модуля позволяет выявить возможные ошибки еще на этапе компиляции программы.\nПо умолчанию, при статической линковке модуля, импортируются все его макросы, функции и переменные модуля, тогда как при динамической загрузке моуля, макросы не импортируются. ?????????????????????????????????????????????????????????????\nЧто такое пакет в NewLang? Пакет в NewLang – это имя каталога, который включает в себя другие каталоги и модули и при этом содержит дополнительный файл __init__.src.\nПакеты используются как дополнение к пространству имен, что позволяет работать с модулями через указание уровня вложенности (через символ \\). Но в отличии от Python и Java, где модули и пакеты заменяют собой пространство имен (namespace), в NewLang модульная структура и области имен используются одновременно и при указании полного имени объекта, программные модули и пространства имен можно объединять.\nНапример, полное имя переменой можно записать с указанием программного модуля \\root\\dir\\module::ns::name::var, где root и dir это каталоги в файловой системе относительно текущего моделя, а module — имя файла, т.е. root/dir/module.src\nДля импортирования пакетов используется тот же синтаксис, что и для работы с модулями.\nИспользование пакетов Рассмотрим следующую структуру пакета:\nfincalc |-- __init__.src |-- simper.src |-- compper.src |-- annuity.src Пакет fincalc содержит в себе модули для работы с простыми процентами (simper.src), сложными процентами (compper.src) и аннуитетами (annuity.src). Файл __init__.src в отличии от Python, не может быть пустым, а должен в явном виде содержать команды загрузки модулей, входящих в пакет\nНапример для нашего случая содержимое __init__.src может быть вот таким:\n\\simper(); \\compper(); \\annuity(); Для использования функции fp из модуля для работы с простыми процентами, можно использовать один из следующих вариантов (для сравнения приведен аналогичный код на Python, когда это возможно):\nИмпорт одного модуля без указания псевдонима: Python:\nimport fincalc.simper fv = fincalc.simper.fv(pv, i, n) NewLang:\n\\fincalc\\simper(); fv := \\fincalc\\simper::fv(pv, i, n); С указанием псевдонима имени модуля: Python:\nimport fincalc.simper as sp fv = sp.fv(pv, i, n) NewLang:\nsp := \\fincalc\\simper(); fv := sp.fv(pv, i, n); Импорт одной конкретной функции: Python:\nfrom fincalc import fv result = fv(pv, i, n) NewLang:\n\\fincalc\\simper(__import__=\"fv\"); result := fv(pv, i, n); Импорт всего пакета: NewLang:\n\\fincalc(); result := fv(pv, i, n); ","categories":"","description":"","excerpt":"В NewLang реализована концепция программных модулей и пакетов - …","ref":"/ru/docs/syntax/modules/","tags":"","title":"Модули и пакеты"},{"body":"Арифметическое сравнение Операторы арифметического сравнения представленными классическими \u003c, \u003e, \u003c=, \u003e=, == и !=. Они использются для сравнения между собой скаляров и рациональных чисел, а операторы сранвения на равенство == и !=, позвоялют сравнивать между собой в том числе и матрицы.\nОператоры сравнения == и != — операторы сравнения с автоматическим приведением совместимых типов для любых объектов\n== и != — операторы сравнения с автоматическим приведением совместимых типов для любых объектов\n=== и !== — операторы точного сравнения для любых объектов (автоматического приведения типов не выполняется). Для объектов сравниваются адреса размещения\nСтрогая статическая (номинальная) типизация Строгая статическая номинальная проверка типа объектов во время любых операций производится автоматически во время компиляции исходного текста программы, если хотя бы у одной из переменных при опеределении был указан её тип в явном виде.\nРезультат статической номинальной проверки типов будет успешным, если тип правого объекта может быть автоматически преобразован к типу левого операнда или тип правого операнада присутствует у левого в иерархии наследования.\nДинамическая номинальная типизация Для проверки имени типа (класса) объекта во время выполнения используется оператор тильда “~”. Это таже номинальная проверка типов, но только во время выполнения приложения. Левым операндом должен быть проверяемый объект, а правым — тип с которым сравнивается левый оператор.\nПравый оператор может быть строкой литералом, переменной строкового типа или именем проверяемого класса непосредственно. Результатом операции будет истина, если правый операнд содержит название класса проверяемого объекта или он присутствует у него в иерархии наследования.\nname := \"class\"; # Строковая переменная с именем класса var ~ name; var ~ :class; # Сравнение с типом var ~ \"class\"; # Имя типа как строка литерал Динамическая утиная типизация Оператор утиной типизации, два символа тильды “~~”. Проверяемым типом является левый оператор, а правый выступает в роли облазца для сравнения. Для простых типов сравнивается совместимость типа левого операнда по отношению к правому. А для словарей и классов в левом операнде проверяется наличие всех имен полей, присутствующих у правого операнда, т.е.:\n# Истина (т. е. левый операнд словарь) (field1=\"value\", field2=2,) ~~ (); # Тоже истина (т. к. поле field1 присутствует у левого операнда) (field1=\"value\", field2=2,) ~~ (field1=_); # Ложь, т.к. поле not_found у левого операнда отсутствует (field1=\"value\", field2=2,) ~~ (not_found=_); Строгая утиная типизация Строгая утиная типизация “~~~” для простых типов сравнивается идентичности типов без учета совместимости, а для составных типов происходит сравнение всех свойств с помощью оператора строгого равенства.\nДля данной операции, пустой тип совместим только с другим пустим типом.\n","categories":"","description":"","excerpt":"Арифметическое сравнение Операторы арифметического сравнения …","ref":"/docs/ops/compare/","tags":"","title":"Операторы сравнения и типизация"},{"body":"Арифметическое сравнение Операторы арифметического сравнения представленными классическими \u003c, \u003e, \u003c=, \u003e=, == и !=. Они использются для сравнения между собой скаляров и рациональных чисел, а операторы сранвения на равенство == и !=, позвоялют сравнивать между собой в том числе и матрицы.\nОператоры сравнения == и != — операторы сравнения с автоматическим приведением совместимых типов для любых объектов\n== и != — операторы сравнения с автоматическим приведением совместимых типов для любых объектов\n=== и !== — операторы точного сравнения для любых объектов (автоматического приведения типов не выполняется). Для объектов сравниваются адреса размещения\nСтрогая статическая (номинальная) типизация Строгая статическая номинальная проверка типа объектов во время любых операций производится автоматически во время компиляции исходного текста программы, если хотя бы у одной из переменных при опеределении был указан её тип в явном виде.\nРезультат статической номинальной проверки типов будет успешным, если тип правого объекта может быть автоматически преобразован к типу левого операнда или тип правого операнада присутствует у левого в иерархии наследования.\nДинамическая номинальная типизация Для проверки имени типа (класса) объекта во время выполнения используется оператор тильда “~”. Это таже номинальная проверка типов, но только во время выполнения приложения. Левым операндом должен быть проверяемый объект, а правым — тип с которым сравнивается левый оператор.\nПравый оператор может быть строкой литералом, переменной строкового типа или именем проверяемого класса непосредственно. Результатом операции будет истина, если правый операнд содержит название класса проверяемого объекта или он присутствует у него в иерархии наследования.\nname := \"class\"; # Строковая переменная с именем класса var ~ name; var ~ :class; # Сравнение с типом var ~ \"class\"; # Имя типа как строка литерал Динамическая утиная типизация Оператор утиной типизации, два символа тильды “~~”. Проверяемым типом является левый оператор, а правый выступает в роли облазца для сравнения. Для простых типов сравнивается совместимость типа левого операнда по отношению к правому. А для словарей и классов в левом операнде проверяется наличие всех имен полей, присутствующих у правого операнда, т.е.:\n# Истина (т. е. левый операнд словарь) (field1=\"value\", field2=2,) ~~ (); # Тоже истина (т. к. поле field1 присутствует у левого операнда) (field1=\"value\", field2=2,) ~~ (field1=_); # Ложь, т.к. поле not_found у левого операнда отсутствует (field1=\"value\", field2=2,) ~~ (not_found=_); Строгая утиная типизация Строгая утиная типизация “~~~” для простых типов сравнивается идентичности типов без учета совместимости, а для составных типов происходит сравнение всех свойств с помощью оператора строгого равенства.\nДля данной операции, пустой тип совместим только с другим пустим типом.\n","categories":"","description":"","excerpt":"Арифметическое сравнение Операторы арифметического сравнения …","ref":"/ru/docs/ops/compare/","tags":"","title":"Операторы сравнения и типизация"},{"body":"Для обработки перываний потока выполения, а также для обработки ошибкок компилятора используются С++ классы - наследники от std::exception, которые возвращают объект ошибки (значение).\nОшибка компилятора возвращает не только тестовое описание, но и объект TermPtr, при обработке которого возникла ошибка, тогда как перывание потока выполения возвращается объект ObjPtr.\nstd::exception -+-\u003e :ParserError | (TermPtr) | +-\u003e :RuntimeError ----\u003e :IntAny --+-\u003e :IntPlus (ObjPtr) | | +-\u003e :IntMinus При выполнении (генерации кода) именованные прерывания могут быть реализованы без использования исключений!\n","categories":"","description":"","excerpt":"Для обработки перываний потока выполения, а также для обработки …","ref":"/docs/arch/errors/","tags":"","title":"Реализация обработки ошибок и прерываний"},{"body":"Чтобы не усложнять обработку ошибок и не разделять их на внутренние и внешние, реализовано всего два класса для сообщения об ошибоках, накопительные и непосредственные + возврат значений.\nНакопительные ошибки и их реализация Накопительные ошибки используются при обработке исходного текста программы при его парсинге, анализа или компиляции. Накопительнность данных ошибок заключается в том, что процесс обработки исходного текста прерывается не сразу после возникновения первой ошибки, а только после превышения определнного лимита (по умолчанию –nlc-error-limit=10).\nДля логирования места возникновения ошибки используется макрос LOG_ERROR и при необходиости инкремент количества ошибок, или без оного (LOG_WARNING, LOG_INFO, LOG_DEBUG, LOG_DUMP) и обязательной пометкой термина TermPtr как причины её возникновения.\nПосле превышения лимита накопительных ошибок или при их наличии и завершении исходного текста программы, генерируется обычное исключение std::exception с описанием причины (последней ошибки).\nНепосредственные ошибки и их реализация Непосредственные ошибки применяются при выполнении (интерпретции) тела программы и предназнчены для информирования пользователя о возникновении ошибки прерывания работы программы. Так как контекст (текущий термин или строка в исходном файла) как правило не доступны, то сразу генерируется обычное исключение std::exception с описанием причины возникновения, а идентификация места её возникновения с конкретным исходным местом в тексте программы возлагается на обработчик прерываний.\nВозврат знечений Для обработки перываний потока выполения, используются отдельные С++ классы, которые не являются наследниками std::exception, чтобы специально разделить код обработки возврата значений от обработки ошибок, а при выполнении (генерации кода) именованные прерывания могут быть реализованы вообще без использования исключений (return, break, continue или goto)!\n:IntAny --+-\u003e :IntPlus (ObjPtr) | | +-\u003e :IntMinus ","categories":"","description":"","excerpt":"Чтобы не усложнять обработку ошибок и не разделять их на внутренние и …","ref":"/ru/docs/arch/errors/","tags":"","title":"Реализация прерываний и обработки ошибок"},{"body":"Объектно ориентированное программирование NewLang поддерживает следующую концепцию объектно-ориентированного программирования:\nКаждый объект представляет собой отдельный тип данных, который наследуется от другого типа или от одного из его наследников (что очень похоже на концепцию объектов в языке Java), а экземпляр конкретного класса создается путем вызова его типа.\nНаследование поддерживается для типов словарь (:Dictionary) и класс (:Class) и всех их потомков.\nСловарь Словарь (:Dictionary) — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии (это похоже и на tuple и на структуру одновременно). Словари отличаются от тензоров тем, что всегда имеют только одно измерение, но каждый элемент может содержать произвольное количество элементов любого типа, в том числе и другие словари.\nДоступ к элементам словаря происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. Индекс начинается с 0 и как у тензоров, тоже может быть отрицательным (индекс элемента от “конца”).\n# Новый тип (класс) :NewClass :Dict := :Dictionary() { _ := 1; # У поля данных имя отсутствует two := 2; name := 3; }; dict := :Dict(); # Экземпляр класса (1, two=2, name=3,):Dict dict2 := :Dict(two=42); # Экземпляр класса (1, two=42, name=100,):Dict dict3 := dict2(99, name=0); # Копия объекта dict2 (99, two=42, name=0,):Dict В будущем можно будет добавить возможность указывать индексы элементов словаря с помощь диапазонов\n$dict = :Dict[10](first=1, 4..4 = 29, 2..3 = 15, , 2..3 = 15, 7..9..2 = 7); #(first=1, 0, 15, 15, 29, 0, 0, 7, 0, 7,) Словарь как литерал Литерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, т. е. (,) — пустой словарь, (1, 2= «2», name=3,). Для указания конкретного типа объекта у литерала, его необходимо указать после закрывающей скобки, т.е. (1, two= «2», name=3,):Dict.\nВажный момент! Хоть такой объект и будет иметь указанный тип, но он будет “неполноценным” и содержать только те данные, которые были явно указаны в скобках, что не гарантирует корректного создания реального объекта, т.к. для создания “правильного” объекта требуется вызвать его тип, т.е. :Dict();\nТакой способ создания литералов классов используется в основном в различных операциях сравнения типов и “утиной типизации”, т.к. не требует доступа к рантайму, да и сам класс может быть не определен.\nПеречисление, структура и объединение Существуют три отдельных типа данных, :Enum, :Struct и :Union — которые так же являются словарями, но на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера. Эти типы данных одновременно относятся к группе нативных типов и могут быть представлены в двоичном виде в одной области машинной памяти.\n","categories":"","description":"","excerpt":"Объектно ориентированное программирование NewLang поддерживает …","ref":"/docs/types/dicts/","tags":["типы данных","ООП","коллекции"],"title":"Словари"},{"body":"Объектно ориентированное программирование NewLang поддерживает следующую концепцию объектно-ориентированного программирования:\nКаждый объект представляет собой отдельный тип данных, который наследуется от другого типа или от одного из его наследников (что очень похоже на концепцию объектов в языке Java), а экземпляр конкретного класса создается путем вызова его типа.\nНаследование поддерживается для типов словарь (:Dictionary) и класс (:Class) и всех их потомков.\nСловарь Словарь (:Dictionary) — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии (это похоже и на tuple и на структуру одновременно). Словари отличаются от тензоров тем, что всегда имеют только одно измерение, но каждый элемент может содержать произвольное количество элементов любого типа, в том числе и другие словари.\nДоступ к элементам словаря происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. Индекс начинается с 0 и как у тензоров, тоже может быть отрицательным (индекс элемента от “конца”).\n# Новый тип (класс) :NewClass :Dict := :Dictionary() { _ := 1; # У поля данных имя отсутствует two := 2; name := 3; }; dict := :Dict(); # Экземпляр класса (1, two=2, name=3,):Dict dict2 := :Dict(two=42); # Экземпляр класса (1, two=42, name=100,):Dict dict3 := dict2(99, name=0); # Копия объекта dict2 (99, two=42, name=0,):Dict В будущем можно будет добавить возможность указывать индексы элементов словаря с помощь диапазонов\n$dict = :Dict[10](first=1, 4..4 = 29, 2..3 = 15, , 2..3 = 15, 7..9..2 = 7); #(first=1, 0, 15, 15, 29, 0, 0, 7, 0, 7,) Словарь как литерал Литерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, т. е. (,) — пустой словарь, (1, 2= «2», name=3,). Для указания конкретного типа объекта у литерала, его необходимо указать после закрывающей скобки, т.е. (1, two= «2», name=3,):Dict.\nВажный момент! Хоть такой объект и будет иметь указанный тип, но он будет “неполноценным” и содержать только те данные, которые были явно указаны в скобках, что не гарантирует корректного создания реального объекта, т.к. для создания “правильного” объекта требуется вызвать его тип, т.е. :Dict();\nТакой способ создания литералов классов используется в основном в различных операциях сравнения типов и “утиной типизации”, т.к. не требует доступа к рантайму, да и сам класс может быть не определен.\nПеречисление, структура и объединение Существуют три отдельных типа данных, :Enum, :Struct и :Union — которые так же являются словарями, но на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера. Эти типы данных одновременно относятся к группе нативных типов и могут быть представлены в двоичном виде в одной области машинной памяти.\n","categories":"","description":"","excerpt":"Объектно ориентированное программирование NewLang поддерживает …","ref":"/ru/docs/types/dicts/","tags":["типы данных","ООП","коллекции"],"title":"Словари"},{"body":" Ответ прост: классы не строго необходимы для ООП. Знаю, это может шокировать.\nРазумеется, нам нужна возможность создания новых объектов, и языки на основе классов, очевидно, распространены сильнее. Однако это не единственный способ достижения цели.\nВ языках наподобие JavaScript (хотя ES6 добавил в язык классы6, 7) и Lua используется концепция ООП на основе прототипов или прототипного ООП. Вместо создания схемы для конструирования новых объектов мы используем существующий объект в качестве прототипа. Такой подход даже может иметь реальные преимущества, поскольку снижает сложность языка8.\nТип данных :Class аналогичен словарю, но все его поля обязаны иметь имена (хотя доступ к свойствам класса по индексу так же возможен). При создании экземпляра класса, создается новая переменная, для которой копируются свойства и методы всех родителей.\nСоздание нового сложного типа (класса), происходит согласно правилам синтаксиса как создание функции в пользовательском пространстве имен. Имя функции является именем нового класса, а сама функция будет выступает в роли конструктора экземпляров класса.\nСинтаксис создание класса выглядит следующим образом:\n# Новый тип (класс) :NewClass ns::NewClass() := :Class() { # Родительские класс или несколько классов через запятую # Конструктор класса - весь блок кода с определением полей и методов @::static := 1; # Поле класса (у всех объектов одно значение) static := 1; # Поле класса (у всех объектов одно значение) .field := 1; # Поле объекта func() := {}; # Метод класса всегда статический #.method() := {}; # Метод объекта (у каждого объекта свой) ~NewClass() ::= { # Деструктор класса }; }; obj := ns::NewClass(); # Экземпляр класса Так как NewLang реализует полный набор вариантов проверок при создании объектов, то переопределения наследуемых функций не требует никаких ключевых слов:\nNewClass2() := NewClass() { # Новый класс на базе существующего .field ::= 2; # Будет ошибка, т.к. поле field уже есть в базовом классе method() = {}; # Аналог override, т.к. method должен существовать в базовом классе }; Интерфейсы, именование методов классов и пространства имен Для создания уникальных идентификаторов на основе имен методов классов, NewLang использует подход, похожий на применяемый в языке Python. При создании метода класса, создается глобальная функция с именем класса и именем метода, объединенные через разделитель области имен. Например, в классе NewClass2 при создании метода method будет создана функция с именем ::NewClass2::method.\nТакая схема наименований методов полностью соответствует именованию функций в пространствах имен, и тем самым позволяет определять классы c чистыми виртуальными функциями (методами без реализации), а в последствии определять их в пространстве имен или указав полное имя в явном виде.\nns:: { NewClass3 := NewClass() { # Новый класс на базе существующего virtual() := _; # Виртуальный метод }; }; obj := ns::NewClass3(); # объект создать нельзя, будет ошибка # Определить функцию для виртуального метода ns::NewClass3::virtual() := {}; obj := ns::NewClass3(); # ОК Конструкторы, деструкторы и финализаторы у объектов ns::NewClass() := Class() { # Новый класс на базе существующего # Блок кода функции - конструктор объекта __NewClass__() = {...}; # Метод с системным именем типа - деструктор объекта (вызывается сразу после удаления) _NewClass() := {...}; # Скрытый метод с именем типа - защищенный конструктор объекта ????????????????? __NewClass() := {...}; # Скрытый метод с именем типа - приватный конструктор объекта ????????????????? :NewClass(type) ::= {...}:NewClass; # Функция для приведения типа объекта $type к типу :NewClass ~NewClass() = {...}; # Скрытый метод - финализатор (вызывается перед освобождением памяти) __equals__(obj):Bool = { __compare__($obj) == 0 }; __compare__(obj):Int8 = { :: __compare__(@this, $obj) }; _() := {...}; # ????????????????????????????????????? }; extension methods !\nПишу на С++ последние лет 20, до этого ещё Delphi лет 10. С годами полностью отошёл от ООП в сторону data-driven design. Классы — практически структуры, из методов как правило только декоративные геттеры. Всё остальное — это просто функции с понятными названиями, сигнатурами и операндами-объектами таких вот классов-носителей данных и состояния. Получается, очень легко дышится и чистенько — состояния изолированы в структуры, логика изолирована в функции. Конечно, в C++ всё довольно печально с ООП как таковым, поскольку нет механизма extension methods — это когда вы собираете методы в класс из разных единиц трансляции из-за этого, обычные функции C++ значительно удобнее методов класса\nОсновная мысль, которая почти всегда теряется при обсуждении ООП, это то, зачем он нужен и в чем его суть. Все сводится к инструментам, их правильном и неправильном использовании, практичных архитектурах и оверинженеринге.\nМне кажется самая главная мысль очень проста. Сложная программа это сложное состояние. Проблема в том, что сложно следить за всей возможной суперпозицией всех деталей состояния. Небольшое состояние гораздо проще валидировать и постоянно поддерживать целостным. Если ты собираешь сложное состояние из простых целостных состояний, то его тоже проще поддерживать целостным (потому что нужно следить только за высокоуровневым состоянием, но не за всеми деталями)\nСоответственно ООП - это способ описания программы как набора иерархии изолированных состояний, где операции по изменению состояний максимально приближены к состоянию.\nТочно так же как сложную функцию можно представить как последовательность простых, так и сложное состояние можно представить комбинацией простых состояний. Изоляция и контроль состояний и есть основная идея ООП.\nФП подходит с другой стороны - максимально старается избежать состояния и работать только с текущим контекстом. Подход не лишен логики, но любая программа - это прежде всего состояние.\nВсе остальное - лишь инструменты и особенности реализации. ООП может быть реализовано почти на любом языке самыми разными инструментами и не обязательно требует интерфейсов, классов, сообщений, инкапсуляции и т.д. Но разумеется современные ООП языки хорошо адаптированы для такого способа описания. В конечном итоге если подсказки или области видимости действительно не дают тебе менять состояние объекта - это и есть прямая польза на этапе понимания и доработки твоего кода. Тебе просто не нужно думать и знать о состоянии объекта, когда ты с ним не работаешь.\nГлавное в ООП - это то, что есть данные, и есть методы которые напрямую работают с этими данными. Это то, что можно засунуть в один объект. Другой объект, который хочет получить данные из первого объекта, обязан пользоваться публичными методами.\nЭто упрощает поддержку обратной совместимости, упрощает изоляцию объектов, упрощает версионирование в случае многократного использования одними объектами других объектов.\nИ опять таки, суть не в том, что это чем-то напоминает рест-апи или библиотеки, а в том, что это парадигма программирования, которая упрощает организацию разработки сложных проектов, в которых задействовано много разработчиков.\nВсе остальные штуки - наследование, интерфейсы и все другое - это не суть ООП, а различные варианты решения или оптимизации различных кейсов\n","categories":"","description":"","excerpt":" Ответ прост: классы не строго необходимы для ООП. Знаю, это может …","ref":"/docs/types/class/","tags":["типы данных","ООП","коллекции"],"title":"Классы"},{"body":" Ответ прост: классы не строго необходимы для ООП. Знаю, это может шокировать.\nРазумеется, нам нужна возможность создания новых объектов, и языки на основе классов, очевидно, распространены сильнее. Однако это не единственный способ достижения цели.\nВ языках наподобие JavaScript (хотя ES6 добавил в язык классы6, 7) и Lua используется концепция ООП на основе прототипов или прототипного ООП. Вместо создания схемы для конструирования новых объектов мы используем существующий объект в качестве прототипа. Такой подход даже может иметь реальные преимущества, поскольку снижает сложность языка8.\nТип данных :Class аналогичен словарю, но все его поля обязаны иметь имена (хотя доступ к свойствам класса по индексу так же возможен). При создании экземпляра класса, создается новая переменная, для которой копируются свойства и методы всех родителей.\nСоздание нового сложного типа (класса), происходит согласно правилам синтаксиса как создание функции в пользовательском пространстве имен. Имя функции является именем нового класса, а сама функция будет выступает в роли конструктора экземпляров класса.\nСинтаксис создание класса выглядит следующим образом:\n# Новый тип (класс) :NewClass ns::NewClass() := :Class() { # Родительские класс или несколько классов через запятую # Конструктор класса - весь блок кода с определением полей и методов @::static := 1; # Поле класса (у всех объектов одно значение) static := 1; # Поле класса (у всех объектов одно значение) .field := 1; # Поле объекта func() := {}; # Метод класса всегда статический #.method() := {}; # Метод объекта (у каждого объекта свой) ~NewClass() ::= { # Деструктор класса }; }; obj := ns::NewClass(); # Экземпляр класса Так как NewLang реализует полный набор вариантов проверок при создании объектов, то переопределения наследуемых функций не требует никаких ключевых слов:\nNewClass2() := NewClass() { # Новый класс на базе существующего .field ::= 2; # Будет ошибка, т.к. поле field уже есть в базовом классе method() = {}; # Аналог override, т.к. method должен существовать в базовом классе }; Интерфейсы, именование методов классов и пространства имен Для создания уникальных идентификаторов на основе имен методов классов, NewLang использует подход, похожий на применяемый в языке Python. При создании метода класса, создается глобальная функция с именем класса и именем метода, объединенные через разделитель области имен. Например, в классе NewClass2 при создании метода method будет создана функция с именем ::NewClass2::method.\nТакая схема наименований методов полностью соответствует именованию функций в пространствах имен, и тем самым позволяет определять классы c чистыми виртуальными функциями (методами без реализации), а в последствии определять их в пространстве имен или указав полное имя в явном виде.\nns:: { NewClass3 := NewClass() { # Новый класс на базе существующего virtual() := _; # Виртуальный метод }; }; obj := ns::NewClass3(); # объект создать нельзя, будет ошибка # Определить функцию для виртуального метода ns::NewClass3::virtual() := {}; obj := ns::NewClass3(); # ОК Конструкторы, деструкторы и финализаторы у объектов ns::NewClass() := Class() { # Новый класс на базе существующего # Блок кода функции - конструктор объекта __NewClass__() = {...}; # Метод с системным именем типа - деструктор объекта (вызывается сразу после удаления) _NewClass() := {...}; # Скрытый метод с именем типа - защищенный конструктор объекта ????????????????? __NewClass() := {...}; # Скрытый метод с именем типа - приватный конструктор объекта ????????????????? :NewClass(type) ::= {...}:NewClass; # Функция для приведения типа объекта $type к типу :NewClass ~NewClass() = {...}; # Скрытый метод - финализатор (вызывается перед освобождением памяти) __equals__(obj):Bool = { __compare__($obj) == 0 }; __compare__(obj):Int8 = { :: __compare__(@this, $obj) }; _() := {...}; # ????????????????????????????????????? }; extension methods !\nПишу на С++ последние лет 20, до этого ещё Delphi лет 10. С годами полностью отошёл от ООП в сторону data-driven design. Классы — практически структуры, из методов как правило только декоративные геттеры. Всё остальное — это просто функции с понятными названиями, сигнатурами и операндами-объектами таких вот классов-носителей данных и состояния. Получается, очень легко дышится и чистенько — состояния изолированы в структуры, логика изолирована в функции. Конечно, в C++ всё довольно печально с ООП как таковым, поскольку нет механизма extension methods — это когда вы собираете методы в класс из разных единиц трансляции из-за этого, обычные функции C++ значительно удобнее методов класса\nОсновная мысль, которая почти всегда теряется при обсуждении ООП, это то, зачем он нужен и в чем его суть. Все сводится к инструментам, их правильном и неправильном использовании, практичных архитектурах и оверинженеринге.\nМне кажется самая главная мысль очень проста. Сложная программа это сложное состояние. Проблема в том, что сложно следить за всей возможной суперпозицией всех деталей состояния. Небольшое состояние гораздо проще валидировать и постоянно поддерживать целостным. Если ты собираешь сложное состояние из простых целостных состояний, то его тоже проще поддерживать целостным (потому что нужно следить только за высокоуровневым состоянием, но не за всеми деталями)\nСоответственно ООП - это способ описания программы как набора иерархии изолированных состояний, где операции по изменению состояний максимально приближены к состоянию.\nТочно так же как сложную функцию можно представить как последовательность простых, так и сложное состояние можно представить комбинацией простых состояний. Изоляция и контроль состояний и есть основная идея ООП.\nФП подходит с другой стороны - максимально старается избежать состояния и работать только с текущим контекстом. Подход не лишен логики, но любая программа - это прежде всего состояние.\nВсе остальное - лишь инструменты и особенности реализации. ООП может быть реализовано почти на любом языке самыми разными инструментами и не обязательно требует интерфейсов, классов, сообщений, инкапсуляции и т.д. Но разумеется современные ООП языки хорошо адаптированы для такого способа описания. В конечном итоге если подсказки или области видимости действительно не дают тебе менять состояние объекта - это и есть прямая польза на этапе понимания и доработки твоего кода. Тебе просто не нужно думать и знать о состоянии объекта, когда ты с ним не работаешь.\nГлавное в ООП - это то, что есть данные, и есть методы которые напрямую работают с этими данными. Это то, что можно засунуть в один объект. Другой объект, который хочет получить данные из первого объекта, обязан пользоваться публичными методами.\nЭто упрощает поддержку обратной совместимости, упрощает изоляцию объектов, упрощает версионирование в случае многократного использования одними объектами других объектов.\nИ опять таки, суть не в том, что это чем-то напоминает рест-апи или библиотеки, а в том, что это парадигма программирования, которая упрощает организацию разработки сложных проектов, в которых задействовано много разработчиков.\nВсе остальные штуки - наследование, интерфейсы и все другое - это не суть ООП, а различные варианты решения или оптимизации различных кейсов\n","categories":"","description":"","excerpt":" Ответ прост: классы не строго необходимы для ООП. Знаю, это может …","ref":"/ru/docs/types/class/","tags":["типы данных","ООП","коллекции"],"title":"Классы"},{"body":"https://habr.com/companies/otus/articles/763810/ https://habr.com/articles/764420/\nПоследовательная согласованность отсутствует (отсутствуют атомарныти типы) Любой язык программирования так или иначе вынужден управлять оперативной памятью. В NewLang реализовано автоматическое управление памятью без сборщика мусора.\nЗа основу была взята модель “владения” из языка Rust, но она переработана под концепцию сильных и слабых указателей (аналоги shared_ptr и weak_ptr из С++), где каждое значение в памяти может иметь только одну переменную-владельца с сильным указателем.\nИ когда такая переменная-владелец уходит из области видимости, счетчик ссылок уменьшается и при достжении нуля память освобождается.\nФактически, это автоматическое управление памятью с помощью подсчёта ссылок на этапе компиляции и без использования сборщика мусора.\nСуществование ссылок на объекты предполагает и возможность одновременного доступа к данным из нескольких потоков выполнения. Из-за чего управление памятью включает в себя и элементы межпотокового взаимодействия, так как совместное владение ссылками по любому будет требовать каких либо механизмов синхронизации доступа к разеделяемой памяти объектов.\nПоэтому, при определении объекта указывается, какие типы ссылок допускается создавать на него, а так-же какая используется модель совместного доступа к переменной.\nВесь механизм подсчета ссылок и проверки их корректности реализован на уровне синтаксиса. В рантайме выполняется только контроль идентификатора потока для однопоточных ссылок, а все остальные проверки выполняются во время компиляции.\nУправление памятью и терминология Врчную выделить или освобондить память нельзя\nЛюбой объект - это ссылка на область памяти с данным. Память выделяется и освобожадется автоматически при создании/удалении объектов\nСсылки на объекты, с точки зрения владения, могут быть:\nСильные/Владеющие ссылки (аналог shared_ptr из С++), а фактические, это переменная которая хранит значение объекта. Слабые/Не владеющие ссылки (аналог weak_ptr из С++) - указатели на другим объекты которые перед использованием требуют обязательного захвата (т.е. преобразования в сильную ссылку). Ссылки на объекты, с точки зрения совместного доступа, могут быть:\nЛегкие - ссылки без объекта синхронизации Тяжелые - ссылки с объектом синхронизации совметсного доступа (мьютексом). Переменные - владельцы объектов (в них хранятся ссылки) могут быть двух видов:\nлокальные (контролируемые) - область жизни локальных переменных строго ограничена и определяется правилами синтаксиса языка (аргументы и локальные переменные функций, потоков и т.д.). не контролируемые - глобальные или статические переменные, динамически создаваемые объекты, время жизни которых компилятор не контролирует. Когда локальная переменная удаляется - уменьшается счетчик ссылок, а при достижении нуля - объект освобождается.\nКаждый объект может иметь только одну не контролируемую переменную с сильной ссылкой и произвольное количество любых дргуих типов ссылок в локальных (контролируемых) переменных.\nДля не контролируемых переменных разрешается делать только слабые ссылки, которые перед использованием требуется захватить, например в локальную (контролируемую) переменную.\nУправление временем жизни объекта включает в себя не только управлением памятью, но и при необходимости, создаются механизмы синхронизации доступа к ней. Для этого при определении переменной, описываются возможные типы ссылок, которые разрешено на неё получать:\nбез создания ссылок, т.е. компилятор не даст создать ссылку на данную переменную, а совместный доступ к такой переменой будет не возможен возможно создание легкой ссылки (\"\u0026\"). Компилятору при генерации машинного кода не нужно создавать объект синхронизации доступа к переменной.\nСсылки для полей структур или объектов могут быть только легкими. разрешено создавать ссылки с монопольным доступом (\"\u0026\u0026\"). Компилятор автоматически создает не рекурсивный мьютекс для синхронизации доступа к переменной, т.е. ссылка у этой переменной будет тяжелой. разрешено создавать ссылки с рекурсивным доступом (\"\u0026*\"). Компилятор автоматически создает рекурсивный мьютекс (его можно захватывать несколько раз), а ссылка у этой переменной будет тяжелой. легкая ссылка может быть создана для совместного доступа (\"\u0026?\"), но её захват и синхронизация доступа к ней возможен только при групповом захвате ссылок. Все виды ссылок могут быть константными (\"\u0026^\", “\u0026\u0026^” или “\u0026*^”), т.е. только для чтения (и в случае константных объектов, таким ссылкам мьютекс не потребуется).\nЗахват слабой ссылки может быть индивидуальным или групповым с сохранением результата в локальную (контролируемую) переменную. Такое использование логики захвата объекта на уровне синтаксиса языка гарантирует последующее автоматическое освобождение временной переменной, что равнозначно невозможности создания циклических ссылок.\nПеременная со слабой/не владеющей ссылкой создается только тогда, когда в правой части операции присвоения присутствует любой из операторов получения ссылки (\u0026, \u0026\u0026, \u0026* или \u0026^, \u0026\u0026^, \u0026*^).\nВо всех остальных случаях создается переменная владелец с сильной/владеющей ссылкой (если это разрешено).\nЗахват ссылки и значение переменной Захват ссылки - это преобразование слабой ссылки в сильную с её сохранением в контролируемую переменую с инкрементом счетчика ссылок и возможностью доступа к значению объекта. Это очень похоже на заимствование (Borrowing) в Rust, так как тоже позволяет использовать данные, находящиеся во владении другой переменной, но без перехода владения. Для захвата ссылок используются операторы:\n‘*’ или ‘*( … )’ - автоматический выбор типа доступа (чтения/запись или только чтение) ‘*^’ или ‘*^( … )’ - захват доступа только для чтения ‘**( … )’ - групповой захват ссылок в локальные (контролируемые) переменные () после имени переменной - создание копии значения переменной (глубокое клонирование) ??????????????????????????????????? Упрощенный условный пример:\nref := \u0026 owner; # переменная ref - слабая ссылка на owner ref_ro := \u0026^ owner; # слабая ссылка на owner только для чтения val := * ref; # Автоматический захват только для чтения *ref = val; # Автоматический захват для чтения/записи val := *^ ref; # Захват только для чтения val := *^ ref_ro; val := * ref_ro; # Автоматический захват только для чтения *ref_ro = val; # Ошибка - ссылка только для чтения !!! *^ ref_ro = val; # Ошибка - недопустима конструкция (захват lval - только для чтения) Слабую ссылку можно захватить (превратить в сильную) сохранив результат в локальной переменной, после чего работать с локальной переменной “по значению” без необходимости захватытвать ссылку при каждом обращении к переменной. Значения переменных со слабыми ссылками можно копировать в другие переменные без ограничений. Значение переменной с сильной ссылкой нельзя скопировать в другую переменную или поле объекта, но можно клонировать данные или обменяться значениями “:=:” с другой переменной с сильной ссылкой (swap). Примеры владения:\nowner := \"string\"; other := \"string 2\"; owner = other; # Ошибка - нельзя копировать! owner = other(); # Глубокое клонирование данных owner :=: other; # Обмен значениями (swap) other = _; # Очистка данных объекта Переменную, содержащую ссылку на ссылку создать нельзя, но можно создать ссылочный тип и после этого создать переменную-ссылку на этот тип данных. Упрощенный условный пример:\nvalue := 123; :RefInt := \u0026 Integer; ref_int :RefInt := \u0026 value; ref_ref := \u0026 ref_int; Если переменная владелец разрешает создавать ссылки на объект, тогда при обращении к такой переменой требуется выполнять захват объекта для обеспечения работы механизма совместного доступа. Ссылки и совместный доступ Управление временем жизни переменной включает в себя не только управление памятью, но и механизм синхронизации для монопольного/раздельного доступа к объектам из разных потоков.\nПримеры ссылок:\n\u0026 local := 123; # Разрешено создание ссылок только в текущем потоке \u0026\u0026 thread := 456; # Разрешено создание ссылок с монопольным доступом в любом потоке ref := \u0026 local; # Создание слабой ссылки на local ref2 := \u0026\u0026 local; # Ошибка! многопоточные ссылки не разрешены ref_th := \u0026\u0026 thread; # Создание слабой ссылки на thread # c монопольной блокировкой доступа local += 1; # ОК thread += 1; # Ошибка, требуется захват объекта с разеляемым доступом *local += 1; # ОК, оператор захвата игнорируется *thread += 1; # Захват объекта (как захват слабой ссылки) ref += 1; # Ошибка, требуется захват слабой ссылки ref_th += 1; # Ошибка, требуется захват слабой ссылки *ref += 1; *ref_th += 1; Операторы захвата ссылки и синхронизации доступа к объекту выполняются только для одного действия над переменной. Но захват объекта синхронизации, это относительно медленная операция и выполнять её для каждого действия над переменной не рационально.\nДля того, чтобы однократно захватить объект(ы) синхронизации для выполнения сразу нескольких действий над переменными можно захватить объект в локальную переменую или использовать менеджер контекста.\nПример программы rand():Int32 ::= %rand...; # Создание объекта @( rand():Int32 ); # Предварительное объявление (объект должен быть создан в другом месте) rand():Int32 = ...; usleep(usec:DWord64):None := %usleep...; printf(format:FmtChar, ...):Int32 := %printf...; func(count:Integer, target:String) := { $iter := @iter( 1..$count ); # Итератор для диапазона от 1 до $count @while( @curr($iter) ) { # Цикл, пока итератор валидный $step := @next($iter); # Получить текущий и перейти на следующий элемент итератора printf('Number %d from %s!', $step, $target); usleep( rand() % 1000 ); # Случайная задержка } } thread = :Thread(func, 5, 'thread'); thread.start(); func(5, 'main'); thread.join(); Number 1 from the thread! Number 1 from the main! Number 2 from the thread! Number 2 from the main! Number 3 from the thread! Number 4 from the thread! Number 3 from the main! Number 4 from the main! Number 5 from the main! Number 5 from the thread! Примеры ссылок:\n\u0026 $local := 123; # Разрешено получение легких ссылок \u0026\u0026 $thread := 456; # Доступ к переменной требует захвата тяжелой ссылки $ref := \u0026 $local; # получение слабой ссылки на local $ref2 := \u0026\u0026 $local; # Ошибка! Тяжелой многопоточные ссылки не разрешены $ref_th := \u0026\u0026 $thread; # Получение слабой ссылки на thread # c монопольной блокировкой доступа $local += 1; # ОК (для легких ссылок блокировка объекта не требуется) $thread += 1; # ОК (захват объекта происходит автоматически) $ref += 1; # Ошибка, требуется захват легкой слабой ссылки $ref_th += 1; # Ошибка, требуется захват тяжолой слабой ссылки *$local += 1; # ОК *$thread += 1; # ОК *$ref += 1; # ОК (только захват ссылки, блокировка игнорируется) *$ref_th += 1; # ОК (захват ссылки и блокироваки доступа) Менеджер контекста Операторы захвата ссылки и синхронизации доступа к объекту выполняются только для одного действия над переменной. Но захват объекта синхронизации, это относительно медленная операция и выполнять её для каждого действия над переменной не рационально.\nДля того, чтобы однократно захватить объект(ы) синхронизации для выполнения сразу нескольких действий над переменными используется менеджер контекста.\n","categories":"","description":"","excerpt":"https://habr.com/companies/otus/articles/763810/ …","ref":"/docs/syntax/memory/","tags":"","title":"Управление памятью, ссылки и совместный доступ"},{"body":"https://habr.com/ru/companies/otus/articles/763810/ https://habr.com/ru/articles/764420/\nПоследовательная согласованность отсутствует (отсутствуют атомарныти типы) Любой язык программирования так или иначе вынужден управлять оперативной памятью. В NewLang реализовано автоматическое управление памятью без сборщика мусора.\nЗа основу была взята модель “владения” из языка Rust, но она переработана под концепцию сильных и слабых указателей (аналоги shared_ptr и weak_ptr из С++), где каждое значение в памяти может иметь только одну переменную-владельца с сильным указателем.\nИ когда такая переменная-владелец уходит из области видимости, счетчик ссылок уменьшается и при достжении нуля память освобождается.\nФактически, это автоматическое управление памятью с помощью подсчёта ссылок на этапе компиляции и без использования сборщика мусора.\nСуществование ссылок на объекты предполагает и возможность одновременного доступа к данным из нескольких потоков выполнения. Из-за чего управление памятью включает в себя и элементы межпотокового взаимодействия, так как совместное владение ссылками по любому будет требовать каких либо механизмов синхронизации доступа к разеделяемой памяти объектов.\nПоэтому, при определении объекта указывается, какие типы ссылок допускается создавать на него, а так-же какая используется модель совместного доступа к переменной.\nВесь механизм подсчета ссылок и проверки их корректности реализован на уровне синтаксиса. В рантайме выполняется только контроль идентификатора потока для однопоточных ссылок, а все остальные проверки выполняются во время компиляции.\nУправление памятью и терминология Врчную выделить или освобондить память нельзя\nЛюбой объект - это ссылка на область памяти с данным. Память выделяется и освобожадется автоматически при создании/удалении объектов\nСсылки на объекты, с точки зрения владения, могут быть:\nСильные/Владеющие ссылки (аналог shared_ptr из С++), а фактические, это переменная которая хранит значение объекта. Слабые/Не владеющие ссылки (аналог weak_ptr из С++) - указатели на другим объекты которые перед использованием требуют обязательного захвата (т.е. преобразования в сильную ссылку). Ссылки на объекты, с точки зрения совместного доступа, могут быть:\nЛегкие - ссылки без объекта синхронизации Тяжелые - ссылки с объектом синхронизации совметсного доступа (мьютексом). Переменные - владельцы объектов (в них хранятся ссылки) могут быть двух видов:\nлокальные (контролируемые) - область жизни локальных переменных строго ограничена и определяется правилами синтаксиса языка (аргументы и локальные переменные функций, потоков и т.д.). не контролируемые - глобальные или статические переменные, динамически создаваемые объекты, время жизни которых компилятор не контролирует. Когда локальная переменная удаляется - уменьшается счетчик ссылок, а при достижении нуля - объект освобождается.\nКаждый объект может иметь только одну не контролируемую переменную с сильной ссылкой и произвольное количество любых дргуих типов ссылок в локальных (контролируемых) переменных.\nДля не контролируемых переменных разрешается делать только слабые ссылки, которые перед использованием требуется захватить, например в локальную (контролируемую) переменную.\nУправление временем жизни объекта включает в себя не только управлением памятью, но и при необходимости, создаются механизмы синхронизации доступа к ней. Для этого при определении переменной, описываются возможные типы ссылок, которые разрешено на неё получать:\nбез создания ссылок, т.е. компилятор не даст создать ссылку на данную переменную, а совместный доступ к такой переменой будет не возможен возможно создание легкой ссылки (\"\u0026\"). Компилятору при генерации машинного кода не нужно создавать объект синхронизации доступа к переменной.\nСсылки для полей структур или объектов могут быть только легкими. разрешено создавать ссылки с монопольным доступом (\"\u0026\u0026\"). Компилятор автоматически создает не рекурсивный мьютекс для синхронизации доступа к переменной, т.е. ссылка у этой переменной будет тяжелой. разрешено создавать ссылки с рекурсивным доступом (\"\u0026*\"). Компилятор автоматически создает рекурсивный мьютекс (его можно захватывать несколько раз), а ссылка у этой переменной будет тяжелой. легкая ссылка может быть создана для совместного доступа (\"\u0026?\"), но её захват и синхронизация доступа к ней возможен только при групповом захвате ссылок. Все виды ссылок могут быть константными (\"\u0026^\", “\u0026\u0026^” или “\u0026*^”), т.е. только для чтения (и в случае константных объектов, таким ссылкам мьютекс не потребуется).\nЗахват слабой ссылки может быть индивидуальным или групповым с сохранением результата в локальную (контролируемую) переменную. Такое использование логики захвата объекта на уровне синтаксиса языка гарантирует последующее автоматическое освобождение временной переменной, что равнозначно невозможности создания циклических ссылок.\nПеременная со слабой/не владеющей ссылкой создается только тогда, когда в правой части операции присвоения присутствует любой из операторов получения ссылки (\u0026, \u0026\u0026, \u0026* или \u0026^, \u0026\u0026^, \u0026*^).\nВо всех остальных случаях создается переменная владелец с сильной/владеющей ссылкой (если это разрешено).\nЗахват ссылки и значение переменной Захват ссылки - это преобразование слабой ссылки в сильную с её сохранением в контролируемую переменую с инкрементом счетчика ссылок и возможностью доступа к значению объекта. Это очень похоже на заимствование (Borrowing) в Rust, так как тоже позволяет использовать данные, находящиеся во владении другой переменной, но без перехода владения. Для захвата ссылок используются операторы:\n‘*’ или ‘*( … )’ - автоматический выбор типа доступа (чтения/запись или только чтение) ‘*^’ или ‘*^( … )’ - захват доступа только для чтения ‘**( … )’ - групповой захват ссылок в локальные (контролируемые) переменные () после имени переменной - создание копии значения переменной (глубокое клонирование) ??????????????????????????????????? Упрощенный условный пример:\nref := \u0026 owner; # переменная ref - слабая ссылка на owner ref_ro := \u0026^ owner; # слабая ссылка на owner только для чтения val := * ref; # Автоматический захват только для чтения *ref = val; # Автоматический захват для чтения/записи val := *^ ref; # Захват только для чтения val := *^ ref_ro; val := * ref_ro; # Автоматический захват только для чтения *ref_ro = val; # Ошибка - ссылка только для чтения !!! *^ ref_ro = val; # Ошибка - недопустима конструкция (захват lval - только для чтения) Слабую ссылку можно захватить (превратить в сильную) сохранив результат в локальной переменной, после чего работать с локальной переменной “по значению” без необходимости захватытвать ссылку при каждом обращении к переменной. Значения переменных со слабыми ссылками можно копировать в другие переменные без ограничений. Значение переменной с сильной ссылкой нельзя скопировать в другую переменную или поле объекта, но можно клонировать данные или обменяться значениями “:=:” с другой переменной с сильной ссылкой (swap). Примеры владения:\nowner := \"string\"; other := \"string 2\"; owner = other; # Ошибка - нельзя копировать! owner = other(); # Глубокое клонирование данных owner :=: other; # Обмен значениями (swap) other = _; # Очистка данных объекта Переменную, содержащую ссылку на ссылку создать нельзя, но можно создать ссылочный тип и после этого создать переменную-ссылку на этот тип данных. Упрощенный условный пример:\nvalue := 123; :RefInt := \u0026 Integer; ref_int :RefInt := \u0026 value; ref_ref := \u0026 ref_int; Если переменная владелец разрешает создавать ссылки на объект, тогда при обращении к такой переменой требуется выполнять захват объекта для обеспечения работы механизма совместного доступа. Ссылки и совместный доступ Управление временем жизни переменной включает в себя не только управление памятью, но и механизм синхронизации для монопольного/раздельного доступа к объектам из разных потоков.\nПримеры ссылок:\n\u0026 local := 123; # Разрешено создание ссылок только в текущем потоке \u0026\u0026 thread := 456; # Разрешено создание ссылок с монопольным доступом в любом потоке ref := \u0026 local; # Создание слабой ссылки на local ref2 := \u0026\u0026 local; # Ошибка! многопоточные ссылки не разрешены ref_th := \u0026\u0026 thread; # Создание слабой ссылки на thread # c монопольной блокировкой доступа local += 1; # ОК thread += 1; # Ошибка, требуется захват объекта с разеляемым доступом *local += 1; # ОК, оператор захвата игнорируется *thread += 1; # Захват объекта (как захват слабой ссылки) ref += 1; # Ошибка, требуется захват слабой ссылки ref_th += 1; # Ошибка, требуется захват слабой ссылки *ref += 1; *ref_th += 1; Операторы захвата ссылки и синхронизации доступа к объекту выполняются только для одного действия над переменной. Но захват объекта синхронизации, это относительно медленная операция и выполнять её для каждого действия над переменной не рационально.\nДля того, чтобы однократно захватить объект(ы) синхронизации для выполнения сразу нескольких действий над переменными можно захватить объект в локальную переменую или использовать менеджер контекста.\nПример программы rand():Int32 ::= %rand...; # Создание объекта @( rand():Int32 ); # Предварительное объявление (объект должен быть создан в другом месте) rand():Int32 = ...; usleep(usec:DWord64):None := %usleep...; printf(format:FmtChar, ...):Int32 := %printf...; func(count:Integer, target:String) := { $iter := @iter( 1..$count ); # Итератор для диапазона от 1 до $count @while( @curr($iter) ) { # Цикл, пока итератор валидный $step := @next($iter); # Получить текущий и перейти на следующий элемент итератора printf('Number %d from %s!', $step, $target); usleep( rand() % 1000 ); # Случайная задержка } } thread = :Thread(func, 5, 'thread'); thread.start(); func(5, 'main'); thread.join(); Number 1 from the thread! Number 1 from the main! Number 2 from the thread! Number 2 from the main! Number 3 from the thread! Number 4 from the thread! Number 3 from the main! Number 4 from the main! Number 5 from the main! Number 5 from the thread! Примеры ссылок:\n\u0026 $local := 123; # Разрешено получение легких ссылок \u0026\u0026 $thread := 456; # Доступ к переменной требует захвата тяжелой ссылки $ref := \u0026 $local; # получение слабой ссылки на local $ref2 := \u0026\u0026 $local; # Ошибка! Тяжелой многопоточные ссылки не разрешены $ref_th := \u0026\u0026 $thread; # Получение слабой ссылки на thread # c монопольной блокировкой доступа $local += 1; # ОК (для легких ссылок блокировка объекта не требуется) $thread += 1; # ОК (захват объекта происходит автоматически) $ref += 1; # Ошибка, требуется захват легкой слабой ссылки $ref_th += 1; # Ошибка, требуется захват тяжолой слабой ссылки *$local += 1; # ОК *$thread += 1; # ОК *$ref += 1; # ОК (только захват ссылки, блокировка игнорируется) *$ref_th += 1; # ОК (захват ссылки и блокироваки доступа) Менеджер контекста Операторы захвата ссылки и синхронизации доступа к объекту выполняются только для одного действия над переменной. Но захват объекта синхронизации, это относительно медленная операция и выполнять её для каждого действия над переменной не рационально.\nДля того, чтобы однократно захватить объект(ы) синхронизации для выполнения сразу нескольких действий над переменными используется менеджер контекста.\n","categories":"","description":"","excerpt":"https://habr.com/ru/companies/otus/articles/763810/ …","ref":"/ru/docs/syntax/memory/","tags":"","title":"Управление памятью, ссылки и совместный доступ"},{"body":"Определение функции происходит с помощью операторов создания объектов, имя функции должно соответствовать правилам именования, после которого указываются круглые скобки. В настоящий момент поддерживается создание функций только в качестве статических объектов с однократной инициализацией с помощью оператора ‘::=’;\nТелом функции должен быть блок кода, который располагается в пространстве имен определения этой функции.\nФункции поддерживают аргументы по умолчанию, а сами аргументы указываются как в Python, т.е. вначале идут обязательные, далее идут аргументы со значениями по умолчанию, где его имя отделяется от дефолтного значения знаком равно “=”.\nЕсли функция допускает обработку произвольного количества аргументов, то последним в списке параметров должно быть указано многоточие “…”.\nУ аргументов функции может быть указан допустимый тип данных. Тип возвращаемого значения указывается после закрывающей скобки.\nУ аргументов и у типа возвращаемого значения можно указать сразу несколько допустимых типов данных.\nДля этого их необходимо перечислить через запятую и заключить в угловые скобки, т.е.*\nfunc(arg:\u003c:Int8, :Int16, :Int32\u003e): \u003c:Int8, :Int16, :Int32\u003e ::= {$arg*$arg}; *) Данная функциональность запланирована, но пока не реализована\nДля создания функций используются те же правила синтаксиса и операторы, что и для создания переменных, только после имени функции обязательно должны быть указаны круглые скобки.\nСинтаксис NewLang поддерживает два типа функций: обычные и чистые функции.\nОбычные функции Обычная функция — такие функции являются именно обычными функциями в понимании С/С++. Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д. ?????????????????????????????\nhello(str) ::= { $printf ::= :Pointer('printf(format:FmtChar, ...):Int32'); $printf('call: %s', $str); $str; }; hello('Привет, мир!'); Чистые функции Чистая функция — это тоже обычная функция, только в том смысле, какой в него вкладывает функциональное программирование.\nУ чистой функции отсутствует доступ к контексту и глобальным переменным, поэтому она может обрабатывать только те данные, которые были ей переданы в качестве аргументов.\nСоздание чистой функции происходит с помощью операторов :- или ::-, а сам оператор заимствован из языка Пролог. ???????????????????????????????? Чистые фунции, так же как и обычные, тоже могут быть только статическими объектами, поэтому их нельзя определять с именами лоакльных объектов.\nSum2(arg1, arg2) ::- {$arg1+$arg2;}; # Тоже самое, но если функция с таким именем уже существует, то будет ошибка ??????????????????????????????????????????????????? Sum1(arg1, arg2) :- {$arg1+$arg2;}; # Создать или переопределить простую функцию, которая возвращает сумму аргументов Лямбда функции Лямбда функции, это анонимная функция без указания имени, т.е. вместо имени функции стоит подчерк, и её нельзя вызвать по имени. Но зато лямбда функцию можно передавать как аругмент в другие функции, например при создании итератора.\n_()::={ ... }; Корутины Любую функцию можно определить как корутину (сопрограмма, Coroutine) - функция, выполнение которой можно прерываться явно методами языка программирования. В отличие от прерывания выполнения потока (thread), который реализован средствами ОС и его переключение происходит неявно и в произвольный момент времени.\nfunc() ::= (){ ... }; Переопределение функций Перегрузка функций по типам аргументов NewLang отсуствует, поэтому нельзя создать несколько функций с однинаковым именем, но разными типами аругментов. Но можно переопределить функцию с помощью оператора “[]=”, а в теле новой функции обратиться к первоначальной функции по системному имени “$$”.\n«Требование от субтипов: пусть φ(x) — свойство, доказуемое относительно объектов x типа T. Тогда φ(y) должно быть истинно для объектов y типа S, где S — субтип T»12.\nЭто называется принципом подстановки Лисков. Я не буду вдаваться в подробности, но основной смысл в том, что любое предусловие (для типов, данных или состояния) параметров не может быть строже, чем для супертипа, а любое постусловие не может быть слабее, чем у супертипа13. Эта формулировка связана с методологией контрактного программирования, зародившегося примерно в то же время.\nНовая функция должна иметь аргументы, совместимые с типом аргумента первоначальной функцией.\nfunc(arg:Int8):Int8 ::= ... ; func(arg:Int16):Int16 = ... ; # ОК Int8 -\u003e Int16 func(arg:String):Int16 = ... ; # Ошибка String -\u003e Int16 func(arg:Int16, arg2:Int16):Int16 = ... ; func(arg:Integer, ...):Integer = ... ; # ОК обобщенные тип ","categories":"","description":"","excerpt":"Определение функции происходит с помощью операторов создания объектов, …","ref":"/docs/types/funcs/","tags":["типы данных","функции"],"title":"Функции"},{"body":"Определение функции происходит с помощью операторов создания объектов, имя функции должно соответствовать правилам именования, после которого указываются круглые скобки. В настоящий момент поддерживается создание функций только в качестве статических объектов с однократной инициализацией с помощью оператора ‘::=’;\nТелом функции должен быть блок кода, который располагается в пространстве имен определения этой функции.\nФункции поддерживают аргументы по умолчанию, а сами аргументы указываются как в Python, т.е. вначале идут обязательные, далее идут аргументы со значениями по умолчанию, где его имя отделяется от дефолтного значения знаком равно “=”.\nЕсли функция допускает обработку произвольного количества аргументов, то последним в списке параметров должно быть указано многоточие “…”.\nУ аргументов функции может быть указан допустимый тип данных. Тип возвращаемого значения указывается после закрывающей скобки.\nУ аргументов и у типа возвращаемого значения можно указать сразу несколько допустимых типов данных.\nДля этого их необходимо перечислить через запятую и заключить в угловые скобки, т.е.*\nfunc(arg:\u003c:Int8, :Int16, :Int32\u003e): \u003c:Int8, :Int16, :Int32\u003e ::= {$arg*$arg}; *) Данная функциональность запланирована, но пока не реализована\nДля создания функций используются те же правила синтаксиса и операторы, что и для создания переменных, только после имени функции обязательно должны быть указаны круглые скобки.\nСинтаксис NewLang поддерживает два типа функций: обычные и чистые функции.\nОбычные функции Обычная функция — такие функции являются именно обычными функциями в понимании С/С++. Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д. ?????????????????????????????\nhello(str) ::= { $printf ::= :Pointer('printf(format:FmtChar, ...):Int32'); $printf('call: %s', $str); $str; }; hello('Привет, мир!'); Чистые функции Чистая функция — это тоже обычная функция, только в том смысле, какой в него вкладывает функциональное программирование.\nУ чистой функции отсутствует доступ к контексту и глобальным переменным, поэтому она может обрабатывать только те данные, которые были ей переданы в качестве аргументов.\nСоздание чистой функции происходит с помощью операторов :- или ::-, а сам оператор заимствован из языка Пролог. ???????????????????????????????? Чистые фунции, так же как и обычные, тоже могут быть только статическими объектами, поэтому их нельзя определять с именами лоакльных объектов.\nSum2(arg1, arg2) ::- {$arg1+$arg2;}; # Тоже самое, но если функция с таким именем уже существует, то будет ошибка ??????????????????????????????????????????????????? Sum1(arg1, arg2) :- {$arg1+$arg2;}; # Создать или переопределить простую функцию, которая возвращает сумму аргументов Лямбда функции Лямбда функции, это анонимная функция без указания имени, т.е. вместо имени функции стоит подчерк, и её нельзя вызвать по имени. Но зато лямбда функцию можно передавать как аругмент в другие функции, например при создании итератора.\n_()::={ ... }; Корутины Любую функцию можно определить как корутину (сопрограмма, Coroutine) - функция, выполнение которой можно прерываться явно методами языка программирования. В отличие от прерывания выполнения потока (thread), который реализован средствами ОС и его переключение происходит неявно и в произвольный момент времени.\nfunc() ::= (){ ... }; Переопределение функций Перегрузка функций по типам аргументов NewLang отсуствует, поэтому нельзя создать несколько функций с однинаковым именем, но разными типами аругментов. Но можно переопределить функцию с помощью оператора “[]=”, а в теле новой функции обратиться к первоначальной функции по системному имени “$$”.\n«Требование от субтипов: пусть φ(x) — свойство, доказуемое относительно объектов x типа T. Тогда φ(y) должно быть истинно для объектов y типа S, где S — субтип T»12.\nЭто называется принципом подстановки Лисков. Я не буду вдаваться в подробности, но основной смысл в том, что любое предусловие (для типов, данных или состояния) параметров не может быть строже, чем для супертипа, а любое постусловие не может быть слабее, чем у супертипа13. Эта формулировка связана с методологией контрактного программирования, зародившегося примерно в то же время.\nНовая функция должна иметь аргументы, совместимые с типом аргумента первоначальной функцией.\nfunc(arg:Int8):Int8 ::= ... ; func(arg:Int16):Int16 = ... ; # ОК Int8 -\u003e Int16 func(arg:String):Int16 = ... ; # Ошибка String -\u003e Int16 func(arg:Int16, arg2:Int16):Int16 = ... ; func(arg:Integer, ...):Integer = ... ; # ОК обобщенные тип ","categories":"","description":"","excerpt":"Определение функции происходит с помощью операторов создания объектов, …","ref":"/ru/docs/types/funcs/","tags":["типы данных","функции"],"title":"Функции"},{"body":"Итераторы в NewLang, как и в остальных языках программирования, предназначены для перебора элементов. Но, в отличии от итераторов в С++, итераторы NewLang являются самостоятельными объектами, а не указателями на отдельные элементы объекта-контейнера. Итераторы NewLang поддерживают фильтрацию элементов по имени за счет использования функций обратного вызова.\nДля работы с итераторами используется следующий синтаксис:\n? или ?( текст ) - создание итератора без фильтра или с regex фильтрацией по имени поля ?( func, args… ) - создание итератора с использованием лямбда функции или функции обратного вызова ! или !( количество возвращаемых элементов ) - перебор элементов итератора ?! или !? - получить текущий элемент без перемещение курсора !! - сбросить указатель итератора в начальное состояние (на первый элемент) ?? - создать итератор и сразу его выполнить, возвращая все значения в виде элементов словаря максимально возможного размера. Это своего рода синтаксический сахар для краткой записи последовательности команд ?; !(9223372036854775807);, что удобно использовать при отладке для вывода значений переменных. Для работы с итераторами можно использовании DSL операторы:\niter() - Создать итератор (?) next() - перебор элементов итератора (! или !( количество возвращаемых элементов )) curr() - Получить текущий элемент без перемещение курсора (?! или !?) first() - Сбросить указатель итератора на первый элемент (!!) all() - Создать итератор и сразу его выполнить (??) Примеры создания итераторов с разными фильтрами отбора данных:\niter := dict ? (\"name\"); # Создание итератора для значений с указанным именем iter := dict ? (\"regex.\"); # Создание итератора для полей с префиксом \"regex\" # Чистая функция для фильтрации по значению filter(value) :- { $value \u0026\u0026 $value \u003c 10; }; iter := dict ? (filter); # Создание итератора для значений меньше 10 equal(value, arg) := { $value == arg }; # Обычная функция iter := dict ? (equal, 100); # Создать итератор только для значений 100 Оператор перебора элементов итератора ! возвращает текущий элемент и сдвигает указатель на следующий. Точнее, на количество считанных элементов, так как прочитать элементы из итератора можно не только по одному, а и заданными порциями, например по 10 за один раз, iter ! (10);.\nЕсли указать количество считываемых элементов !(0), то будет возвращен сам элемент, но для значений отличных от нуля будет возвращаться не элемент данных, а словарь с данными, считанными из итератора. Из-за этого операторы ! и !(0) НЕ эквивалентны, т.к. по разному обрабатывают конец данных.\nЛучше всего это показать на примерах для словаря с пятью элементами:\ndict := (1,2,3,4,5,)?; # Создать итератор для словаря dict!; # -\u003e 1 dict!; # -\u003e 2 dict!; # -\u003e 3 dict!; # -\u003e 4 dict!; # -\u003e 5 dict!; # -\u003e будет исключение \"конец итератора\" # Но dict !(0); # -\u003e (1,) dict !(0); # -\u003e (2,) dict !(0); # -\u003e (3,) dict !(0); # -\u003e (4,) dict !(0); # -\u003e (5,) dict !(0); # -\u003e (,) - вернется пустой словарь Так же для чтения итератора можно указывать и отрицательное количество элементов. В этом случае будет возвращаться словарь всегда указанного размера, но элементы в словаре будут присутствовать только в случае чтения реальных данных из итератора:\ndict := (1,2,3,4,5,) ?; # Итератор для словаря с пятью элементами dict !(3); # -\u003e (1,2,3,) dict !(3); # -\u003e (4,5,) dict !(3); # -\u003e (,) # Но dict !(-3); # -\u003e (1,2,3,) dict !(-3); # -\u003e (4,5, :IteratorEnd) dict !(-3); # -\u003e (:IteratorEnd, :IteratorEnd, :IteratorEnd) ","categories":"","description":"","excerpt":"Итераторы в NewLang, как и в остальных языках программирования, …","ref":"/docs/types/iter/","tags":["типы данных","итераторы"],"title":"Итераторы"},{"body":"Итераторы в NewLang, как и в остальных языках программирования, предназначены для перебора элементов. Но, в отличии от итераторов в С++, итераторы NewLang являются самостоятельными объектами, а не указателями на отдельные элементы объекта-контейнера. Итераторы NewLang поддерживают фильтрацию элементов по имени за счет использования функций обратного вызова.\nДля работы с итераторами используется следующий синтаксис:\n? или ?( текст ) - создание итератора без фильтра или с regex фильтрацией по имени поля ?( func, args… ) - создание итератора с использованием лямбда функции или функции обратного вызова ! или !( количество возвращаемых элементов ) - перебор элементов итератора ?! или !? - получить текущий элемент без перемещение курсора !! - сбросить указатель итератора в начальное состояние (на первый элемент) ?? - создать итератор и сразу его выполнить, возвращая все значения в виде элементов словаря максимально возможного размера. Это своего рода синтаксический сахар для краткой записи последовательности команд ?; !(9223372036854775807);, что удобно использовать при отладке для вывода значений переменных. Для работы с итераторами можно использовании DSL операторы:\niter() - Создать итератор (?) next() - перебор элементов итератора (! или !( количество возвращаемых элементов )) curr() - Получить текущий элемент без перемещение курсора (?! или !?) first() - Сбросить указатель итератора на первый элемент (!!) all() - Создать итератор и сразу его выполнить (??) Примеры создания итераторов с разными фильтрами отбора данных:\niter := dict ? (\"name\"); # Создание итератора для значений с указанным именем iter := dict ? (\"regex.\"); # Создание итератора для полей с префиксом \"regex\" # Чистая функция для фильтрации по значению filter(value) :- { $value \u0026\u0026 $value \u003c 10; }; iter := dict ? (filter); # Создание итератора для значений меньше 10 equal(value, arg) := { $value == arg }; # Обычная функция iter := dict ? (equal, 100); # Создать итератор только для значений 100 Оператор перебора элементов итератора ! возвращает текущий элемент и сдвигает указатель на следующий. Точнее, на количество считанных элементов, так как прочитать элементы из итератора можно не только по одному, а и заданными порциями, например по 10 за один раз, iter ! (10);.\nЕсли указать количество считываемых элементов !(0), то будет возвращен сам элемент, но для значений отличных от нуля будет возвращаться не элемент данных, а словарь с данными, считанными из итератора. Из-за этого операторы ! и !(0) НЕ эквивалентны, т.к. по разному обрабатывают конец данных.\nЛучше всего это показать на примерах для словаря с пятью элементами:\ndict := (1,2,3,4,5,)?; # Создать итератор для словаря dict!; # -\u003e 1 dict!; # -\u003e 2 dict!; # -\u003e 3 dict!; # -\u003e 4 dict!; # -\u003e 5 dict!; # -\u003e будет исключение \"конец итератора\" # Но dict !(0); # -\u003e (1,) dict !(0); # -\u003e (2,) dict !(0); # -\u003e (3,) dict !(0); # -\u003e (4,) dict !(0); # -\u003e (5,) dict !(0); # -\u003e (,) - вернется пустой словарь Так же для чтения итератора можно указывать и отрицательное количество элементов. В этом случае будет возвращаться словарь всегда указанного размера, но элементы в словаре будут присутствовать только в случае чтения реальных данных из итератора:\ndict := (1,2,3,4,5,) ?; # Итератор для словаря с пятью элементами dict !(3); # -\u003e (1,2,3,) dict !(3); # -\u003e (4,5,) dict !(3); # -\u003e (,) # Но dict !(-3); # -\u003e (1,2,3,) dict !(-3); # -\u003e (4,5, :IteratorEnd) dict !(-3); # -\u003e (:IteratorEnd, :IteratorEnd, :IteratorEnd) ","categories":"","description":"","excerpt":"Итераторы в NewLang, как и в остальных языках программирования, …","ref":"/ru/docs/types/iter/","tags":["типы данных","итераторы"],"title":"Итераторы"},{"body":"Макросы в NewLang, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем).\nМакросы обработываются во время работы лексера, т.е. перед передачей последовательности лексем в парсер, что позволяет с их помощью изменять даже сам синтаксис языка, например, при реализации собственных диалектов DSL.\nОпределение макросов Определение макросов аналогично определению других объектов и состоит из трех частей \u003cимя макроса\u003e \u003cоператор создания/присвоения\u003e \u003cтело макроса\u003e и завершающая точка с запятой “;”, т.е. применяются обычные операторы ::=, = или := для создания нового или переопределения уже существующего объекта, а имя макроса указывается между двумя символами \"@@\" и может содержать одну или нескольких лексем (терминов).\nВсе макросы относятся к глобальному пространству имен, поэтому первый термин в имени макроса должен быть уникальным, иначе он будет прекрывать имена локальных и глобальных переменных при разрешении имен, если они указаны в коде без квалификаторов.\n??????????????????????? Чистые (гигиеничные) макросы, ::- :-, аргумента и переммые в которых гарантиованно не пересекаются с пространством имен программы?????????????????\nТелом макроса могут быть корректное выражение языка, последовательность лексем (которые заключается в двойные собачки \"@@\", т.е. @@ лексема1 лексема1 @@) или обычная текстовая строка (которую нужно указать между тройными собачками \"@@@\", т.е. @@@ текстовая строка @@@).\nВ имени макроса, кроме первого термина, могут присутствовать один или несколько шаблонов. Шаблон — это термин, который при сопоставлении последовательности лексем с идентификатором макроса может заменяться любым другим одиночным термином (т.е. фактически это сопоставление по образцу/шаблону).\nДля создания термина-шаблона в начале его идентификатора нужно поставить знак доллара (что соответствует квалификатору локальной переменой), т.е. имя макроса @@ FUNC $name @@ будет соответствовать последовательности лексем как FUNC my_func_name, так и FUNC other_name_func.\nДля удаления макроса используется специальный синтаксис: @@@@ name @@@@; или @@@@ два термина @@@@;, т.е. необходимо указать идентификатор макроса между четырмя символами \"@@@@\".\n# Тело макроса из текстовой строки (как в препроцессоре С/С++) @@macro_str@@ := @@@ строка - тело макроса @@@; # Строка для лексера # Удаления макроса @macro_str @@@@ macro_str @@@@; Аргументы макросов и их раскрытие Макросы можно определять как с аргументами (параметрами в скобках), так и без них. Если макрос был определен с аргументами, то их проверка будет выполнятся макропроцессором при определении и раскрытии макроса. Если макрос был определен без аргументов, то их наличие макропроцессором игнорируется.\nТак как макропроцессор считает макросы с аргументами и без оных идентичными, то нельзя создать два макроса с одинаковыми именами, один из которых будет с аргументами (скобками), а другой без них.\nПоэтому, если требуется использовать макрос в двух разных вариантах (с аргументами и без них), тогда следует определять макрос без аргументов и в этом случае контроль параметров будет производить компилятор.\n@@macro@@ := term; # Макрос без аргументов macro(args); # ОК -\u003e term(args); macro; # ОК -\u003e term; # Но @@call()@@ := term(); call(); # ОК -\u003e term(); call; # Ошибка (@call определен с аргументами) Если при определении макроса указаны аргументы, то место для их вставки в теле макроса записывается как имя локальной переменой, перед которой добавлен символ \"@\", т.е. @$arg.\nПроизвольное количество аргументов у макроса отмечается троеточием \"…\", а место для их вставки отмечается в теле макроса лексемой \"@$…\".\nМесто для вставки числа реально переданных аргументов отмечается лексемой \"@$#\". Если требуется вставить переданные аргументы в виде элементов словаря, то место для вставки отмечается лексемой \"@$*\".\nПо аналогии с препроцессором С/С++, для соединения двух лексем в одну, в теле макроса используется оператор \"@##\", а для преобразование лексемы в текстову строку применяется операторы @#, @#\" или @#’, например, @@macro($arg)@@ := @@ func_ @## @$arg( @#\" arg ) @;, тогда вызов macro(name); будет преобразован в func_name (\"name\");\nОграничения макропроцессора в текущей версии На текущий момент макросы реализованы в минимальном объеме для самых простых сценариев использования:\nDSL для keyword based syntax (if, else, return, match, while и т.д.) - (1 термин с произвольными аргументами и без) - требуется сейчас !!! Парсер при обработке макросов может анализировать информацию о типах данных, если она указана. Но на текущий момент типы данных в макросах никак не обрабатываются и это одна из обязательных фич, которая будет реализована в будущем.\nОпределения (func, class) - (несколько терминов с аргументами и без аргументов) - Реализация ООП и импорт С++ классов Модификации при определениях (override) - (несколько терминов и шаблоны с аргументами и без аргументов) - Реализация ООП и импорт С++ классов МАКРОСЫ БЕЗ АРГУМЕНТОВ ИЛИ ВСЕ АРГУМЕНТЫ СРАЗУ !!!!! анализа аргументов или их типов не производится !!! Lambda @@ lambda $name(…) @@ ::= @@ @$name( @$… ) ::= ( _( @$… ) ::= @PRAGMA_FINALIZE( @), {, {+, {-, {* ) @@\nПримеры использования макросов # Обычные макросы (тело макроса корректное выражение) @@macro@@ := replace(); @@macro2(arg)@@ := { call(@$arg); call()}; # Тело макросов из последовательности лексем @@if(...)@@ := @@ [ \\$if(*) ]--\u003e @@; # Выражение может быть не полным @@elif(...)@@ := @@ ,[ \\$elif(*) ]--\u003e @@; @@else@@ := @@ ,[_]--\u003e @@; # Запись условного оператора с использованием # определенных выше макросов if( condition ){ ... } elif( condition2 ) { ... } else { ... }; Зачем нужна трансформация синтаксиса? Нативная поддержка других языков нужна чтобы не переписывать легаси код на этих языках.\nЧтобы можно было использовать существующие исходники как собственные требуется настройка работы препроцессора и лексера под конкретный язык программирования (описание DSL). Для С/С++ потребуется выделять лексером комментарии из-за пересечения синтаксиса (которые сейчас игнорируются). Для Python требуется выделять лексером отступы (которые сейчас тоже игнорируются), причем потребуется реализация не только синтаксиса, но и зависимых пакетов с последующая трансляцией этого кода в С++, что в настоящий момент делать не целесообразно (cython ???).\nНо так как возможность трансформации кода с других языков программирования принципиальная возможна, стоит над этим думать только после полноценного релиза NewLang и его перехода в прод.\nДля реализации DSL требуется передача команд в парсер для управления его работой (по аналогии с командой #pragma) Но так как обработка таких команд должна происходить в лексере до передачи данных в парсер (анализатор), то команды для макропроцессора должны быть в максимально простом виде и состоять из элементов, которые лексер может самостоятельно идентифицировать, т.е. термины, строки и цифры (без выражений и именованных аргументов).\nПосле обработки такой команды она анализируется макропроцессором и удаляется из потока лексем, т.е. в парсер (анализатор) не передается. Но в случае ошибки с синтаксисе, данные команды нужно уметь однозначно идентифировать и самый простой способ, комбинация признака макроса и системного имени, т.е. что-то вроде\n@__PRAGMA_DIAG__(push) @__PRAGMA_DIAG__(ignored, \"-Wundef\") @__PRAGMA_DIAG__(warning, \"-Wformat\") @__PRAGMA_DIAG__(error \"-Wuninitialized\") @__PRAGMA_DIAG__(pop) #pragma message \"Compiling \" __FILE__ \"...\" @__PRAGMA_MESSAGE__(\"Compiling \", __FILE__, \"...\") #pragma error \"Error \" __FILE__ \"...\" @__PRAGMA_ERROR__(\"Error \", __FILE__, \"...\") #define DO_PRAGMA(x) _Pragma (#x) #define TODO(x) DO_PRAGMA(message (\"TODO - \" #x)) @@TODO( ... )@@ := @__PRAGMA_MESSAGE__(\"TODO - \", @*) @TODO(Remember to fix this) # note: TODO - Remember to fix this \\\\.__lexer__ignore_space__ = 1; \\\\.__lexer__ignore_indent__ = 1; \\\\.__lexer__ignore_comment__ = 1; \\\\.__lexer__ignore_crlf__ = 1; Таким образом можно трансформировать условный оператор на питоне в синтаксис NewLang следующим макросом:\n#pragma clang attribute push #pragma clang diagnostic ignored \"-Wundef\" #pragma clang diagnostic ignored \"-Wunused-variable\" #elif __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored \"-Wuninitialized\" #pragma GCC diagnostic ignored \"-Wall\" #pragma GCC diagnostic ignored \"-Wextra\" @pragma warning(pop) @@ pragma warning(...) @@ := __PRAGMA_TERM_DIAG_WARNING__(); @__PRAGMA_DIAG__(warning, pop); Обработка терминов в макропроцессоре в максимально простом виде. Агрументы только термины, строки и цифры без вложенных выражений и именованных аргументов, т.е. только элементы, которые может самостоятельно идентифицировать лексер. @warning(\"--\") @@ if ... : @@ := @@ [ @$* ]-\u003e __TERM_BLOCK_INDENT__(\"{\", force_semicolon=1) @@ if __name__ == \"__main__\": run1() run2() [ __name__ == \"__main__\" ]-\u003e { run1(); run2(); }; Ключ –parser-syntax-only только текстовый парсинг исходного кода без загрузки модулей, раскрытия макросов и проверки имен.\nКлюч –parser-no-macros - без раскрытия макросов Ключ –parser-no-module - без загрузки модулей (и мокросов, если они в них определяются) Ключ –parser-no-check-prototype - без проверки имен при обращении\nprototype @PRAGMA_PROTOTYPE(define) @PRAGMA_PROTOTYPE(implement)\n$$\n\\$ - корень системы (система)\n$ - текущий модуль\nМакросы для конвертора проверки в Python if name == “main”: @@ name @@ ::= @@ $. @PRAGMA_NO_MACRO() name @@ @@ if $… @: @@ ::= @@ [ @$… ] –\u003e @@\n@if( $.name == “main” ) {\n}\n\\каталог\\модуль() - статический импорт модуля \\(“каталог\\модуль”)() - динамический импорт модуля\nprintf := :Pointer(‘printf(format:FmtChar, …):Int32’); printf := %printf(format:FmtChar, …):Int32;\nРегистрация прототипа нативной функции @prototype %puts(format:StrChar):Int32;\nИмпорт нативной функции с предварительной проверкой её наличия во время компиляции (статическая линковка) puts2(format:StrChar):Int32 := %puts(format:StrChar):Int32;\nИмпорт нативной функции по её прототипу во время выполнения (динамическая линковка) puts3(format:StrChar):Int32 := :Pointer(‘puts(format:StrChar):Int32’);\n%puts(‘Тест вывода строки’); # Линковка с нативной функцией во время компиляции и непосредственный вызов с оптимизацией передачи параметров puts2(‘Тест 2 вывода строки’); # Линковка с нативной функцией во время компиляции puts3(‘Тест 3 вывода строки’); # Линковка с нативной функцией во время выполнения при первом вызове puts3\nПарсинг исходного текста без раскрытия макросов и загрузки модулей Парсинг исходного текста с раскрытием макросов (требуется загрузка модулей для зависимых и переопределяемых макросов) Загружатся модули могут как в виде исходников (которые требуется парсить и компилировть/выполнять) или в виде бинарников (в них должны быть список макросов, типов и имена объектов) После парсинга получается список имен макросов, типов и объектов (TermPtr) После выполнения модуля - список имен заполняется реальными объектами (ObjPtr). Компиляция файла Парсинг исходника для построения AST (без анализа имен, связей, загрузки модулей и пр. только исходые тексты с раскрытием макросов Систематизация реализации макросов последовательность лексем MACRO_SEQ мужду @@ @@ сохраняется в m_block, так как фрагменты блоков не могут быть идентификаторами\nРазбор макросов происходит в лексере. Определением макроса всегда является целая строка, которая заканчивается точкой с запятой, а идентификатором макроса всегда выступает последовательность лексем:\n@@ id @@ := macro; @@ id @@ := @@ @@; @@ id @@ := @@@ @@@; Хранилищем текущих максросов является объект класса MacroBuffer. Последовательность лексем идентификатора (id) макроса должна сохраняется в отдельном поле термина и однозначно его идентифицирует. Первый термин в идентификаторе хранится как ключ hashmap, а дальше происходит поиск полным перебором. Этапы работы с макросами\nВходные термины из лексера получаются вызовом GetNextToken, внутри которой и происходит раскрытие макросов. Внутренний буфер заполняется до окончания строки (выражения), т.е. до символа ‘;’ или , после чего производится поиск макросов в объекте MacroBuffer для текущей последовательности лексем в буфере.\nЕсли макрос найден, то соответствющая ему последоваетльность заменяется на тело макроса и происходит переход на повторный анализ входного буфера.\nЕсли макрос не найден, то данные передаются в парсер для дальнейшего синтаксическго анализа.\nДля этого во входном потоке лексем (parser.y) во время оператората создания/присвоения вызывается функция проверки на макрос. MacroBuffer::CheckMacroAndConvertDel($$), и после этого выходному значению присваивается результат выполнения driver.MacroEval($$), и в дальнейшем этот макрос никак не обработывается.\nСоздание макросов, проверка на дубликаты и логические ошибки в определении происходит путем обращения к методам объекта MacroBuffer.\n/*\nМакросы хрянтся как фрагменты AST в виде объектов типа Term, так как создаются после обработки парсером по правилам стандратной грамматики. Но анализ входных данных на предмет раскрытия макросов проиходит из потока (последовательности) лексем, т.е. ДО обработки парсером, так как при раскрытии макросов может меняться грамматика выражений. Функция \\ref CompareMacro сравнивает входной буфер (последовательность лексем) на предмет возможного соответствия одному конкретному макросу. Сравниваются только ключевые словам без учета аргументов в скобках, но само наличие аргументов проверяется ?????????????????? Проблема: К функции можно обратится с целью её вызова (указав после имени скобки), так и по имени без скобок (например для получения ссылки на объект). Так и к переменной можно обратиться только по имени, так и указав скобки после имени как к функции (при копировании объекта). Сделать один макрос под оба сценария (со скобками и без скобок) не получится, так как непонятно, что делать с аргументами при раскрытии тела макроса, когда они не указаны. Но может быть следует переименовывать только одно имя без учета скобок, например, оставив такую возможность только для одиночных макросов. \\name -\u003e name или name (…), hash: name но \\name(…) -\u003e name(…), а name - ошибка !!!! hash: name Или все же следует различать макросы со скобками и без скобок как два разных объекта??? \\name := name2; и \\name(…) := name2(…); будут разными объектами Или добавить макросы-алиасы без аргументов только для переименования отдельных терминов? \\alias :- name2; но как их отличать от обычных макросов в операции удаления? Или вообще не нужно отличать и оставить только один варинат (либо макрос, либо алиас) Тода вопрос со скобками закрывается сам собой, алиасы всегда без скобок, макросы со скбками или без скобок, но должно быть полное соответствие. @ name name2 @ -\u003e name name2, но name name2(…) - ошибка!!! (hash: name,name2) @ name name2(…) @ -\u003e name name2(…), но name name2 - ошибка !!!! (hash: name,name2) @ name name2… @ -\u003e name name2…, но name name2 - ошибка !!!! ( hash: name,name2 ) @ name $tmpl… name3@ -\u003e name $tmpl… name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 ) Но! @ name name2 @ ::- -\u003e name name2 - ок, но name name2(…) - ок @ name $tmpl name3@ ::- -\u003e name $tmpl… name3 - ок, name $tmpl(…) name3[…] - ок Для последовательности лексем требуется полное соответствие с учетом скобок ??? и может ли быть несколько скобок одного типа (несколько крыглях, или несколько квардратных???? \u003cМожет быть несколько скобок одного типа, например, при указании типа у аргументов или типа возвращаемого значения.\u003e @ name name2 @ -\u003e name name2, но name name2(…) - ошибка!!! (hash: name,name2) @ name name2(…) @ -\u003e name name2(…), но name name2 - ошибка !!!! (hash: name,name2) @ name name2… @ -\u003e name name2…, но name name2 - ошибка !!!! ( hash: name,name2 ) @ name $tmpl… name3@ -\u003e name $tmpl… name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 ) Проблема скобок возникает из-за сценария замены одного термина на другой, который есть в препроцессоре С/С++, но отсутствует при реализации с использованием шаблонов. */\nМакросы используются и для превращеня исходного кода NewLang в более привычный синтаксис на основе ключевых слов, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода.\nНапример:.\n@@if(...)@@ ::= @@ [ \\$* ]--\u003e @@; @@while(...)@@ ::= @@ [\\$*] \u003c-\u003e @@; @@return $arg@@::= @@ -- \\$arg -- @@; @@true@@ ::= 1; Тогда цикл до 5:\ncount:=1; [ 1 ] \u003c-\u003e { [count\u003e5] --\u003e { -- 42 --; }; count+=1; }; будет выглядеть более привычно\ncount:=1; while( true ) { if(count\u003e5) { return 42; }; count+=1; }; Идеи на будущее Символьное программирование Символьное программирование, часто называемое декларативным программированием, представляет собой парадигму программирования, которая использует математическую логику, отношения и символы для представления знаний и помощи в решении проблем. Вместо того, чтобы сосредотачиваться на описании последовательности операций, необходимых для выполнения вычислений, как в императивном программировании, символическое программирование делает упор на выражении отношений и ограничений между структурами данных, уделяя особое внимание «что», а не «как».\nВ контексте парадигм программирования символическое программирование часто противопоставляется процедурному или императивному программированию, где программы определяют пошаговые процедуры для достижения своих целей. В то время как императивное программирование фокусируется на описании потока управления с использованием таких конструкций, как циклы и условные выражения, для управления выполнением, символическое программирование сосредоточено на выражении фактов о проблеме и позволяет выполнению естественным образом выводить последующие последствия из предоставленной информации.\nОдним из основных преимуществ символьного программирования является его способность обеспечивать более высокий уровень абстракции, что упрощает анализ кода и снижает вероятность ошибок. Непосредственно выражая отношения и ограничения, символическое программирование позволяет разработчикам сосредоточиться на моделировании и спецификации проблем, позволяя базовой системе управлять реализацией и выполнением алгоритмов.\nСуществует несколько языков программирования и сред, использующих парадигму символьного программирования, например Prolog, Lisp и Haskell. Например, Пролог — это язык логического программирования, который позволяет разработчикам выражать взаимосвязи и факты о проблемных областях, в то время как выполнение автоматически обосновывает и извлекает новые факты на основе исходной информации. В том же духе Лисп, функциональный язык программирования, использует символьные вычисления для манипулирования структурами данных и выполнения сложных операций над ними, используя краткий и математически обоснованный синтаксис. Haskell, еще один функциональный язык программирования, использует строгую типизацию и ленивые вычисления, чтобы обеспечить символическое рассуждение и облегчить эффективное создание программ.\nСимвольное программирование может быть полезным в широком спектре проблемных областей, включая искусственный интеллект, экспертные системы, программирование логики ограничений и символьную математику, среди других. Более высокий уровень абстракции, обеспечиваемый декларативными языками программирования, облегчает разработку сложных систем, сводя к минимуму вероятность ошибки и улучшая удобство обслуживания. В частности, использование символьного программирования в искусственном интеллекте позволяет разработчикам создавать системы представления знаний и механизмы рассуждения, которые можно применять для обработки естественного языка, машинного обучения и автоматического доказательства теорем.\nРазличие между символьным программированием и препроцессором\nЗадача препроцессора - раскрыть(расширить) макрос, тогда как при символьном программировании нужно сокращать (сворачивать) выражения Препроцессор обрабатывает последовательности лексем (плоские данные), тогда как символьное программирование оперирует выражениями (деревом лексем) Макрос у препроцессора идентифицируется первым термином, и если макрос не может быть раскрыт, то возникает ошибка. В символьном программировани требуется точное соответствие всего выражения и только в этом случае производится сокращение выражения. Предпосылки для реализации символьного программирования Компилятор - интерепретатор с REPL и обработка AST как во время компиляции, так и во время выполнения. Необходимо добавить конструкции для определения правил символьного программрования (чистые функции?) Необходимо добавить конструкцию для вычисления выражений в символьном программировании.\nWolfram https://habr.com/articles/772984/\ndiffRules = { Sin[x] -\u003e Cos[x], Cos[x] -\u003e -Sin[x], x^2 -\u003e 2*x, x -\u003e 1, Log[x] -\u003e 1/x }; diffRules := ( Sin(x) @-\u003e Cos(x), Cos(x) @-\u003e -Sin(x), x^2 @-\u003e 2*x, x @-\u003e 1, Log(x) @-\u003e 1\\x, ); expr @-\u003e Sin(x) - x^2 + Log(x); # И применим к нему правила дифференцирования #expr /. diffRules #(* 1/x - 2 x + Cos[x] *) sym := SymEval(expr, diffRules); res := Eval(sym, x=0.123); expr = a^2 + 3 * b^3 - c^4 + 2 * x^2 - x + 4*c + 3 И я хочу это выражение линеаризовать, т.е. отбросить все степени выше первой. Я могу сделать это напрямую, как в примерах выше: expr /. { a^2 -\u003e 0, b^3 -\u003e 0, c^4 -\u003e 0, x^2 -\u003e 0 } (* 3 + 4 c - x *) Но это слишком неудобно. Что если я не знаю ни точную степень, ни имя переменной? Как просто указать, что нужно заменить все места, где встречается возведение в степень на ноль? Это можно сделать при помощи шаблонов вот так: expr /. Power[_, _] -\u003e 0 (* 3 + 4 c - x *) Либо вот так: expr /. _ ^ _ -\u003e 0 (* 3 + 4 c - x *) :diffRules() := { {@ Sin(x) @} ::- {@ Cos(x) @}; Cos(x) @-\u003e -Sin(x), x^2 @-\u003e 2*x, x @-\u003e 1, Log(x) @-\u003e 1\\x, }; expr @-\u003e Sin(x) - x^2 + Log(x); # И применим к нему правила дифференцирования #expr /. diffRules #(* 1/x - 2 x + Cos[x] *) sym := SymEval(expr, diffRules); res := Eval(sym, x=0.123); ","categories":"","description":"","excerpt":"Макросы в NewLang, это один или несколько последовательных терминов, …","ref":"/docs/syntax/macros/","tags":"","title":"Макросы"},{"body":"Макросы в NewLang, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем).\nМакросы обработываются во время работы лексера, т.е. перед передачей последовательности лексем в парсер, что позволяет с помощью маросов изменять фрагменты синтаксиса языка, например, при реализации собственных диалектов DSL.\nОпределение макросов Определение макросов аналогично определению других объектов и состоит из трех частей \u003cимя макроса\u003e \u003cоператор создания/присвоения\u003e \u003cтело макроса\u003e и завершающая точка с запятой “;”, т.е. применяются обычные операторы ::=(::-), = или :=(:-) для создания нового или переопределения уже существующего объекта, а имя макроса указывается между двумя символами \"@@\" и может содержать одну или нескольких лексем (терминов).\nВсе макросы относятся к глобальному пространству имен, поэтому первый термин в имени макроса должен быть уникальным, иначе он будет прекрывать локальные и глобальные переменные при разрешении имен, если они записаны в тексте программы без квалификаторов (сигилов).\nС помощью операторов ::- и :- создаются чистые (гигиеничные) макросы, аргументы и переменные в которых гарантированно не пересекаются с пространством имен программы.\nТелом макроса могут быть корректное выражение языка, последовательность лексем (которые заключается в двойные собачки \"@@\", т.е. @@ лексема1 лексема1 @@) или обычная текстовая строка (которую нужно указать между тройными собачками \"@@@\", т.е. @@@ текстовая строка @@@).\nВ имени макроса после первого термина могут присутствовать один или несколько шаблонов. Шаблон — это термин, который при сопоставлении последовательности лексем с идентификатором макроса может заменяться любым другим одиночным термином (т.е. фактически это сопоставление по образцу/шаблону).\nДля создания термина-шаблона в начале его идентификатора нужно поставить знак доллара (что соответствует квалификатору локальной переменой), т.е. имя макроса @@ FUNC $name @@ будет соответствовать последовательности лексем как FUNC my_func_name, так и FUNC other_name_func.\nДля удаления макроса используется специальный синтаксис: @@@@ name @@@@; или @@@@ два термина @@@@;, т.е. необходимо указать идентификатор макроса между четырмя символами \"@@@@\".\n# Тело макроса из текстовой строки (как в препроцессоре С/С++) @@macro_str@@ := @@@ строка - тело макроса @@@; # Строка для лексера # Удаления макроса @macro_str @@@@ macro_str @@@@; Аргументы макросов и их раскрытие Макросы можно определять как с аргументами (параметрами в скобках), так и без них. Если макрос был определен с аргументами, то их проверка будет выполнятся макропроцессором при определении и раскрытии макроса. Если макрос был определен без аргументов, то их наличие макропроцессором игнорируется.\nМакропроцессор считает макросы с аргументами и без оных идентичными, то нельзя создать два макроса с одинаковыми именами, один из которых будет с аргументами (скобками), а другой без них.\nПоэтому, если требуется использовать макрос в двух разных вариантах (с аргументами и без оных), следует определять макрос без аргументов и в этом случае контроль параметров будет выполнятся компилятором.\n@@macro@@ := term; # Макрос без аргументов macro(args); # ОК -\u003e term(args); macro; # ОК -\u003e term; # Но @@call()@@ := term(); call(); # ОК -\u003e term(); call; # Ошибка (@call определен с аргументами) Если при определении макроса указаны аргументы, то место для их вставки в теле макроса записывается как имя локальной переменой, перед которой добавлен символ \"@\", т.е. @$arg.\nМесто для вставки числа реально переданных аргументов отмечается лексемой \"@$#\". Если требуется вставить переданные аргументы в виде словаря, то место для вставки отмечается лексемой \"@$*\".\nЕсли макрос принимае произвольное количество аргументов (аргуметы макроса завершает многоточие), то место их вставки в тело макроса отмечается лексемой \"@$…\".\nПо аналогии с препроцессором С/С++, для соединения двух лексем в одну, в теле макроса используется оператор \"@##\", а для преобразование лексемы в текстову строку применяется операторы @#, @#\" или @#’, например, @@macro($arg)@@ := @@ func_ @## @$arg( @#\" arg ) @;, тогда вызов macro(name); будет преобразован в func_name (\"name\");\nОграничения макропроцессора в текущей версии На текущий момент макросы реализованы в минимальном объеме для самых простых сценариев использования:\nDSL для keyword based syntax (if, else, return, match, while и т.д.) - (1 термин с произвольными аргументами и без) - требуется сейчас !!! Парсер при обработке макросов может анализировать информацию о типах данных, если она указана. Но на текущий момент типы данных в макросах никак не обрабатываются и это одна из обязательных фич, которая будет реализована в будущем.\nОпределения (func, class) - (несколько терминов с аргументами и без аргументов) - Реализация ООП и импорт С++ классов Модификации при определениях (override) - (несколько терминов и шаблоны с аргументами и без аргументов) - Реализация ООП и импорт С++ классов МАКРОСЫ БЕЗ АРГУМЕНТОВ ИЛИ ВСЕ АРГУМЕНТЫ СРАЗУ !!!!! анализа аргументов или их типов не производится !!! Lambda @@ lambda $name(…) @@ ::= @@ @$name( @$… ) ::= ( _( @$… ) ::= @PRAGMA_FINALIZE( @), {, {+, {-, {* ) @@\nПримеры использования макросов # Обычные макросы (тело макроса корректное выражение) @@macro@@ := replace(); @@macro2(arg)@@ := { call(@$arg); call()}; # Тело макросов из последовательности лексем @@if(...)@@ := @@ [ \\$if(*) ]--\u003e @@; # Выражение может быть не полным @@elif(...)@@ := @@ ,[ \\$elif(*) ]--\u003e @@; @@else@@ := @@ ,[_]--\u003e @@; # Запись условного оператора с использованием # определенных выше макросов if( condition ){ ... } elif( condition2 ) { ... } else { ... }; Зачем нужна трансформация синтаксиса? Нативная поддержка других языков нужна чтобы не переписывать легаси код на этих языках.\nЧтобы можно было использовать существующие исходники как собственные требуется настройка работы препроцессора и лексера под конкретный язык программирования (описание DSL). Для С/С++ потребуется выделять лексером комментарии из-за пересечения синтаксиса (которые сейчас игнорируются). Для Python требуется выделять лексером отступы (которые сейчас тоже игнорируются), причем потребуется реализация не только синтаксиса, но и зависимых пакетов с последующая трансляцией этого кода в С++, что в настоящий момент делать не целесообразно (cython ???).\nНо так как возможность трансформации кода с других языков программирования принципиальная возможна, стоит над этим думать только после полноценного релиза NewLang и его перехода в прод.\nДля реализации DSL требуется передача команд в парсер для управления его работой (по аналогии с командой #pragma) Но так как обработка таких команд должна происходить в лексере до передачи данных в парсер (анализатор), то команды для макропроцессора должны быть в максимально простом виде и состоять из элементов, которые лексер может самостоятельно идентифицировать, т.е. термины, строки и цифры (без выражений и именованных аргументов).\nПосле обработки такой команды она анализируется макропроцессором и удаляется из потока лексем, т.е. в парсер (анализатор) не передается. Но в случае ошибки с синтаксисе, данные команды нужно уметь однозначно идентифировать и самый простой способ, комбинация признака макроса и системного имени, т.е. что-то вроде\n@__PRAGMA_DIAG__(push) @__PRAGMA_DIAG__(ignored, \"-Wundef\") @__PRAGMA_DIAG__(warning, \"-Wformat\") @__PRAGMA_DIAG__(error \"-Wuninitialized\") @__PRAGMA_DIAG__(pop) #pragma message \"Compiling \" __FILE__ \"...\" @__PRAGMA_MESSAGE__(\"Compiling \", __FILE__, \"...\") #pragma error \"Error \" __FILE__ \"...\" @__PRAGMA_ERROR__(\"Error \", __FILE__, \"...\") #define DO_PRAGMA(x) _Pragma (#x) #define TODO(x) DO_PRAGMA(message (\"TODO - \" #x)) @@TODO( ... )@@ := @__PRAGMA_MESSAGE__(\"TODO - \", @*) @TODO(Remember to fix this) # note: TODO - Remember to fix this \\\\.__lexer__ignore_space__ = 1; \\\\.__lexer__ignore_indent__ = 1; \\\\.__lexer__ignore_comment__ = 1; \\\\.__lexer__ignore_crlf__ = 1; Таким образом можно трансформировать условный оператор на питоне в синтаксис NewLang следующим макросом:\n#pragma clang attribute push #pragma clang diagnostic ignored \"-Wundef\" #pragma clang diagnostic ignored \"-Wunused-variable\" #elif __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored \"-Wuninitialized\" #pragma GCC diagnostic ignored \"-Wall\" #pragma GCC diagnostic ignored \"-Wextra\" @pragma warning(pop) @@ pragma warning(...) @@ := __PRAGMA_TERM_DIAG_WARNING__(); @__PRAGMA_DIAG__(warning, pop); Обработка терминов в макропроцессоре в максимально простом виде. Агрументы только термины, строки и цифры без вложенных выражений и именованных аргументов, т.е. только элементы, которые может самостоятельно идентифицировать лексер. @warning(\"--\") @@ if ... : @@ := @@ [ @$* ]-\u003e __TERM_BLOCK_INDENT__(\"{\", force_semicolon=1) @@ if __name__ == \"__main__\": run1() run2() [ __name__ == \"__main__\" ]-\u003e { run1(); run2(); }; Ключ –parser-syntax-only только текстовый парсинг исходного кода без загрузки модулей, раскрытия макросов и проверки имен.\nКлюч –parser-no-macros - без раскрытия макросов Ключ –parser-no-module - без загрузки модулей (и мокросов, если они в них определяются) Ключ –parser-no-check-prototype - без проверки имен при обращении\nprototype @PRAGMA_PROTOTYPE(define) @PRAGMA_PROTOTYPE(implement)\n$$\n\\$ - корень системы (система)\n$ - текущий модуль\nМакросы для конвертора проверки в Python if name == “main”: @@ name @@ ::= @@ $. @PRAGMA_NO_MACRO() name @@ @@ if $… @: @@ ::= @@ [ @$… ] –\u003e @@\n@if( $.name == “main” ) {\n}\n\\каталог\\модуль() - статический импорт модуля \\(“каталог\\модуль”)() - динамический импорт модуля\nprintf := :Pointer(‘printf(format:FmtChar, …):Int32’); printf := %printf(format:FmtChar, …):Int32;\nРегистрация прототипа нативной функции @prototype %puts(format:StrChar):Int32;\nИмпорт нативной функции с предварительной проверкой её наличия во время компиляции (статическая линковка) puts2(format:StrChar):Int32 := %puts(format:StrChar):Int32;\nИмпорт нативной функции по её прототипу во время выполнения (динамическая линковка) puts3(format:StrChar):Int32 := :Pointer(‘puts(format:StrChar):Int32’);\n%puts(‘Тест вывода строки’); # Линковка с нативной функцией во время компиляции и непосредственный вызов с оптимизацией передачи параметров puts2(‘Тест 2 вывода строки’); # Линковка с нативной функцией во время компиляции puts3(‘Тест 3 вывода строки’); # Линковка с нативной функцией во время выполнения при первом вызове puts3\nПарсинг исходного текста без раскрытия макросов и загрузки модулей Парсинг исходного текста с раскрытием макросов (требуется загрузка модулей для зависимых и переопределяемых макросов) Загружатся модули могут как в виде исходников (которые требуется парсить и компилировть/выполнять) или в виде бинарников (в них должны быть список макросов, типов и имена объектов) После парсинга получается список имен макросов, типов и объектов (TermPtr) После выполнения модуля - список имен заполняется реальными объектами (ObjPtr). Компиляция файла Парсинг исходника для построения AST (без анализа имен, связей, загрузки модулей и пр. только исходые тексты с раскрытием макросов Систематизация реализации макросов последовательность лексем MACRO_SEQ мужду @@ @@ сохраняется в m_block, так как фрагменты блоков не могут быть идентификаторами\nРазбор макросов происходит в лексере. Определением макроса всегда является целая строка, которая заканчивается точкой с запятой, а идентификатором макроса всегда выступает последовательность лексем:\n@@ id @@ := macro; @@ id @@ := @@ @@; @@ id @@ := @@@ @@@; Хранилищем текущих максросов является объект класса MacroBuffer. Последовательность лексем идентификатора (id) макроса должна сохраняется в отдельном поле термина и однозначно его идентифицирует. Первый термин в идентификаторе хранится как ключ hashmap, а дальше происходит поиск полным перебором. Этапы работы с макросами\nВходные термины из лексера получаются вызовом GetNextToken, внутри которой и происходит раскрытие макросов. Внутренний буфер заполняется до окончания строки (выражения), т.е. до символа ‘;’ или , после чего производится поиск макросов в объекте MacroBuffer для текущей последовательности лексем в буфере.\nЕсли макрос найден, то соответствющая ему последоваетльность заменяется на тело макроса и происходит переход на повторный анализ входного буфера.\nЕсли макрос не найден, то данные передаются в парсер для дальнейшего синтаксическго анализа.\nДля этого во входном потоке лексем (parser.y) во время оператората создания/присвоения вызывается функция проверки на макрос. MacroBuffer::CheckMacroAndConvertDel($$), и после этого выходному значению присваивается результат выполнения driver.MacroEval($$), и в дальнейшем этот макрос никак не обработывается.\nСоздание макросов, проверка на дубликаты и логические ошибки в определении происходит путем обращения к методам объекта MacroBuffer.\n/*\nМакросы хрянтся как фрагменты AST в виде объектов типа Term, так как создаются после обработки парсером по правилам стандратной грамматики. Но анализ входных данных на предмет раскрытия макросов проиходит из потока (последовательности) лексем, т.е. ДО обработки парсером, так как при раскрытии макросов может меняться грамматика выражений. Функция \\ref CompareMacro сравнивает входной буфер (последовательность лексем) на предмет возможного соответствия одному конкретному макросу. Сравниваются только ключевые словам без учета аргументов в скобках, но само наличие аргументов проверяется ?????????????????? Проблема: К функции можно обратится с целью её вызова (указав после имени скобки), так и по имени без скобок (например для получения ссылки на объект). Так и к переменной можно обратиться только по имени, так и указав скобки после имени как к функции (при копировании объекта). Сделать один макрос под оба сценария (со скобками и без скобок) не получится, так как непонятно, что делать с аргументами при раскрытии тела макроса, когда они не указаны. Но может быть следует переименовывать только одно имя без учета скобок, например, оставив такую возможность только для одиночных макросов. \\name -\u003e name или name (…), hash: name но \\name(…) -\u003e name(…), а name - ошибка !!!! hash: name Или все же следует различать макросы со скобками и без скобок как два разных объекта??? \\name := name2; и \\name(…) := name2(…); будут разными объектами Или добавить макросы-алиасы без аргументов только для переименования отдельных терминов? \\alias :- name2; но как их отличать от обычных макросов в операции удаления? Или вообще не нужно отличать и оставить только один варинат (либо макрос, либо алиас) Тода вопрос со скобками закрывается сам собой, алиасы всегда без скобок, макросы со скбками или без скобок, но должно быть полное соответствие. @ name name2 @ -\u003e name name2, но name name2(…) - ошибка!!! (hash: name,name2) @ name name2(…) @ -\u003e name name2(…), но name name2 - ошибка !!!! (hash: name,name2) @ name name2… @ -\u003e name name2…, но name name2 - ошибка !!!! ( hash: name,name2 ) @ name $tmpl… name3@ -\u003e name $tmpl… name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 ) Но! @ name name2 @ ::- -\u003e name name2 - ок, но name name2(…) - ок @ name $tmpl name3@ ::- -\u003e name $tmpl… name3 - ок, name $tmpl(…) name3[…] - ок Для последовательности лексем требуется полное соответствие с учетом скобок ??? и может ли быть несколько скобок одного типа (несколько крыглях, или несколько квардратных???? \u003cМожет быть несколько скобок одного типа, например, при указании типа у аргументов или типа возвращаемого значения.\u003e @ name name2 @ -\u003e name name2, но name name2(…) - ошибка!!! (hash: name,name2) @ name name2(…) @ -\u003e name name2(…), но name name2 - ошибка !!!! (hash: name,name2) @ name name2… @ -\u003e name name2…, но name name2 - ошибка !!!! ( hash: name,name2 ) @ name $tmpl… name3@ -\u003e name $tmpl… name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 ) Проблема скобок возникает из-за сценария замены одного термина на другой, который есть в препроцессоре С/С++, но отсутствует при реализации с использованием шаблонов. */\nМакросы используются и для превращеня исходного кода NewLang в более привычный синтаксис на основе ключевых слов, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода.\nНапример:.\n@@if(...)@@ ::= @@ [ \\$* ]--\u003e @@; @@while(...)@@ ::= @@ [\\$*] \u003c-\u003e @@; @@return $arg@@::= @@ -- \\$arg -- @@; @@true@@ ::= 1; Тогда цикл до 5:\ncount:=1; [ 1 ] \u003c-\u003e { [count\u003e5] --\u003e { -- 42 --; }; count+=1; }; будет выглядеть более привычно\ncount:=1; while( true ) { if(count\u003e5) { return 42; }; count+=1; }; Идеи на будущее Символьное программирование Символьное программирование, часто называемое декларативным программированием, представляет собой парадигму программирования, которая использует математическую логику, отношения и символы для представления знаний и помощи в решении проблем. Вместо того, чтобы сосредотачиваться на описании последовательности операций, необходимых для выполнения вычислений, как в императивном программировании, символическое программирование делает упор на выражении отношений и ограничений между структурами данных, уделяя особое внимание «что», а не «как».\nВ контексте парадигм программирования символическое программирование часто противопоставляется процедурному или императивному программированию, где программы определяют пошаговые процедуры для достижения своих целей. В то время как императивное программирование фокусируется на описании потока управления с использованием таких конструкций, как циклы и условные выражения, для управления выполнением, символическое программирование сосредоточено на выражении фактов о проблеме и позволяет выполнению естественным образом выводить последующие последствия из предоставленной информации.\nОдним из основных преимуществ символьного программирования является его способность обеспечивать более высокий уровень абстракции, что упрощает анализ кода и снижает вероятность ошибок. Непосредственно выражая отношения и ограничения, символическое программирование позволяет разработчикам сосредоточиться на моделировании и спецификации проблем, позволяя базовой системе управлять реализацией и выполнением алгоритмов.\nСуществует несколько языков программирования и сред, использующих парадигму символьного программирования, например Prolog, Lisp и Haskell. Например, Пролог — это язык логического программирования, который позволяет разработчикам выражать взаимосвязи и факты о проблемных областях, в то время как выполнение автоматически обосновывает и извлекает новые факты на основе исходной информации. В том же духе Лисп, функциональный язык программирования, использует символьные вычисления для манипулирования структурами данных и выполнения сложных операций над ними, используя краткий и математически обоснованный синтаксис. Haskell, еще один функциональный язык программирования, использует строгую типизацию и ленивые вычисления, чтобы обеспечить символическое рассуждение и облегчить эффективное создание программ.\nСимвольное программирование может быть полезным в широком спектре проблемных областей, включая искусственный интеллект, экспертные системы, программирование логики ограничений и символьную математику, среди других. Более высокий уровень абстракции, обеспечиваемый декларативными языками программирования, облегчает разработку сложных систем, сводя к минимуму вероятность ошибки и улучшая удобство обслуживания. В частности, использование символьного программирования в искусственном интеллекте позволяет разработчикам создавать системы представления знаний и механизмы рассуждения, которые можно применять для обработки естественного языка, машинного обучения и автоматического доказательства теорем.\nРазличие между символьным программированием и препроцессором\nЗадача препроцессора - раскрыть(расширить) макрос, тогда как при символьном программировании нужно сокращать (сворачивать) выражения Препроцессор обрабатывает последовательности лексем (плоские данные), тогда как символьное программирование оперирует выражениями (деревом лексем) Макрос у препроцессора идентифицируется первым термином, и если макрос не может быть раскрыт, то возникает ошибка. В символьном программировани требуется точное соответствие всего выражения и только в этом случае производится сокращение выражения. Предпосылки для реализации символьного программирования Компилятор - интерепретатор с REPL и обработка AST как во время компиляции, так и во время выполнения. Необходимо добавить конструкции для определения правил символьного программрования (чистые функции?) Необходимо добавить конструкцию для вычисления выражений в символьном программировании.\nWolfram https://habr.com/ru/articles/772984/\ndiffRules = { Sin[x] -\u003e Cos[x], Cos[x] -\u003e -Sin[x], x^2 -\u003e 2*x, x -\u003e 1, Log[x] -\u003e 1/x }; diffRules := ( Sin(x) @-\u003e Cos(x), Cos(x) @-\u003e -Sin(x), x^2 @-\u003e 2*x, x @-\u003e 1, Log(x) @-\u003e 1\\x, ); expr @-\u003e Sin(x) - x^2 + Log(x); # И применим к нему правила дифференцирования #expr /. diffRules #(* 1/x - 2 x + Cos[x] *) sym := SymEval(expr, diffRules); res := Eval(sym, x=0.123); expr = a^2 + 3 * b^3 - c^4 + 2 * x^2 - x + 4*c + 3 И я хочу это выражение линеаризовать, т.е. отбросить все степени выше первой. Я могу сделать это напрямую, как в примерах выше: expr /. { a^2 -\u003e 0, b^3 -\u003e 0, c^4 -\u003e 0, x^2 -\u003e 0 } (* 3 + 4 c - x *) Но это слишком неудобно. Что если я не знаю ни точную степень, ни имя переменной? Как просто указать, что нужно заменить все места, где встречается возведение в степень на ноль? Это можно сделать при помощи шаблонов вот так: expr /. Power[_, _] -\u003e 0 (* 3 + 4 c - x *) Либо вот так: expr /. _ ^ _ -\u003e 0 (* 3 + 4 c - x *) :diffRules() := { {@ Sin(x) @} ::- {@ Cos(x) @}; Cos(x) @-\u003e -Sin(x), x^2 @-\u003e 2*x, x @-\u003e 1, Log(x) @-\u003e 1\\x, }; expr @-\u003e Sin(x) - x^2 + Log(x); # И применим к нему правила дифференцирования #expr /. diffRules #(* 1/x - 2 x + Cos[x] *) sym := SymEval(expr, diffRules); res := Eval(sym, x=0.123); ","categories":"","description":"","excerpt":"Макросы в NewLang, это один или несколько последовательных терминов, …","ref":"/ru/docs/syntax/macros/","tags":"","title":"Макросы"},{"body":"Пусто (:None) :None (пусто) — не содержит значения (точнее имеет одно значение :None). Указывается в тексте программы как один подчерк «_». Значение None имеют не инициализированные переменные и при попытке чтения из такой переменной возникает ошибка.\nТип переменной может быть явно указан или выведен автоматически из присваиваемого значения. Присвоить новое значение уже инициализированной переменной можно только для совместимого типа, так как неявное преобразование типов не допускаются.\n$var := _; # Создать не инициализированную переменную $var2 := var; # Ошибка!!! Нельзя прочитать не инициализированную переменную var $var = 1000; # У переменной будет тип Short (минимальный размер для хранения значения) $var = 0,5; # Ошибка!!! Short ← Float не совместимы $var = _; # Очистить значение переменной $var = 0,5; # Теперь можно, т. к. None совместим с любым типом Диапазон (:Range) Диапазон — специальный тип данных, являющейся приблизительным аналогом типа «генератор» в Python. К диапазону можно обращаться как к итератору и он будет поочередно выдавать элементы в указанном интервале с заданным шагом. Диапазон в тексте программы указывается как два или три элемента через две точки, например 1..5 — диапазон от единицы до пяти с шагом по умолчанию 1. В качестве параметров диапазона можно указывать не только литералы, но и имена переменных и даже рациональные числа. Например, 0,1..$stop..0,1 — диапазон от 0,1 до значения, указанного в переменной $stop с шагом 0,1 или 0..1\\10 - диапазон рациональных числе от 0 до 10.\nДиапазон целых чисел можно использовать в качестве индекса у тензоров (точнее, у любых объектов, которые допускают доступ к своим элементам по индексу, т.е. тензоры, словари и текстовые строки). Фактический, это поведение аналогично slice в языке Python и array[1:5] в Python означает тоже самое, что и array[1..5] в NewLang.\nВ качестве индекса у тензоров еще можно указать произвольное количество измерений с помощью многоточия, т.е.\n$tensor[…, 0] = 0; # Обнулить все первые элементы в каждом измерении. В будущем можно будет добавить возможность указывать индексы элементов с помощь диапазонов\n$tensor = :Tensor[12](4..4 = 29, 2..3 = 15, , 7..9..2 = 7, 10 ...); # [0, 0, 15, 15, 29, 0, 0, 7, 0, 7, 10, 10,] Поток (:Thread) Поток — специальный тип данных, который запускает функцию в отдельном потоке, который выполнтеся паралельно основному потоку приложения. Поток созадется в остановленном виде и для его запуска необходимо вызвать метод start(), а чтобы дождаться завершения потока вызывается метод join().\nrand():Int32 := %rand; usleep(usec:DWord64):None := %usleep; printf(format:FmtChar, ...):Int32 := %printf; func(count:Integer, target:String) := { $iter := 1..$count?; # Итератор для диапазона от 1 до $count [ $iter ?! ] \u003c-\u003e { # Цикл, пока итератор валидный $step := $iter!; # Получить текущий и перейти на следующий элемент итератора printf('Number %d from %s!', $step, $target); usleep( rand() % 1000 ); # Случайная задержка } } thread = :Thread(func, 5, 'thread'); thread.start(); func(5, 'main'); thread.join(); Number 1 from the thread! Number 1 from the main! Number 2 from the thread! Number 2 from the main! Number 3 from the thread! Number 4 from the thread! Number 3 from the main! Number 4 from the main! Number 5 from the main! Number 5 from the thread!\nУсловные переменные (condvars). Сходны с событиями, но не являются объектами, занимающими память — используется только адрес переменной, понятие «содержимое переменной» не существует, в качестве условной переменной может использоваться адрес произвольного объекта. В отличие от событий, установка условной переменной в просигнализированное состояние не влечёт за собой никаких последствий в случае, если на данный момент нет потоков, ожидающих на переменной. Установка события в аналогичном случае влечёт за собой запоминание состояния «просигнализировано» внутри самого события, после чего следующие потоки, желающие ожидать события, продолжают исполнение немедленно без остановки. Для полноценного использования такого объекта необходима также операция «освободить mutex и ожидать условную переменную атомарно». Активно используются в UNIX-подобных ОС. Дискуссии о преимуществах и недостатках событий и условных переменных являются заметной частью дискуссий о преимуществах и недостатках Windows и UNIX.\nERESOURCE. Мьютекс, поддерживающий рекурсивный захват, с семантикой разделяемого или эксклюзивного захвата. Семантика: объект может быть либо свободен, либо захвачен произвольным числом потоков разделяемым образом, либо захвачен всего одним потоком эксклюзивным образом. Любые попытки осуществить захваты, нарушающее это правило, приводят к блокировке потока до тех пор, пока объект не освободится так, чтобы сделать захват разрешённым. Также есть операции вида TryToAcquire — никогда не блокирует поток, либо захватывает, либо (если нужна блокировка) возвращает FALSE, ничего не делая. Используется в ядре Windows, особенно в файловых системах — так, например, любому кем-то открытому дисковому файлу соответствует структура FCB, в которой есть 2 таких объекта для синхронизации доступа к размеру файла. Один из них — paging IO resource — захватывается эксклюзивно только в пути обрезания файла, и гарантирует, что в момент обрезания на файле нет активного ввода-вывода от кэша и от отображения в память.\nИнтерфейс операционной системы (:System) Для доступа к различным функциям операционной системы NewLang предоставляет специальный тип данных :System. Он позволяет запускать системные команды и переопределять для них параметры системного окружения.\nВыполнение команды происходит при вызове метода run(), которому нужно передать имя системной команды и при необходимости дополнительные аргументы командной строки.\nРезультат выполнения команды (текстовый вывод, код завершения и т.д.) доступен как отдельные свойства объекта.\nПример:\n:System().run(\"echo\", \"Hello from the other side!\"); os := :System(); home_dir := os.run(\"cd\", \"~\"); printf(\"`cd ~` ran with exit code %d\", os.exitcode()); unknown_dir := os.run(\"cd\", \"doesnotexist\"); printf(\"`cd doesnotexis` ran with exit code %d\", os.exitcode()); Первая строка делает запускает команду echo.\nПотом создается объект :System и далее мы создаем две переменные, в которых хранятся результаты этой выполнения команды cd, которые изменяют каталог на домашнюю папку и на несуществующую папку.\nЗапустив этот файл, мы увидим:\nHello from the other side! `cd ~` ran with exit code 0 sh: line 0: cd: doesnotexist: No such file or directory `cd doesnotexist` ran with exit code 256 Первая строка - результат выполнения команды echo.\nДалее команда cd выполняется успешно и изменяет каталог на домашний. Следовательно, код возврата ноль, который получаем с помощью вызова метода exitcode().\nПоследняя команда cd выполняется с ошибкой, так как пытается изменить каталог на несуществующую папку.\nПростой варинат выполнение системной команды Есть упрощенный вариант выполнения системной команды с помощью заключения строки выполнения в обратные кавычки (как в bash).\n`echo Hello from the other side!`; В этом случае системная команда :System.run() сразу выполняется, а её текстовый вывод сохраняется в текстовую строку с широкими символами (:StrWide).\nЧтобы получить код возврата (например, чтобы проверить результат завершения на ошибки), можно обратится к результату выполнения последней команды $^.exitcode() или сохранить результат выполнения предыдущей команды в отдельную переменню, которая будет иметь тип :System.\n`echo Hello from the other side!`; res := $^; printf(\"`cd doesnotexis` ran with exit code %d\", res.exitcode()); В дальнейшем планируется расширить возможности интерфейса с операционной системой фоновое выполнение программ (useless_cat_call = subprocess.run([“cat”], stdout=subprocess.PIPE, text=True, input=“Hello from the other side”)) переназначение ввода/вывода (list_dir = subprocess.Popen([“ls”, “-l”]); list_dir.wait()) чтение/изменние перемнных окржения Еще пример возможностей для расширения os.name - имя операционной системы. Доступные варианты: ‘posix’, ’nt’, ‘mac’, ‘os2’, ‘ce’, ‘java’. os.environ - словарь переменных окружения. Изменяемый (можно добавлять и удалять переменные окружения). os.getlogin() - имя пользователя, вошедшего в терминал (Unix). os.getpid() - текущий id процесса. os.uname() - информация об ОС. возвращает объект с атрибутами: sysname - имя операционной системы, nodename - имя машины в сети (определяется реализацией), release - релиз, version - версия, machine - идентификатор машины. os.access(path, mode, *, dir_fd=None, effective_ids=False, follow_symlinks=True) - проверка доступа к объекту у текущего пользователя. Флаги: os.F_OK - объект существует, os.R_OK - доступен на чтение, os.W_OK - доступен на запись, os.X_OK - доступен на исполнение. os.chdir(path) - смена текущей директории. os.chmod(path, mode, *, dir_fd=None, follow_symlinks=True) - смена прав доступа к объекту (mode - восьмеричное число). os.chown(path, uid, gid, *, dir_fd=None, follow_symlinks=True) - меняет id владельца и группы (Unix). os.getcwd() - текущая рабочая директория. os.link(src, dst, *, src_dir_fd=None, dst_dir_fd=None, follow_symlinks=True) - создаёт жёсткую ссылку. os.listdir(path=\".\") - список файлов и директорий в папке. os.mkdir(path, mode=0o777, *, dir_fd=None) - создаёт директорию. OSError, если директория существует. os.makedirs(path, mode=0o777, exist_ok=False) - создаёт директорию, создавая при этом промежуточные директории. os.remove(path, *, dir_fd=None) - удаляет путь к файлу. os.rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None) - переименовывает файл или директорию из src в dst. os.renames(old, new) - переименовывает old в new, создавая промежуточные директории. os.replace(src, dst, *, src_dir_fd=None, dst_dir_fd=None) - переименовывает из src в dst с принудительной заменой. os.rmdir(path, *, dir_fd=None) - удаляет пустую директорию. os.removedirs(path) - удаляет директорию, затем пытается удалить родительские директории, и удаляет их рекурсивно, пока они пусты. os.symlink(source, link_name, target_is_directory=False, *, dir_fd=None) - создаёт символическую ссылку на объект. os.sync() - записывает все данные на диск (Unix). os.truncate(path, length) - обрезает файл до длины length. os.utime(path, times=None, *, ns=None, dir_fd=None, follow_symlinks=True) - модификация времени последнего доступа и изменения файла. Либо times - кортеж (время доступа в секундах, время изменения в секундах), либо ns - кортеж (время доступа в наносекундах, время изменения в наносекундах). os.walk(top, topdown=True, onerror=None, followlinks=False) - генерация имён файлов в дереве каталогов, сверху вниз (если topdown равен True), либо снизу вверх (если False). Для каждого каталога функция walk возвращает кортеж (путь к каталогу, список каталогов, список файлов). os.system(command) - исполняет системную команду, возвращает код её завершения (в случае успеха 0). os.urandom(n) - n случайных байт. Возможно использование этой функции в криптографических целях. ","categories":"","description":"","excerpt":"Пусто (:None) :None (пусто) — не содержит значения (точнее имеет одно …","ref":"/docs/types/other/","tags":["типы данных"],"title":"Другие типы данных"},{"body":"Пусто (:None) :None (пусто) — не содержит значения (точнее имеет одно значение :None). Указывается в тексте программы как один подчерк «_». Значение None имеют не инициализированные переменные и при попытке чтения из такой переменной возникает ошибка.\nТип переменной может быть явно указан или выведен автоматически из присваиваемого значения. Присвоить новое значение уже инициализированной переменной можно только для совместимого типа, так как неявное преобразование типов не допускаются.\n$var := _; # Создать не инициализированную переменную $var2 := var; # Ошибка!!! Нельзя прочитать не инициализированную переменную var $var = 1000; # У переменной будет тип Short (минимальный размер для хранения значения) $var = 0,5; # Ошибка!!! Short ← Float не совместимы $var = _; # Очистить значение переменной $var = 0,5; # Теперь можно, т. к. None совместим с любым типом Диапазон (:Range) Диапазон — специальный тип данных, являющейся приблизительным аналогом типа «генератор» в Python. К диапазону можно обращаться как к итератору и он будет поочередно выдавать элементы в указанном интервале с заданным шагом. Диапазон в тексте программы указывается как два или три элемента через две точки, например 1..5 — диапазон от единицы до пяти с шагом по умолчанию 1. В качестве параметров диапазона можно указывать не только литералы, но и имена переменных и даже рациональные числа. Например, 0,1..$stop..0,1 — диапазон от 0,1 до значения, указанного в переменной $stop с шагом 0,1 или 0..1\\10 - диапазон рациональных числе от 0 до 10.\nДиапазон целых чисел можно использовать в качестве индекса у тензоров (точнее, у любых объектов, которые допускают доступ к своим элементам по индексу, т.е. тензоры, словари и текстовые строки). Фактический, это поведение аналогично slice в языке Python и array[1:5] в Python означает тоже самое, что и array[1..5] в NewLang.\nВ качестве индекса у тензоров еще можно указать произвольное количество измерений с помощью многоточия, т.е.\n$tensor[…, 0] = 0; # Обнулить все первые элементы в каждом измерении. В будущем можно будет добавить возможность указывать индексы элементов с помощь диапазонов\n$tensor = :Tensor[12](4..4 = 29, 2..3 = 15, , 7..9..2 = 7, 10 ...); # [0, 0, 15, 15, 29, 0, 0, 7, 0, 7, 10, 10,] Поток (:Thread) Поток — специальный тип данных, который запускает функцию в отдельном потоке, который выполнтеся паралельно основному потоку приложения. Поток созадется в остановленном виде и для его запуска необходимо вызвать метод start(), а чтобы дождаться завершения потока вызывается метод join().\nrand():Int32 := %rand; usleep(usec:DWord64):None := %usleep; printf(format:FmtChar, ...):Int32 := %printf; func(count:Integer, target:String) := { $iter := 1..$count?; # Итератор для диапазона от 1 до $count [ $iter ?! ] \u003c-\u003e { # Цикл, пока итератор валидный $step := $iter!; # Получить текущий и перейти на следующий элемент итератора printf('Number %d from %s!', $step, $target); usleep( rand() % 1000 ); # Случайная задержка } } thread = :Thread(func, 5, 'thread'); thread.start(); func(5, 'main'); thread.join(); Number 1 from the thread! Number 1 from the main! Number 2 from the thread! Number 2 from the main! Number 3 from the thread! Number 4 from the thread! Number 3 from the main! Number 4 from the main! Number 5 from the main! Number 5 from the thread!\nУсловные переменные (condvars). Сходны с событиями, но не являются объектами, занимающими память — используется только адрес переменной, понятие «содержимое переменной» не существует, в качестве условной переменной может использоваться адрес произвольного объекта. В отличие от событий, установка условной переменной в просигнализированное состояние не влечёт за собой никаких последствий в случае, если на данный момент нет потоков, ожидающих на переменной. Установка события в аналогичном случае влечёт за собой запоминание состояния «просигнализировано» внутри самого события, после чего следующие потоки, желающие ожидать события, продолжают исполнение немедленно без остановки. Для полноценного использования такого объекта необходима также операция «освободить mutex и ожидать условную переменную атомарно». Активно используются в UNIX-подобных ОС. Дискуссии о преимуществах и недостатках событий и условных переменных являются заметной частью дискуссий о преимуществах и недостатках Windows и UNIX.\nERESOURCE. Мьютекс, поддерживающий рекурсивный захват, с семантикой разделяемого или эксклюзивного захвата. Семантика: объект может быть либо свободен, либо захвачен произвольным числом потоков разделяемым образом, либо захвачен всего одним потоком эксклюзивным образом. Любые попытки осуществить захваты, нарушающее это правило, приводят к блокировке потока до тех пор, пока объект не освободится так, чтобы сделать захват разрешённым. Также есть операции вида TryToAcquire — никогда не блокирует поток, либо захватывает, либо (если нужна блокировка) возвращает FALSE, ничего не делая. Используется в ядре Windows, особенно в файловых системах — так, например, любому кем-то открытому дисковому файлу соответствует структура FCB, в которой есть 2 таких объекта для синхронизации доступа к размеру файла. Один из них — paging IO resource — захватывается эксклюзивно только в пути обрезания файла, и гарантирует, что в момент обрезания на файле нет активного ввода-вывода от кэша и от отображения в память.\nИнтерфейс операционной системы (:System) Для доступа к различным функциям операционной системы NewLang предоставляет специальный тип данных :System. Он позволяет запускать системные команды и переопределять для них параметры системного окружения.\nВыполнение команды происходит при вызове метода run(), которому нужно передать имя системной команды и при необходимости дополнительные аргументы командной строки.\nРезультат выполнения команды (текстовый вывод, код завершения и т.д.) доступен как отдельные свойства объекта.\nПример:\n:System().run(\"echo\", \"Hello from the other side!\"); os := :System(); home_dir := os.run(\"cd\", \"~\"); printf(\"`cd ~` ran with exit code %d\", os.exitcode()); unknown_dir := os.run(\"cd\", \"doesnotexist\"); printf(\"`cd doesnotexis` ran with exit code %d\", os.exitcode()); Первая строка делает запускает команду echo.\nПотом создается объект :System и далее мы создаем две переменные, в которых хранятся результаты этой выполнения команды cd, которые изменяют каталог на домашнюю папку и на несуществующую папку.\nЗапустив этот файл, мы увидим:\nHello from the other side! `cd ~` ran with exit code 0 sh: line 0: cd: doesnotexist: No such file or directory `cd doesnotexist` ran with exit code 256 Первая строка - результат выполнения команды echo.\nДалее команда cd выполняется успешно и изменяет каталог на домашний. Следовательно, код возврата ноль, который получаем с помощью вызова метода exitcode().\nПоследняя команда cd выполняется с ошибкой, так как пытается изменить каталог на несуществующую папку.\nПростой варинат выполнение системной команды Есть упрощенный вариант выполнения системной команды с помощью заключения строки выполнения в обратные кавычки (как в bash).\n`echo Hello from the other side!`; В этом случае системная команда :System.run() сразу выполняется, а её текстовый вывод сохраняется в текстовую строку с широкими символами (:StrWide).\nЧтобы получить код возврата (например, чтобы проверить результат завершения на ошибки), можно обратится к результату выполнения последней команды $^.exitcode() или сохранить результат выполнения предыдущей команды в отдельную переменню, которая будет иметь тип :System.\n`echo Hello from the other side!`; res := $^; printf(\"`cd doesnotexis` ran with exit code %d\", res.exitcode()); В дальнейшем планируется расширить возможности интерфейса с операционной системой фоновое выполнение программ (useless_cat_call = subprocess.run([“cat”], stdout=subprocess.PIPE, text=True, input=“Hello from the other side”)) переназначение ввода/вывода (list_dir = subprocess.Popen([“ls”, “-l”]); list_dir.wait()) чтение/изменние перемнных окржения Еще пример возможностей для расширения os.name - имя операционной системы. Доступные варианты: ‘posix’, ’nt’, ‘mac’, ‘os2’, ‘ce’, ‘java’. os.environ - словарь переменных окружения. Изменяемый (можно добавлять и удалять переменные окружения). os.getlogin() - имя пользователя, вошедшего в терминал (Unix). os.getpid() - текущий id процесса. os.uname() - информация об ОС. возвращает объект с атрибутами: sysname - имя операционной системы, nodename - имя машины в сети (определяется реализацией), release - релиз, version - версия, machine - идентификатор машины. os.access(path, mode, *, dir_fd=None, effective_ids=False, follow_symlinks=True) - проверка доступа к объекту у текущего пользователя. Флаги: os.F_OK - объект существует, os.R_OK - доступен на чтение, os.W_OK - доступен на запись, os.X_OK - доступен на исполнение. os.chdir(path) - смена текущей директории. os.chmod(path, mode, *, dir_fd=None, follow_symlinks=True) - смена прав доступа к объекту (mode - восьмеричное число). os.chown(path, uid, gid, *, dir_fd=None, follow_symlinks=True) - меняет id владельца и группы (Unix). os.getcwd() - текущая рабочая директория. os.link(src, dst, *, src_dir_fd=None, dst_dir_fd=None, follow_symlinks=True) - создаёт жёсткую ссылку. os.listdir(path=\".\") - список файлов и директорий в папке. os.mkdir(path, mode=0o777, *, dir_fd=None) - создаёт директорию. OSError, если директория существует. os.makedirs(path, mode=0o777, exist_ok=False) - создаёт директорию, создавая при этом промежуточные директории. os.remove(path, *, dir_fd=None) - удаляет путь к файлу. os.rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None) - переименовывает файл или директорию из src в dst. os.renames(old, new) - переименовывает old в new, создавая промежуточные директории. os.replace(src, dst, *, src_dir_fd=None, dst_dir_fd=None) - переименовывает из src в dst с принудительной заменой. os.rmdir(path, *, dir_fd=None) - удаляет пустую директорию. os.removedirs(path) - удаляет директорию, затем пытается удалить родительские директории, и удаляет их рекурсивно, пока они пусты. os.symlink(source, link_name, target_is_directory=False, *, dir_fd=None) - создаёт символическую ссылку на объект. os.sync() - записывает все данные на диск (Unix). os.truncate(path, length) - обрезает файл до длины length. os.utime(path, times=None, *, ns=None, dir_fd=None, follow_symlinks=True) - модификация времени последнего доступа и изменения файла. Либо times - кортеж (время доступа в секундах, время изменения в секундах), либо ns - кортеж (время доступа в наносекундах, время изменения в наносекундах). os.walk(top, topdown=True, onerror=None, followlinks=False) - генерация имён файлов в дереве каталогов, сверху вниз (если topdown равен True), либо снизу вверх (если False). Для каждого каталога функция walk возвращает кортеж (путь к каталогу, список каталогов, список файлов). os.system(command) - исполняет системную команду, возвращает код её завершения (в случае успеха 0). os.urandom(n) - n случайных байт. Возможно использование этой функции в криптографических целях. ","categories":"","description":"","excerpt":"Пусто (:None) :None (пусто) — не содержит значения (точнее имеет одно …","ref":"/ru/docs/types/other/","tags":["типы данных"],"title":"Другие типы данных"},{"body":"Нативные типы данных Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента “%”. В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат.\n:Pointer — указатель на системную область памяти или нативную функцию Так как любой программе приходится взаимодействовать с внешним миром, т о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип :Pointer. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. Но можно вывести его значение, например для отладки.\n:Plain — указатель на представление данных в бинарном виде Для взаимодействия с внешними библиотеками требуется еще и обмен данными. И для этих целей служит тип данных :Plain — который также является указателем, но на двоичное представление данных в области памяти. Конечно, если их можно представить в виде одного фрагмента.\nПеречисление, структура и объединение :Enum, :Struct и :Union — это такие же словари, только на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера. Эти типы данных так же относятся к группе :Plain и могут быть представлены в двоичном виде в одной области машинной памяти.\n","categories":"","description":"","excerpt":"Нативные типы данных Нативными (машинные) данными могут быть как …","ref":"/docs/types/native/","tags":["типы данных","системые типы","коллекции"],"title":"Нативные типы"},{"body":"Нативные типы данных Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента “%”. В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат.\n:Pointer — указатель на системную область памяти или нативную функцию Так как любой программе приходится взаимодействовать с внешним миром, т о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип :Pointer. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. Но можно вывести его значение, например для отладки.\n:Plain — указатель на представление данных в бинарном виде Для взаимодействия с внешними библиотеками требуется еще и обмен данными. И для этих целей служит тип данных :Plain — который также является указателем, но на двоичное представление данных в области памяти. Конечно, если их можно представить в виде одного фрагмента.\nПеречисление, структура и объединение :Enum, :Struct и :Union — это такие же словари, только на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера. Эти типы данных так же относятся к группе :Plain и могут быть представлены в двоичном виде в одной области машинной памяти.\n","categories":"","description":"","excerpt":"Нативные типы данных Нативными (машинные) данными могут быть как …","ref":"/ru/docs/types/native/","tags":["типы данных","системые типы","коллекции"],"title":"Нативные типы"},{"body":"Несмотря на динамическую типизацию языка, если тип переменной указан явно, то автоматическое приведение типов не выполняется, и чтобы присвоить переменой значение не совместимого типа, требуется его явное преобразование.\nТак как символьные названия типов относятся к деталям реализации, то явное преобразование в конкретный тип данных производится с помощью вызова функции с именем типа, т.е. :Bool(), :StrWide(), :Int64() и т.д.\nПримеры:\nСтроки и тензоры # Создать тензор из строки широких символов с автоматическим выводом типа #(тип Int32 будет на системах с Linux, а под Windows тип тензора будет Int16) \u003e tstr := :Tensor(\"Тест\"); [1058, 1077, 1089, 1090,]:Int32 # Тоже самое, но тензор заданной размерности \u003e t2 := :Tensor[2,2](\"Тест\"); [ [1058, 1077,], [1089, 1090,], ]:Int32 # Создать символьную строку из тензора \u003e :StrWide(tstr) Тест # Изменить тип данных тензора без изменения размерности \u003e :Float64(t2) [ [1058, 1077,], [1089, 1090,], ]:Float64 # Изменить размерность тензора и его тип # (в данном случае с частичной потерей данных) \u003e t3 := :Int8[4]( t2 ) [34, 53, 65, 66,]:Int8 Словари # Создать тензор из словаря \u003e:Tensor( (1,2,3,) ); [1, 2, 3,]:Int8 # Преобразовать байтовую строку в тензор \u003e:Tensor( 'first second' ) [102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Int8 # Получаем тензор из словаря с такими же данными \u003e:Tensor( ('first', space=32, second='second',) ) [102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Int8 ","categories":"","description":"","excerpt":"Несмотря на динамическую типизацию языка, если тип переменной указан …","ref":"/docs/types/convert/","tags":["типы данных"],"title":"Преобразование типов"},{"body":"Несмотря на динамическую типизацию языка, если тип переменной указан явно, то автоматическое приведение типов не выполняется, и чтобы присвоить переменой значение не совместимого типа, требуется его явное преобразование.\nТак как символьные названия типов относятся к деталям реализации, то явное преобразование в конкретный тип данных производится с помощью вызова функции с именем типа, т.е. :Bool(), :StrWide(), :Int64() и т.д.\nПримеры:\nСтроки и тензоры # Создать тензор из строки широких символов с автоматическим выводом размера и типа данных #(тип Int32 будет на системах с Linux, а под Windows тип тензора будет Int16) \u003e tstr := :Tensor[...](\"Тест\"); [1058, 1077, 1089, 1090,]:Int32 # Тоже самое, но тензор заданной размерности \u003e t2 := :Tensor[2,2](\"Тест\"); [ [1058, 1077,], [1089, 1090,], ]:Int32 # Создать символьную строку из тензора \u003e :StrWide(tstr) Тест # Изменить тип данных тензора без изменения размерности \u003e :Float64[...](t2) [ [1058, 1077,], [1089, 1090,], ]:Float64 # Изменить размерность тензора и его тип # (в данном случае с частичной потерей данных) \u003e t3 := :Int8[4]( t2 ) [34, 53, 65, 66,]:Int8 # Логическое значение - скаляр \u003e:Bool( [0, 53, 65, 66,] ); 1:Bool # Или так (тензор нулевой размерности) \u003e:Bool[0]( [0, 53, 65, 66,] ); 1:Bool # Тензор логических значений без изменения размера \u003e:Bool[_]( [0, 53, 65, 66,] ); [0, 1, 1, 1,]:Bool Словари # Создать тензор из словаря с автоматическим выводом размера \u003e:Tensor[...]( (1,2,3,) ); [1, 2, 3,]:Int8 # Преобразовать байтовую строку в одномерный тензор \u003e:Tensor[_]( 'first second' ) [102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Int8 # Получаем тензор из словаря с такими же данными \u003e:Tensor[...]( ('first', space=32, second='second',) ) [102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Int8 # Логическое значение - скаляр \u003e:Bool( (0,1,2,3,) ); 1:Bool # Тензор логических значений \u003e:Bool[...]( (0,1,2,3,) ); [0, 1, 1, 1]:Bool # Различия между \"...\" и \"_\" # Автоматический вывод размеров измерений \u003e:Tensor[...]( ((1,2,3,), (4,5,6,), (7,8,9,),) ); [ [1, 2, 3,], [4, 5, 6,], [7, 8, 9,] ]:Int8 # Одномерный тензор с произвольным размером \u003e:Tensor[_]( ((1,2,3,), (4,5,6,), (7,8,9,),) ); [ 1, 2, 3, 4, 5, 6, 7, 8, 9,]:Int8 ","categories":"","description":"","excerpt":"Несмотря на динамическую типизацию языка, если тип переменной указан …","ref":"/ru/docs/types/convert/","tags":["типы данных"],"title":"Преобразование типов"},{"body":"Системные свойства Несмотря на то, что не все объекты NewLang являются классами с точки зрения реализованной концепции ООП, тем не менее, каждый объект имеет системные свойства, которые можно считать во время выполнения как обычные свойства объекта:\nУ всех переменных (объектов) есть системные свойства __name__ - краткое имя переменной (объекта)\n__full_name__ - полное имя переменной, включая имя модуля и пространство имен\n__type__ - текущий тип переменной. Может изменится при некоторых операциях\n__type_fixed__ - тип переменной (объекта) который не может измениться (ограничитель)\n__module__ - имя модуля в котором определена переменная (объект)\n__class__ - имя класса переменной или пусто, если объект не является классом\n__base__ - словарь со списком базовых классов или пусто, если объект не является классом\n__size__ - количество элементов у объекта, если применимо или :None\n__doc__ - документация по текущему объекту (если есть, иначе пустая строка)\n__str__ - строковое представление объекта для дампа\n__source__ - исходный текст модуля или функции\nСистемные свойства у модулей __file__ - полный путь к файлу модуля (соответствует С/С++ макросу __FILE__) __timestamp__ - дата и время последней модификации файла модуля (соответствует макросу С/С++ __TIMESTAMP__) __md5__ - хеш исходных данных модуля (соответствует макросу __MD5__) DSL Особенности ассоциативной памяти Синтаксис языка NewLang основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например if, чем комбинация минус минус правая угловая скобка –\u003e. Из-за этого имеет смысл использовать не “чистый” базовый синтаксис, а более привычный диалект с использованием ключевых слов.\nСинтаксис на ключевых словах В файле dsl.nlp находится набор макросов, которые расширяют базовый синтаксис NewLang, основанный на правилах, набором предопределенных ключевых слов как в классических языках программирования. А при необходимости, их можно адаптировать или дополнить под собственную предметную область.\nКонстанты Логические true - 1 yes - 1 false - 0 no - 0 Системные имена this - Текущий объект ($0) parent - Родительский объект ($$) last - Результат выполнения последнего оператора ($^) !!!!!!!!- args - Все аргументы функции ($*)\n!!!!!!!!- sys - Системный контекст запущенной программы (@@) !!!!!!!!- current - Текущий модуль (@$) !!!!!!!!- cmd - Все аргументы выполняющегося приложения из командной строки (@*)\n!!!!!!!!!!1### Типовые функции и проверки !!!!!!!!!!- run(‘filename’) - Выполнить указанный файл (@@(‘filename’)) !!!!!!!!!!- ifmain - Проверка, если текущий модуль основной ([@$.$0] –\u003e { … }) !!!!!!!!!!- ifload - Проверка, если текущий модуль загружается впервые ([@$.load] –\u003e { … })\nОператоры match(cond) - Оператор оценки выражения\nif(…) - Первый условный оператор ([$*]–\u003e { … })\nelif(…) - Второй и все последующие (,[$*]–\u003e { … })\nelse - Оператор иначе (,[_]–\u003e { … })\nwhile(cond) - Оператор цикла с предусловием ([@$cond] \u003c-\u003e { … } )\ndowhile(cond) - Оператор цикла с постусловием ({ … } \u003c-\u003e[@$cond])\niter(obj, … ) - Создание итератора ( @$obj ? (@$*) )\nnext(obj, … ) - Следующий элемент итератора ( @$obj ! ($*) )\ncurr(obj, … ) - Текущий элемент итератора ( @$obj !? ($*) )\nfirst(obj) - Перейти на первый элемент итератора ( @$obj !! )\nall(obj) - Получить сразу все элементы итератора ( @$obj ??)\nПрерывания return - Положительное прерывание (++)\nreturn(…)- Положительное прерывание с возвратом значения (++ @$value ++)\nerror - Отрицательное прерывание (--)\nerror(…) - Отрицательное прерывание с возвратом значения (-- @$value --)\nbreak+ и break- - Выход из цикла:\nwhile(...) {+ ++ :Break ++ +} while(...) {- -- :Break -- -} continue+ и continue- - В начало цикла: while(...) {+ ++ :Continue ++ +} while(...) {- -- :Continue -- -} obj { .field = 1; .prop(); };\n#Python\n1) without using with statement file = open(‘file_path’, ‘w’) file.write(‘hello world !’) file.close()\n2) without using with statement file = open(‘file_path’, ‘w’) try: file.write(‘hello world’) finally: file.close()\nopen(‘file_path’, ‘w’) { .write(‘hello world !’); .close(); }\nPython3\nusing with statement with open(‘file_path’, ‘w’) as file: file.write(‘hello world !’)\na simple file writer object class MessageWriter(object): def init(self, file_name): self.file_name = file_name\ndef __enter__(self): self.file = open(self.file_name, 'w') return self.file def __exit__(self, *args): self.file.close() using with statement with MessageWriter with MessageWriter(‘my_file.txt’) as xfile: xfile.write(‘hello world’)\na simple file writer object :MessageWriter { def init(self, file_name): self.file_name = file_name\ndef __enter__(self): self.file = open(self.file_name, 'w') return self.file def __exit__(self, *args): self.file.close() }\nusing with statement with MessageWriter MessageWriter(‘my_file.txt’) { .write(‘hello world’); };\nfrom contextlib import contextmanager\nclass MessageWriter(object): def init(self, filename): self.file_name = filename\n@contextmanager def open_file(self): try: file = open(self.file_name, 'w') yield file finally: file.close() usage message_writer = MessageWriter(‘hello.txt’) with message_writer.open_file() as my_file: my_file.write(‘hello world’)\n:MessageWriter(object) { def init(self, filename): self.file_name = filename\n@contextmanager def open_file(self): try: file = open(self.file_name, 'w') yield file finally: file.close() }\nusage message_writer = MessageWriter(‘hello.txt’) with message_writer.open_file() as my_file: my_file.write(‘hello world’)\nПриложения Предопределенные макросы При работе парсера NewLang автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. Данные предопределенные макросы можно использовать как обычные константы.\n__FILE__ или __FILE_NAME__ - имя и полный путь текущего файла\n__LINE__ или __FILE_LINE__ - содержит номер текущей строки в файле\n__FILE_TIMESTAMP__ - дату и время последней модификации текущего файла в строковом представлении\n__FILE_MD5__ - md5 хеш текущего файла в строковом виде\n__COUNTER__ - целочисленный счетчик, который увеличивает свое значение при каждом обращении\n__DATE__ - дата начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIME__ - время начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIMESTAMP__ - дату и время начала запуска компилятора (например: “Fri 19 Aug 13:32:58 2016”)\n__TIMESTAMP_ISO__ - дату и время начала запуска компилятора в формате ISO (например: “2013-07-06T00:50:06Z”)\n__NLC_VER__ - Страшая и младшая версия компилятора NewLang (8 битное число, по 4 бита на цифру)\n__NLC_DATE_BUILD__ - текстовая строка с датой сборки компилятора NewLang (например, “23.06.04 20:51:39”)\n__NLC_SOURCE_GIT__ - текстовая строка с идентификатором исходных файлов NewLang git репозитория, использованных при сборке компилятора (например, “v0.3.0-fef8c371”)\n__NLC_SOURCE_BUILD__ - дата сборки и git идентификатор исходных файлов NewLang одной текстовой строкой (например, “v0.3.0-fef8c371 23.06.04 20:51:39”)\n","categories":"","description":"","excerpt":"Системные свойства Несмотря на то, что не все объекты NewLang являются …","ref":"/docs/syntax/sysprop/","tags":"","title":"Системные свойства"},{"body":"Системные свойства Несмотря на то, что не все объекты NewLang являются классами с точки зрения реализованной концепции ООП, тем не менее, каждый объект имеет системные свойства, которые можно считать во время выполнения как обычные свойства объекта:\nУ всех переменных (объектов) есть системные свойства __name__ - краткое имя переменной (объекта)\n__full_name__ - полное имя переменной, включая имя модуля и пространство имен\n__type__ - текущий тип переменной. Может изменится при некоторых операциях\n__type_fixed__ - тип переменной (объекта) который не может измениться (ограничитель)\n__module__ - имя модуля в котором определена переменная (объект)\n__class__ - имя класса переменной или пусто, если объект не является классом\n__base__ - словарь со списком базовых классов или пусто, если объект не является классом\n__size__ - количество элементов у объекта, если применимо или :None\n__doc__ - документация по текущему объекту (если есть, иначе пустая строка)\n__str__ - строковое представление объекта для дампа\n__source__ - исходный текст модуля или функции\nСистемные свойства у модулей __file__ - полный путь к файлу модуля (соответствует С/С++ макросу __FILE__) __timestamp__ - дата и время последней модификации файла модуля (соответствует макросу С/С++ __TIMESTAMP__) __md5__ - хеш исходных данных модуля (соответствует макросу __MD5__) DSL Особенности ассоциативной памяти Синтаксис языка NewLang основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например if, чем комбинация минус минус правая угловая скобка –\u003e. Из-за этого имеет смысл использовать не “чистый” базовый синтаксис, а более привычный диалект с использованием ключевых слов.\nСинтаксис на ключевых словах В файле dsl.nlp находится набор макросов, которые расширяют базовый синтаксис NewLang, основанный на правилах, набором предопределенных ключевых слов как в классических языках программирования. А при необходимости, их можно адаптировать или дополнить под собственную предметную область.\nКонстанты Логические true - 1 yes - 1 false - 0 no - 0 Системные имена this - Текущий объект ($0) parent - Родительский объект ($$) last - Результат выполнения последнего оператора ($^) !!!!!!!!- args - Все аргументы функции ($*)\n!!!!!!!!- sys - Системный контекст запущенной программы (@@) !!!!!!!!- current - Текущий модуль (@$) !!!!!!!!- cmd - Все аргументы выполняющегося приложения из командной строки (@*)\n!!!!!!!!!!1### Типовые функции и проверки !!!!!!!!!!- run(‘filename’) - Выполнить указанный файл (@@(‘filename’)) !!!!!!!!!!- ifmain - Проверка, если текущий модуль основной ([@$.$0] –\u003e { … }) !!!!!!!!!!- ifload - Проверка, если текущий модуль загружается впервые ([@$.load] –\u003e { … })\nОператоры match(cond) - Оператор оценки выражения\nif(…) - Первый условный оператор ([$*]–\u003e { … })\nelif(…) - Второй и все последующие (,[$*]–\u003e { … })\nelse - Оператор иначе (,[_]–\u003e { … })\nwhile(cond) - Оператор цикла с предусловием ([@$cond] \u003c-\u003e { … } )\ndowhile(cond) - Оператор цикла с постусловием ({ … } \u003c-\u003e[@$cond])\niter(obj, … ) - Создание итератора ( @$obj ? (@$*) )\nnext(obj, … ) - Следующий элемент итератора ( @$obj ! ($*) )\ncurr(obj, … ) - Текущий элемент итератора ( @$obj !? ($*) )\nfirst(obj) - Перейти на первый элемент итератора ( @$obj !! )\nall(obj) - Получить сразу все элементы итератора ( @$obj ??)\nПрерывания return - Положительное прерывание (++)\nreturn(…)- Положительное прерывание с возвратом значения (++ @$value ++)\nerror - Отрицательное прерывание (--)\nerror(…) - Отрицательное прерывание с возвратом значения (-- @$value --)\nbreak+ и break- - Выход из цикла:\nwhile(...) {+ ++ :Break ++ +} while(...) {- -- :Break -- -} continue+ и continue- - В начало цикла: while(...) {+ ++ :Continue ++ +} while(...) {- -- :Continue -- -} obj { .field = 1; .prop(); };\n#Python\n1) without using with statement file = open(‘file_path’, ‘w’) file.write(‘hello world !’) file.close()\n2) without using with statement file = open(‘file_path’, ‘w’) try: file.write(‘hello world’) finally: file.close()\nopen(‘file_path’, ‘w’) { .write(‘hello world !’); .close(); }\nPython3\nusing with statement with open(‘file_path’, ‘w’) as file: file.write(‘hello world !’)\na simple file writer object class MessageWriter(object): def init(self, file_name): self.file_name = file_name\ndef __enter__(self): self.file = open(self.file_name, 'w') return self.file def __exit__(self, *args): self.file.close() using with statement with MessageWriter with MessageWriter(‘my_file.txt’) as xfile: xfile.write(‘hello world’)\na simple file writer object :MessageWriter { def init(self, file_name): self.file_name = file_name\ndef __enter__(self): self.file = open(self.file_name, 'w') return self.file def __exit__(self, *args): self.file.close() }\nusing with statement with MessageWriter MessageWriter(‘my_file.txt’) { .write(‘hello world’); };\nfrom contextlib import contextmanager\nclass MessageWriter(object): def init(self, filename): self.file_name = filename\n@contextmanager def open_file(self): try: file = open(self.file_name, 'w') yield file finally: file.close() usage message_writer = MessageWriter(‘hello.txt’) with message_writer.open_file() as my_file: my_file.write(‘hello world’)\n:MessageWriter(object) { def init(self, filename): self.file_name = filename\n@contextmanager def open_file(self): try: file = open(self.file_name, 'w') yield file finally: file.close() }\nusage message_writer = MessageWriter(‘hello.txt’) with message_writer.open_file() as my_file: my_file.write(‘hello world’)\nПриложения Предопределенные макросы При работе парсера NewLang автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. Данные предопределенные макросы можно использовать как обычные константы.\n__FILE__ или __FILE_NAME__ - имя и полный путь текущего файла\n__LINE__ или __FILE_LINE__ - содержит номер текущей строки в файле\n__FILE_TIMESTAMP__ - дату и время последней модификации текущего файла в строковом представлении\n__FILE_MD5__ - md5 хеш текущего файла в строковом виде\n__COUNTER__ - целочисленный счетчик, который увеличивает свое значение при каждом обращении\n__DATE__ - дата начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIME__ - время начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIMESTAMP__ - дату и время начала запуска компилятора (например: “Fri 19 Aug 13:32:58 2016”)\n__TIMESTAMP_ISO__ - дату и время начала запуска компилятора в формате ISO (например: “2013-07-06T00:50:06Z”)\n__NLC_VER__ - Страшая и младшая версия компилятора NewLang (8 битное число, по 4 бита на цифру)\n__NLC_DATE_BUILD__ - текстовая строка с датой сборки компилятора NewLang (например, “23.06.04 20:51:39”)\n__NLC_SOURCE_GIT__ - текстовая строка с идентификатором исходных файлов NewLang git репозитория, использованных при сборке компилятора (например, “v0.3.0-fef8c371”)\n__NLC_SOURCE_BUILD__ - дата сборки и git идентификатор исходных файлов NewLang одной текстовой строкой (например, “v0.3.0-fef8c371 23.06.04 20:51:39”)\n","categories":"","description":"","excerpt":"Системные свойства Несмотря на то, что не все объекты NewLang являются …","ref":"/ru/docs/syntax/sysprop/","tags":"","title":"Системные свойства"},{"body":"В качестве оператора проверки условия используется синтаксическая конструкция, которая соответствует по смыслу термину «следует», т.е. два тире и угловая скобка --\u003e. Такая запись условного оператора очень похожа на математическую и легко объединяется в последовательности для проверки множественных условий вида «else if».\nВ общем случае условный оператор имеет вид: [ условие ] --\u003e { действие }; или с условием иначе [ условие ] --\u003e { действие }, […] --\u003e { действие иначе };\nДля наглядности записанный с отступами:\n[ условие1 ] --\u003e { действие1 }, [ условие2 ] --\u003e действие2, [ условие3 ] --\u003e действие3, [...] --\u003e {действие_иначе}; Или тоже самое, но с использованием макросов DSL.:\n@if( условие1 ) { действие1 } @elif( условие2 ) действие2 @elif( условие3 ) действие3 @else { действие_иначе }; ","categories":"","description":"","excerpt":"В качестве оператора проверки условия используется синтаксическая …","ref":"/docs/ops/if/","tags":"","title":"Условный оператор"},{"body":"В качестве оператора проверки условия используется синтаксическая конструкция, которая соответствует по смыслу термину «следует», т.е. два тире и угловая скобка --\u003e. Такая запись условного оператора очень похожа на математическую и легко объединяется в последовательности для проверки множественных условий вида «else if».\nВ общем случае условный оператор имеет вид: [ условие ] --\u003e { действие }; или с условием иначе [ условие ] --\u003e { действие }, […] --\u003e { действие иначе };\nДля наглядности записанный с отступами:\n[ условие1 ] --\u003e { действие1 }, [ условие2 ] --\u003e действие2, [ условие3 ] --\u003e действие3, [...] --\u003e {действие_иначе}; Или тоже самое, но с использованием макросов DSL.:\n@if( условие1 ) { действие1 } @elif( условие2 ) действие2 @elif( условие3 ) действие3 @else { действие_иначе }; ","categories":"","description":"","excerpt":"В качестве оператора проверки условия используется синтаксическая …","ref":"/ru/docs/ops/if/","tags":"","title":"Условный оператор"},{"body":"Прагмы Предварительное объевления объектов @__PRAGMA_DECLARE__\n@__PRAGMA_DECLARE__( func(arg) ); Импорт нативной функции / переменной @__PRAGMA_NATIVE__\n// import native int printf(char *format, ...) @__PRAGMA_NATIVE__( printf(format:FmtChar, ...):Int32 ); Управление диагностикой компилятора @__PRAGMA_DIAG__ -\n@__PRAGMA_DIAG__(push) @__PRAGMA_DIAG__(ignored, \"-Wundef\") @__PRAGMA_DIAG__(warning, \"-Wformat\" , \"-Wundef\", \"-Wuninitialized\") @__PRAGMA_DIAG__(error, \"-Wuninitialized\") @__PRAGMA_DIAG__(pop) @__PRAGMA_MESSAGE__\n#pragma message \"Compiling \" __FILE__ \"...\" @__PRAGMA_MESSAGE__(\"Compiling \", __FILE__, \"...\") #define DO_PRAGMA(x) _Pragma (#x) #define TODO(x) DO_PRAGMA(message (\"TODO - \" #x)) @@TODO( ... )@@ := @__PRAGMA_MESSAGE__(\"TODO - \", @#...) @TODO(Remember to fix this) # note: TODO - Remember to fix this @__PRAGMA_WARNING__ @__PRAGMA_ERROR__\n@__PRAGMA_LOCATION__ // #line 303 \"location.hh\" // Prototype - @__PRAGMA_LOCATION__( pop ) // Prototype - @__PRAGMA_LOCATION__( push ) or @__PRAGMA_LOCATION__( push, 'filename') or @__PRAGMA_LOCATION__( push, 'filename', line) // Prototype - @__PRAGMA_LOCATION__( line ) or @__PRAGMA_LOCATION__( line, 'filename') Управление макросами @__PRAGMA_EXPECTED__ - Следующий символ должен быть одним из списка\n@__PRAGMA_EXPECTED__( @\\ {, @\\ {*, @\\ {+ ) { } @__PRAGMA_EXPECTED__( @\\ {, @\\ {*, @\\ {+) {+ +} @__PRAGMA_UNEXPECTED__ - Запретить использование перечисленных символов\n@__PRAGMA_UNEXPECTED__( @\\{, @\\{*, @\\{+) {- -} @__PRAGMA_UNEXPECTED__( @\\{*, @\\{+) { } @__PRAGMA_NO_MACRO__ - Следующий символ не макрос\nАннотации @__ANNOTATION_SET__\n@__ANNOTATION_SET__(name) @__ANNOTATION_SET__(name, \"value\") @__ANNOTATION_SET__(name, 1) @__ANNOTATION_IIF__\nНе используется (заготовки на будущее) @__PRAGMA_IGNORE__\nstatic const char * ignore_space = \"space\"; static const char * ignore_indent = \"indent\"; static const char * ignore_comment = \"comment\"; static const char * ignore_crlf = \"crlf\"; @__PRAGMA_INDENT_BLOCK__\n@__PRAGMA_MACRO__ -\n@__PRAGMA_MACRO_COND__\n@__PRAGMA_FINALIZE__\n","categories":"","description":"","excerpt":"Прагмы Предварительное объевления объектов @__PRAGMA_DECLARE__ …","ref":"/docs/syntax/pragmas/","tags":"","title":"Опции и настройки компилятора"},{"body":"Прагмы Предварительное объевления объектов @__PRAGMA_DECLARE__\n@__PRAGMA_DECLARE__( func(arg) ); Импорт нативной функции / переменной @__PRAGMA_NATIVE__\n// import native int printf(char *format, ...) @__PRAGMA_NATIVE__( printf(format:FmtChar, ...):Int32 ); Управление диагностикой компилятора @__PRAGMA_DIAG__ -\n@__PRAGMA_DIAG__(push) @__PRAGMA_DIAG__(ignored, \"-Wundef\") @__PRAGMA_DIAG__(warning, \"-Wformat\" , \"-Wundef\", \"-Wuninitialized\") @__PRAGMA_DIAG__(error, \"-Wuninitialized\") @__PRAGMA_DIAG__(pop) @__PRAGMA_MESSAGE__\n#pragma message \"Compiling \" __FILE__ \"...\" @__PRAGMA_MESSAGE__(\"Compiling \", __FILE__, \"...\") #define DO_PRAGMA(x) _Pragma (#x) #define TODO(x) DO_PRAGMA(message (\"TODO - \" #x)) @@TODO( ... )@@ := @__PRAGMA_MESSAGE__(\"TODO - \", @#...) @TODO(Remember to fix this) # note: TODO - Remember to fix this @__PRAGMA_WARNING__ @__PRAGMA_ERROR__\n@__PRAGMA_LOCATION__ // #line 303 \"location.hh\" // Prototype - @__PRAGMA_LOCATION__( pop ) // Prototype - @__PRAGMA_LOCATION__( push ) or @__PRAGMA_LOCATION__( push, 'filename') or @__PRAGMA_LOCATION__( push, 'filename', line) // Prototype - @__PRAGMA_LOCATION__( line ) or @__PRAGMA_LOCATION__( line, 'filename') Управление макросами @__PRAGMA_EXPECTED__ - Следующий символ должен быть одним из списка\n@__PRAGMA_EXPECTED__( @\\ {, @\\ {*, @\\ {+ ) { } @__PRAGMA_EXPECTED__( @\\ {, @\\ {*, @\\ {+) {+ +} @__PRAGMA_UNEXPECTED__ - Запретить использование перечисленных символов\n@__PRAGMA_UNEXPECTED__( @\\{, @\\{*, @\\{+) {- -} @__PRAGMA_UNEXPECTED__( @\\{*, @\\{+) { } @__PRAGMA_NO_MACRO__ - Следующий символ не макрос\nАннотации @__ANNOTATION_SET__\n@__ANNOTATION_SET__(name) @__ANNOTATION_SET__(name, \"value\") @__ANNOTATION_SET__(name, 1) @__ANNOTATION_IIF__\nНе используется (заготовки на будущее) @__PRAGMA_IGNORE__\nstatic const char * ignore_space = \"space\"; static const char * ignore_indent = \"indent\"; static const char * ignore_comment = \"comment\"; static const char * ignore_crlf = \"crlf\"; @__PRAGMA_INDENT_BLOCK__\n@__PRAGMA_MACRO__ -\n@__PRAGMA_MACRO_COND__\n@__PRAGMA_FINALIZE__\n","categories":"","description":"","excerpt":"Прагмы Предварительное объевления объектов @__PRAGMA_DECLARE__ …","ref":"/ru/docs/syntax/pragmas/","tags":"","title":"Опции и настройки компилятора"},{"body":"DSL Особенности ассоциативной памяти Синтаксис языка NewLang основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например if, чем комбинация минус минус правая угловая скобка –\u003e. Из-за этого имеет смысл использовать не “чистый” базовый синтаксис, а более привычный диалект с использованием ключевых слов.\nСинтаксис на ключевых словах В файле dsl.nlp находится набор макросов, которые расширяют базовый синтаксис NewLang, основанный на правилах, набором предопределенных ключевых слов как в классических языках программирования. А при необходимости, их можно адаптировать или дополнить под собственную предметную область.\nКонстанты Логические true - 1 yes - 1 false - 0 no - 0 Системные имена this - Текущий объект ($0) parent - Родительский объект ($$) last - Результат выполнения последнего оператора ($^) !!!!!!!!- args - Все аргументы функции ($*)\n!!!!!!!!- sys - Системный контекст запущенной программы (@@) !!!!!!!!- current - Текущий модуль (@$) !!!!!!!!- cmd - Все аргументы выполняющегося приложения из командной строки (@*)\n!!!!!!!!!!1### Типовые функции и проверки !!!!!!!!!!- run(‘filename’) - Выполнить указанный файл (@@(‘filename’)) !!!!!!!!!!- ifmain - Проверка, если текущий модуль основной ([@$.$0] –\u003e { … }) !!!!!!!!!!- ifload - Проверка, если текущий модуль загружается впервые ([@$.load] –\u003e { … })\nОператоры match(cond) - Оператор оценки выражения\nif(…) - Первый условный оператор ([$*]–\u003e { … })\nelif(…) - Второй и все последующие (,[$*]–\u003e { … })\nelse - Оператор иначе (,[_]–\u003e { … })\nwhile(cond) - Оператор цикла с предусловием ([@$cond] \u003c-\u003e { … } )\ndowhile(cond) - Оператор цикла с постусловием ({ … } \u003c-\u003e[@$cond])\niter(obj, … ) - Создание итератора ( @$obj ? (@$*) )\nnext(obj, … ) - Следующий элемент итератора ( @$obj ! ($*) )\ncurr(obj, … ) - Текущий элемент итератора ( @$obj !? ($*) )\nfirst(obj) - Перейти на первый элемент итератора ( @$obj !! )\nall(obj) - Получить сразу все элементы итератора ( @$obj ??)\nПрерывания return - Положительное прерывание (++)\nreturn(…)- Положительное прерывание с возвратом значения (++ @$value ++)\nerror - Отрицательное прерывание (--)\nerror(…) - Отрицательное прерывание с возвратом значения (-- @$value --)\nbreak+ и break- - Выход из цикла:\nwhile(...) {+ ++ :Break ++ +} while(...) {- -- :Break -- -} continue+ и continue- - В начало цикла: while(...) {+ ++ :Continue ++ +} while(...) {- -- :Continue -- -} obj { .field = 1; .prop(); };\n#Python\n1) without using with statement file = open(‘file_path’, ‘w’) file.write(‘hello world !’) file.close()\n2) without using with statement file = open(‘file_path’, ‘w’) try: file.write(‘hello world’) finally: file.close()\nopen(‘file_path’, ‘w’) { .write(‘hello world !’); .close(); }\nPython3\nusing with statement with open(‘file_path’, ‘w’) as file: file.write(‘hello world !’)\na simple file writer object class MessageWriter(object): def init(self, file_name): self.file_name = file_name\ndef __enter__(self): self.file = open(self.file_name, 'w') return self.file def __exit__(self, *args): self.file.close() using with statement with MessageWriter with MessageWriter(‘my_file.txt’) as xfile: xfile.write(‘hello world’)\na simple file writer object :MessageWriter { def init(self, file_name): self.file_name = file_name\ndef __enter__(self): self.file = open(self.file_name, 'w') return self.file def __exit__(self, *args): self.file.close() }\nusing with statement with MessageWriter MessageWriter(‘my_file.txt’) { .write(‘hello world’); };\nfrom contextlib import contextmanager\nclass MessageWriter(object): def init(self, filename): self.file_name = filename\n@contextmanager def open_file(self): try: file = open(self.file_name, 'w') yield file finally: file.close() usage message_writer = MessageWriter(‘hello.txt’) with message_writer.open_file() as my_file: my_file.write(‘hello world’)\n:MessageWriter(object) { def init(self, filename): self.file_name = filename\n@contextmanager def open_file(self): try: file = open(self.file_name, 'w') yield file finally: file.close() }\nusage message_writer = MessageWriter(‘hello.txt’) with message_writer.open_file() as my_file: my_file.write(‘hello world’)\nПриложения Предопределенные макросы При работе парсера NewLang автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. Данные предопределенные макросы можно использовать как обычные константы.\n__FILE__ или __FILE_NAME__ - имя и полный путь текущего файла\n__LINE__ или __FILE_LINE__ - содержит номер текущей строки в файле\n__FILE_TIMESTAMP__ - дату и время последней модификации текущего файла в строковом представлении\n__FILE_MD5__ - md5 хеш текущего файла в строковом виде\n__COUNTER__ - целочисленный счетчик, который увеличивает свое значение при каждом обращении\n__DATE__ - дата начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIME__ - время начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIMESTAMP__ - дату и время начала запуска компилятора (например: “Fri 19 Aug 13:32:58 2016”)\n__TIMESTAMP_ISO__ - дату и время начала запуска компилятора в формате ISO (например: “2013-07-06T00:50:06Z”)\n__NLC_VER__ - Страшая и младшая версия компилятора NewLang (8 битное число, по 4 бита на цифру)\n__NLC_DATE_BUILD__ - текстовая строка с датой сборки компилятора NewLang (например, “23.06.04 20:51:39”)\n__NLC_SOURCE_GIT__ - текстовая строка с идентификатором исходных файлов NewLang git репозитория, использованных при сборке компилятора (например, “v0.3.0-fef8c371”)\n__NLC_SOURCE_BUILD__ - дата сборки и git идентификатор исходных файлов NewLang одной текстовой строкой (например, “v0.3.0-fef8c371 23.06.04 20:51:39”)\n","categories":"","description":"","excerpt":"DSL Особенности ассоциативной памяти Синтаксис языка NewLang основан …","ref":"/docs/syntax/sysmacro/","tags":"","title":"Системные макросы"},{"body":"DSL Особенности ассоциативной памяти Синтаксис языка NewLang основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например if, чем комбинация минус минус правая угловая скобка –\u003e. Из-за этого имеет смысл использовать не “чистый” базовый синтаксис, а более привычный диалект с использованием ключевых слов.\nСинтаксис на ключевых словах В файле dsl.nlp находится набор макросов, которые расширяют базовый синтаксис NewLang, основанный на правилах, набором предопределенных ключевых слов как в классических языках программирования. А при необходимости, их можно адаптировать или дополнить под собственную предметную область.\nКонстанты Логические true - 1 yes - 1 false - 0 no - 0 Системные имена this - Текущий объект ($0) parent - Родительский объект ($$) last - Результат выполнения последнего оператора ($^) !!!!!!!!- args - Все аргументы функции ($*)\n!!!!!!!!- sys - Системный контекст запущенной программы (@@) !!!!!!!!- current - Текущий модуль (@$) !!!!!!!!- cmd - Все аргументы выполняющегося приложения из командной строки (@*)\n!!!!!!!!!!1### Типовые функции и проверки !!!!!!!!!!- run(‘filename’) - Выполнить указанный файл (@@(‘filename’)) !!!!!!!!!!- ifmain - Проверка, если текущий модуль основной ([@$.$0] –\u003e { … }) !!!!!!!!!!- ifload - Проверка, если текущий модуль загружается впервые ([@$.load] –\u003e { … })\nОператоры match(cond) - Оператор оценки выражения\nif(…) - Первый условный оператор ([$*]–\u003e { … })\nelif(…) - Второй и все последующие (,[$*]–\u003e { … })\nelse - Оператор иначе (,[_]–\u003e { … })\nwhile(cond) - Оператор цикла с предусловием ([@$cond] \u003c-\u003e { … } )\ndowhile(cond) - Оператор цикла с постусловием ({ … } \u003c-\u003e[@$cond])\niter(obj, … ) - Создание итератора ( @$obj ? (@$*) )\nnext(obj, … ) - Следующий элемент итератора ( @$obj ! ($*) )\ncurr(obj, … ) - Текущий элемент итератора ( @$obj !? ($*) )\nfirst(obj) - Перейти на первый элемент итератора ( @$obj !! )\nall(obj) - Получить сразу все элементы итератора ( @$obj ??)\nПрерывания return - Положительное прерывание (++)\nreturn(…)- Положительное прерывание с возвратом значения (++ @$value ++)\nerror - Отрицательное прерывание (--)\nerror(…) - Отрицательное прерывание с возвратом значения (-- @$value --)\nbreak+ и break- - Выход из цикла:\nwhile(...) {+ ++ :Break ++ +} while(...) {- -- :Break -- -} continue+ и continue- - В начало цикла: while(...) {+ ++ :Continue ++ +} while(...) {- -- :Continue -- -} obj { .field = 1; .prop(); };\n#Python\n1) without using with statement file = open(‘file_path’, ‘w’) file.write(‘hello world !’) file.close()\n2) without using with statement file = open(‘file_path’, ‘w’) try: file.write(‘hello world’) finally: file.close()\nopen(‘file_path’, ‘w’) { .write(‘hello world !’); .close(); }\nPython3\nusing with statement with open(‘file_path’, ‘w’) as file: file.write(‘hello world !’)\na simple file writer object class MessageWriter(object): def init(self, file_name): self.file_name = file_name\ndef __enter__(self): self.file = open(self.file_name, 'w') return self.file def __exit__(self, *args): self.file.close() using with statement with MessageWriter with MessageWriter(‘my_file.txt’) as xfile: xfile.write(‘hello world’)\na simple file writer object :MessageWriter { def init(self, file_name): self.file_name = file_name\ndef __enter__(self): self.file = open(self.file_name, 'w') return self.file def __exit__(self, *args): self.file.close() }\nusing with statement with MessageWriter MessageWriter(‘my_file.txt’) { .write(‘hello world’); };\nfrom contextlib import contextmanager\nclass MessageWriter(object): def init(self, filename): self.file_name = filename\n@contextmanager def open_file(self): try: file = open(self.file_name, 'w') yield file finally: file.close() usage message_writer = MessageWriter(‘hello.txt’) with message_writer.open_file() as my_file: my_file.write(‘hello world’)\n:MessageWriter(object) { def init(self, filename): self.file_name = filename\n@contextmanager def open_file(self): try: file = open(self.file_name, 'w') yield file finally: file.close() }\nusage message_writer = MessageWriter(‘hello.txt’) with message_writer.open_file() as my_file: my_file.write(‘hello world’)\nПриложения Предопределенные макросы При работе парсера NewLang автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. Данные предопределенные макросы можно использовать как обычные константы.\n__FILE__ или __FILE_NAME__ - имя и полный путь текущего файла\n__LINE__ или __FILE_LINE__ - содержит номер текущей строки в файле\n__FILE_TIMESTAMP__ - дату и время последней модификации текущего файла в строковом представлении\n__FILE_MD5__ - md5 хеш текущего файла в строковом виде\n__COUNTER__ - целочисленный счетчик, который увеличивает свое значение при каждом обращении\n__DATE__ - дата начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIME__ - время начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIMESTAMP__ - дату и время начала запуска компилятора (например: “Fri 19 Aug 13:32:58 2016”)\n__TIMESTAMP_ISO__ - дату и время начала запуска компилятора в формате ISO (например: “2013-07-06T00:50:06Z”)\n__NLC_VER__ - Страшая и младшая версия компилятора NewLang (8 битное число, по 4 бита на цифру)\n__NLC_DATE_BUILD__ - текстовая строка с датой сборки компилятора NewLang (например, “23.06.04 20:51:39”)\n__NLC_SOURCE_GIT__ - текстовая строка с идентификатором исходных файлов NewLang git репозитория, использованных при сборке компилятора (например, “v0.3.0-fef8c371”)\n__NLC_SOURCE_BUILD__ - дата сборки и git идентификатор исходных файлов NewLang одной текстовой строкой (например, “v0.3.0-fef8c371 23.06.04 20:51:39”)\n","categories":"","description":"","excerpt":"DSL Особенности ассоциативной памяти Синтаксис языка NewLang основан …","ref":"/ru/docs/syntax/sysmacro/","tags":"","title":"Системные макросы"},{"body":"DSL Features of associative memory The syntax of the NewLang language is based on strict rules without the use of keywords, and no matter how logical it may seem, association by keywords is much easier to remember, for example, if, than the combination minus minus right angle bracket –\u003e. Because of this, it makes sense to use not a “pure” basic syntax, but a more familiar dialect with the use of keywords.\nSyntax based on keywords In the dsl.nlp file, there is a set of macros that expand the basic syntax of NewLang, based on rules, with a set of predefined keywords as in classical programming languages. And if necessary, they can be adapted or supplemented for your own domain.\nКонстанты Логические true - 1 yes - 1 false - 0 no - 0 Системные имена this - Текущий объект ($0) parent - Родительский объект ($$) last - Результат выполнения последнего оператора ($^) !!!!!!!!- args - Все аргументы функции ($*)\n!!!!!!!!- sys - Системный контекст запущенной программы (@@) !!!!!!!!- current - Текущий модуль (@$) !!!!!!!!- cmd - Все аргументы выполняющегося приложения из командной строки (@*)\n!!!!!!!!!!1### Типовые функции и проверки !!!!!!!!!!- run(‘filename’) - Выполнить указанный файл (@@(‘filename’)) !!!!!!!!!!- ifmain - Проверка, если текущий модуль основной ([@$.$0] –\u003e { … }) !!!!!!!!!!- ifload - Проверка, если текущий модуль загружается впервые ([@$.load] –\u003e { … })\nОператоры match(cond) - Оператор оценки выражения\nif(…) - Первый условный оператор ([$*]–\u003e { … })\nelif(…) - Второй и все последующие (,[$*]–\u003e { … })\nelse - Оператор иначе (,[_]–\u003e { … })\nwhile(cond) - Оператор цикла с предусловием ([@$cond] \u003c-\u003e { … } )\ndowhile(cond) - Оператор цикла с постусловием ({ … } \u003c-\u003e[@$cond])\niter(obj, … ) - Создание итератора ( @$obj ? (@$*) )\nnext(obj, … ) - Следующий элемент итератора ( @$obj ! ($*) )\ncurr(obj, … ) - Текущий элемент итератора ( @$obj !? ($*) )\nfirst(obj) - Перейти на первый элемент итератора ( @$obj !! )\nall(obj) - Получить сразу все элементы итератора ( @$obj ??)\nПрерывания return - Положительное прерывание (++)\nreturn(…)- Положительное прерывание с возвратом значения (++ @$value ++)\nerror - Отрицательное прерывание (--)\nerror(…) - Отрицательное прерывание с возвратом значения (-- @$value --)\nbreak+ и break- - Выход из цикла:\nwhile(...) {+ ++ :Break ++ +} while(...) {- -- :Break -- -} continue+ и continue- - В начало цикла: while(...) {+ ++ :Continue ++ +} while(...) {- -- :Continue -- -} obj { .field = 1; .prop(); };\n#Python\n1) without using with statement file = open(‘file_path’, ‘w’) file.write(‘hello world !’) file.close()\n2) without using with statement file = open(‘file_path’, ‘w’) try: file.write(‘hello world’) finally: file.close()\nopen(‘file_path’, ‘w’) { .write(‘hello world !’); .close(); }\nPython3\nusing with statement with open(‘file_path’, ‘w’) as file: file.write(‘hello world !’)\na simple file writer object class MessageWriter(object): def init(self, file_name): self.file_name = file_name\ndef __enter__(self): self.file = open(self.file_name, 'w') return self.file def __exit__(self, *args): self.file.close() using with statement with MessageWriter with MessageWriter(‘my_file.txt’) as xfile: xfile.write(‘hello world’)\na simple file writer object :MessageWriter { def init(self, file_name): self.file_name = file_name\ndef __enter__(self): self.file = open(self.file_name, 'w') return self.file def __exit__(self, *args): self.file.close() }\nusing with statement with MessageWriter MessageWriter(‘my_file.txt’) { .write(‘hello world’); };\nfrom contextlib import contextmanager\nclass MessageWriter(object): def init(self, filename): self.file_name = filename\n@contextmanager def open_file(self): try: file = open(self.file_name, 'w') yield file finally: file.close() usage message_writer = MessageWriter(‘hello.txt’) with message_writer.open_file() as my_file: my_file.write(‘hello world’)\n:MessageWriter(object) { def init(self, filename): self.file_name = filename\n@contextmanager def open_file(self): try: file = open(self.file_name, 'w') yield file finally: file.close() }\nusage message_writer = MessageWriter(‘hello.txt’) with message_writer.open_file() as my_file: my_file.write(‘hello world’)\nПриложения Предопределенные макросы При работе парсера NewLang автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. Данные предопределенные макросы можно использовать как обычные константы.\n__FILE__ или __FILE_NAME__ - имя и полный путь текущего файла\n__LINE__ или __FILE_LINE__ - содержит номер текущей строки в файле\n__FILE_TIMESTAMP__ - дату и время последней модификации текущего файла в строковом представлении\n__FILE_MD5__ - md5 хеш текущего файла в строковом виде\n__COUNTER__ - целочисленный счетчик, который увеличивает свое значение при каждом обращении\n__DATE__ - дата начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIME__ - время начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIMESTAMP__ - дату и время начала запуска компилятора (например: “Fri 19 Aug 13:32:58 2016”)\n__TIMESTAMP_ISO__ - дату и время начала запуска компилятора в формате ISO (например: “2013-07-06T00:50:06Z”)\n__NLC_VER__ - Страшая и младшая версия компилятора NewLang (8 битное число, по 4 бита на цифру)\n__NLC_DATE_BUILD__ - текстовая строка с датой сборки компилятора NewLang (например, “23.06.04 20:51:39”)\n__NLC_SOURCE_GIT__ - текстовая строка с идентификатором исходных файлов NewLang git репозитория, использованных при сборке компилятора (например, “v0.3.0-fef8c371”)\n__NLC_SOURCE_BUILD__ - дата сборки и git идентификатор исходных файлов NewLang одной текстовой строкой (например, “v0.3.0-fef8c371 23.06.04 20:51:39”)\n","categories":"","description":"","excerpt":"DSL Features of associative memory The syntax of the NewLang language …","ref":"/docs/syntax/dsl/","tags":"","title":"Keyword syntax (DSL)"},{"body":"DSL Особенности ассоциативной памяти Синтаксис языка NewLang основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например if, чем комбинация минус минус правая угловая скобка –\u003e. Из-за этого имеет смысл использовать не “чистый” базовый синтаксис, а более привычный диалект с использованием ключевых слов.\nСинтаксис на ключевых словах В файле dsl.nlp находится набор макросов, которые расширяют базовый синтаксис NewLang, основанный на правилах, набором предопределенных ключевых слов как в классических языках программирования. А при необходимости, их можно адаптировать или дополнить под собственную предметную область.\nКонстанты Логические true - 1 yes - 1 false - 0 no - 0 Системные имена this - Текущий объект ($0) parent - Родительский объект ($$) last - Результат выполнения последнего оператора ($^) !!!!!!!!- args - Все аргументы функции ($*)\n!!!!!!!!- sys - Системный контекст запущенной программы (@@) !!!!!!!!- current - Текущий модуль (@$) !!!!!!!!- cmd - Все аргументы выполняющегося приложения из командной строки (@*)\n!!!!!!!!!!1### Типовые функции и проверки !!!!!!!!!!- run(‘filename’) - Выполнить указанный файл (@@(‘filename’)) !!!!!!!!!!- ifmain - Проверка, если текущий модуль основной ([@$.$0] –\u003e { … }) !!!!!!!!!!- ifload - Проверка, если текущий модуль загружается впервые ([@$.load] –\u003e { … })\nОператоры match(cond) - Оператор оценки выражения\nif(…) - Первый условный оператор ([$*]–\u003e { … })\nelif(…) - Второй и все последующие (,[$*]–\u003e { … })\nelse - Оператор иначе (,[_]–\u003e { … })\nwhile(cond) - Оператор цикла с предусловием ([@$cond] \u003c-\u003e { … } )\ndowhile(cond) - Оператор цикла с постусловием ({ … } \u003c-\u003e[@$cond])\niter(obj, … ) - Создание итератора ( @$obj ? (@$*) )\nnext(obj, … ) - Следующий элемент итератора ( @$obj ! ($*) )\ncurr(obj, … ) - Текущий элемент итератора ( @$obj !? ($*) )\nfirst(obj) - Перейти на первый элемент итератора ( @$obj !! )\nall(obj) - Получить сразу все элементы итератора ( @$obj ??)\nПрерывания return - Положительное прерывание (++)\nreturn(…)- Положительное прерывание с возвратом значения (++ @$value ++)\nerror - Отрицательное прерывание (--)\nerror(…) - Отрицательное прерывание с возвратом значения (-- @$value --)\nbreak+ и break- - Выход из цикла:\nwhile(...) {+ ++ :Break ++ +} while(...) {- -- :Break -- -} continue+ и continue- - В начало цикла: while(...) {+ ++ :Continue ++ +} while(...) {- -- :Continue -- -} obj { .field = 1; .prop(); };\n#Python\n1) without using with statement file = open(‘file_path’, ‘w’) file.write(‘hello world !’) file.close()\n2) without using with statement file = open(‘file_path’, ‘w’) try: file.write(‘hello world’) finally: file.close()\nopen(‘file_path’, ‘w’) { .write(‘hello world !’); .close(); }\nPython3\nusing with statement with open(‘file_path’, ‘w’) as file: file.write(‘hello world !’)\na simple file writer object class MessageWriter(object): def init(self, file_name): self.file_name = file_name\ndef __enter__(self): self.file = open(self.file_name, 'w') return self.file def __exit__(self, *args): self.file.close() using with statement with MessageWriter with MessageWriter(‘my_file.txt’) as xfile: xfile.write(‘hello world’)\na simple file writer object :MessageWriter { def init(self, file_name): self.file_name = file_name\ndef __enter__(self): self.file = open(self.file_name, 'w') return self.file def __exit__(self, *args): self.file.close() }\nusing with statement with MessageWriter MessageWriter(‘my_file.txt’) { .write(‘hello world’); };\nfrom contextlib import contextmanager\nclass MessageWriter(object): def init(self, filename): self.file_name = filename\n@contextmanager def open_file(self): try: file = open(self.file_name, 'w') yield file finally: file.close() usage message_writer = MessageWriter(‘hello.txt’) with message_writer.open_file() as my_file: my_file.write(‘hello world’)\n:MessageWriter(object) { def init(self, filename): self.file_name = filename\n@contextmanager def open_file(self): try: file = open(self.file_name, 'w') yield file finally: file.close() }\nusage message_writer = MessageWriter(‘hello.txt’) with message_writer.open_file() as my_file: my_file.write(‘hello world’)\nПриложения Предопределенные макросы При работе парсера NewLang автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. Данные предопределенные макросы можно использовать как обычные константы.\n__FILE__ или __FILE_NAME__ - имя и полный путь текущего файла\n__LINE__ или __FILE_LINE__ - содержит номер текущей строки в файле\n__FILE_TIMESTAMP__ - дату и время последней модификации текущего файла в строковом представлении\n__FILE_MD5__ - md5 хеш текущего файла в строковом виде\n__COUNTER__ - целочисленный счетчик, который увеличивает свое значение при каждом обращении\n__DATE__ - дата начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIME__ - время начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIMESTAMP__ - дату и время начала запуска компилятора (например: “Fri 19 Aug 13:32:58 2016”)\n__TIMESTAMP_ISO__ - дату и время начала запуска компилятора в формате ISO (например: “2013-07-06T00:50:06Z”)\n__NLC_VER__ - Страшая и младшая версия компилятора NewLang (8 битное число, по 4 бита на цифру)\n__NLC_DATE_BUILD__ - текстовая строка с датой сборки компилятора NewLang (например, “23.06.04 20:51:39”)\n__NLC_SOURCE_GIT__ - текстовая строка с идентификатором исходных файлов NewLang git репозитория, использованных при сборке компилятора (например, “v0.3.0-fef8c371”)\n__NLC_SOURCE_BUILD__ - дата сборки и git идентификатор исходных файлов NewLang одной текстовой строкой (например, “v0.3.0-fef8c371 23.06.04 20:51:39”)\n","categories":"","description":"","excerpt":"DSL Особенности ассоциативной памяти Синтаксис языка NewLang основан …","ref":"/ru/docs/syntax/dsl/","tags":"","title":"Keyword syntax (DSL)"},{"body":"Синтаксическая конструкция с помощью которой реализуется примерный аналог оператора switch или match выглядит следующим образом:\n[ $var ] ==\u003e { [1] --\u003e { code }; # Выполнится проверка условия $var == 1 [1, 2] --\u003e { code }; # Выполнится проверка условия ($var == 1 || $var == 2) [...] --\u003e { code default }; # Ветка условия иначе }; Или тоже самое, но с использованием макросов из модуля dsl:\n@match( $var ) ==\u003e { @case( 1 ) { code }; @case( 1, 2 ) { code }; @default { code default }; }; Этот оператор очень похож на Pattern Matching, но все же не является сопоставлением с образцом, а скорее более краткая запись множественного оператора сравнения, так как в качестве оператора для оценки могут быть использован любые имеющиеся операторы сравнения на равенство:\n==\u003e — проверка на равенство с приведением типов; ===\u003e — проверка на точное равенство; ~\u003e — проверка типа (имени класса); ~~\u003e — утиная типизация; ~~~\u003e — строгая утиная типизация. Но если в качестве оператора сравнения использовать оператор утиной типизации, то оценка выражения превращается в классический Pattern Matching:\n$value := (f1=1, f2=\"2\",); @match( $value ) ~~\u003e { @case((f1=_, ), (f1=_, f2=0, )) { ... code ... }; # Поле f2 отсутствует или число @case((f1=_, f2=\"\",), (f1=_, f2='',)) { ... code ... }; # Поле f2 строка @default { ... code default ... }; # Код по умолчанию }; ","categories":"","description":"","excerpt":"Синтаксическая конструкция с помощью которой реализуется примерный …","ref":"/docs/ops/match/","tags":"","title":"Оценка выражения"},{"body":"Синтаксическая конструкция с помощью которой реализуется примерный аналог оператора switch или match выглядит следующим образом:\n[ $var ] ==\u003e { [1] --\u003e { code }; # Выполнится проверка условия $var == 1 [1, 2] --\u003e { code }; # Выполнится проверка условия ($var == 1 || $var == 2) [...] --\u003e { code default }; # Ветка условия иначе }; Или тоже самое, но с использованием макросов из модуля dsl:\n@match( $var ) ==\u003e { @case( 1 ) { code }; @case( 1, 2 ) { code }; @default { code default }; }; Этот оператор очень похож на Pattern Matching, но все же не является сопоставлением с образцом, а скорее более краткая запись множественного оператора сравнения, так как в качестве оператора для оценки могут быть использован любые имеющиеся операторы сравнения на равенство:\n==\u003e — проверка на равенство с приведением типов; ===\u003e — проверка на точное равенство; ~\u003e — проверка типа (имени класса); ~~\u003e — утиная типизация; ~~~\u003e — строгая утиная типизация. Но если в качестве оператора сравнения использовать оператор утиной типизации, то оценка выражения превращается в классический Pattern Matching:\n$value := (f1=1, f2=\"2\",); @match( $value ) ~~\u003e { @case((f1=_, ), (f1=_, f2=0, )) { ... code ... }; # Поле f2 отсутствует или число @case((f1=_, f2=\"\",), (f1=_, f2='',)) { ... code ... }; # Поле f2 строка @default { ... code default ... }; # Код по умолчанию }; ","categories":"","description":"","excerpt":"Синтаксическая конструкция с помощью которой реализуется примерный …","ref":"/ru/docs/ops/match/","tags":"","title":"Оценка выражения"},{"body":"Для записи циклов используются оператор \u003c-\u003e, который ставится между условием цикла (проверкой логического выражения) и телом цикла. Условие цикла записывается в квадратных скобках и в зависимости от взаимного расположения цикл может быть с предусловием (while) или постусловием (dowhile):\n[условие while] \u003c-\u003e { тело цикла while }; { тело цикла do while } \u003c-\u003e [условие do while]; Цикл с предусловием (while) поддерживает конструкцию else, которая выполняется, если условие входа в цикл не было выполнено.\nВнимание! Это поведение отличается от аналогичных конструкций в языке Python, у которого секция else выполняется всегда, кроме прерывания цикла по break.\nВетка else у оператора цикла записывается так же как и ветка иначе в условном операторе, т.е.\n[ cond ] \u003c-\u003e { ... },[...] --\u003e { ... }; Или тоже самое, но с использованием макросов из модуля dsl:\n@while(cond) { ... } @else { ... # Выполнится, только если cond будет false при входе в цикл }; Пример реализации цикла foreach для суммирования всех элементов словаря (или одномерного тензора) с использованием оператора раскрытия списка:\nsumma := 0; dict := (1,2,3,4,5,); [ dict ] \u003c-\u003e { # Условие цикла, пока есть данные # Результат оператора распаковка словаря - первый элемент перемещается в item item, dict := ... dict; summa += item; # Вычисление суммы всех элементов словаря }; ","categories":"","description":"","excerpt":"Для записи циклов используются оператор \u003c-\u003e, который ставится между …","ref":"/docs/ops/while/","tags":"","title":"Операторы циклов"},{"body":"Для записи циклов используются оператор \u003c-\u003e, который ставится между условием цикла (проверкой логического выражения) и телом цикла. Условие цикла записывается в квадратных скобках и в зависимости от взаимного расположения цикл может быть с предусловием (while) или постусловием (dowhile):\n[условие while] \u003c-\u003e { тело цикла while }; { тело цикла do while } \u003c-\u003e [условие do while]; Цикл с предусловием (while) поддерживает конструкцию else, которая выполняется, если условие входа в цикл не было выполнено.\nВнимание! Это поведение отличается от аналогичных конструкций в языке Python, у которого секция else выполняется всегда, кроме прерывания цикла по break.\nВетка else у оператора цикла записывается так же как и ветка иначе в условном операторе, т.е.\n[ cond ] \u003c-\u003e { ... },[...] --\u003e { ... }; Или тоже самое, но с использованием макросов из модуля dsl:\n@while(cond) { ... } @else { ... # Выполнится, только если cond будет false при входе в цикл }; Пример реализации цикла foreach для суммирования всех элементов словаря (или одномерного тензора) с использованием оператора раскрытия списка:\nsumma := 0; dict := (1,2,3,4,5,); [ dict ] \u003c-\u003e { # Условие цикла, пока есть данные # Результат оператора распаковка словаря - первый элемент перемещается в item item, dict := ... dict; summa += item; # Вычисление суммы всех элементов словаря }; ","categories":"","description":"","excerpt":"Для записи циклов используются оператор \u003c-\u003e, который ставится между …","ref":"/ru/docs/ops/while/","tags":"","title":"Операторы циклов"},{"body":"Одиночный оператор захвата ссылки и синхронизации доступа к объекту ‘*’ или ‘*(…)’ выполняется только для одной переменной при использовании в одном действии. Но захват ссылки и объекта синхронизации, это относительно медленная операция и выполнять её для каждого действия над переменной не рационально.\nДля того, чтобы захватить одновременно сразу несколько объектов синхронизации для выполнения группы последовательных действий используется менеджер контекста.\n**( val1 = *ref1, val2 = *ref2, __timeout__ = 10000 ){ ... }; **( ... ){ ... } , [...] { # Ветка else при ошибке захвата ссылки # Информация об ошибке в переменной $^ ... }; Или таже самая запись с использованием макросов DSL:\n@with( val1 = *ref1, val2 = *ref2, __timeout__ = 10000 ){ ... }; @with( ... ){ ... } @else { # Ветка else при ошибке захвата ссылки # Информация об ошибке в переменной $^ ... }; Захват легких ссылок совместного доступа При захвате обычной легкой ссылки всегда сравнивается идентификатор текущего потока с идентифкатором потока - владельца объекта. Использование обычных легких ссылок допускается только в рамках одного потока - владельца объекта.\nЧтобы можно было использовать ссылки на легкие объекты в других потоках, для них требуется создать легкие ссылки для совместного доступа (\"\u0026?\").\nЗахват легких ссылок для совместного доступа возможен только с помощью оператора группового захвата, при условии, что как миниму одна из первых ссылок будет тяжелой. т.е. с реализованным объектом синхронизации.\nПример реализации критической секции с помощью оператора группового захвата @with и статической переменной @::sync в качестве флага блокировки доступа:\n# Функция для вызова в разных потоках show( \u0026? win1, \u0026? win2) := { \u0026\u0026 @::sync := @false; # Global (static) synchronization object @with (*sync, w1 = *win1, w2 = *win2){ ... # Критическая секция } } Расширенный синтаксис определения ссылок При определении переменной, у которой допускается создание ссылок и синхронизация доступа, можно указать дополнительные параметры работы. Это делается с помощью указания системных параметров в типе разрешенных ссылок при определении объекта.\nУсловный пример:\n\u0026\u0026 sync; # Объект синхронизации \u0026\u0026(__timeout__=1000) sync_other; # Объект синхронизации c таймаутом на блокировку with(*sync_other) { # Блокировка с таймаутом ... } # Переменная value с конкретным объектом синхроинзации \u0026?(sync) value := 123; with(*sync, lock = *value) { # ОК ... } with(*sync_other, val = *value) { # Ошибка компиляции # для синхронизации должен использоваться sync ... } Автоматическое освобождение ресурсов Менеджер контекста, кроме захвата слабых ссылок в локальные переменные и блокировки доступа, одновременно с этим позволяет выделять и освобождать ресурсы, автоматически вызывая декструктор локального объекта при выходе из блока кода оператора.\nОсвобождение ресурсов (вызов деструктора у объекта) происходит до попадания в ветку else, если она присутствует.\nСамый популярный пример использования менеджера контекста - связанные операции открытия, чтения/записи и закрытия файла в одном блоке кода.\nНапример:\n# Фрагмент определения класса File File(name, mode) := :Class() { .file ::= fopen($name, $mode); # Handle file ~File() := { # Destructor of class @if(@this.file){ fclose(@this.file); @this.file := _; } } ... }; @with( file = :File('some_file', 'w') ) { file.write('Oppa!'); }; Код выше открывает файл, записывает в него данные и закрывает файл при выходе из блока кода.\nЭтот код эквивалентен следующему на Python:\nwith open('some_file', 'w') as file: file.write('Oppa!') # Или без менеджера контекста file = open('some_file', 'w') try: file.write('Oppa!') finally: file.close() Более сложный пример чтение файла с одновремнным захватом ссылки на буфер и обработкой ошибок:\n@with( file = :File('some_file', 'r'), buffer = *ref_buffer ) { file.read(buffer); } @else { @match(@latter){ @case( :ErrorLock ) { /* Ошибка захвата ссылки ref_buffer */ }; @case( :ErrorOpenFile ) { /* Ошибка открытия для записи файла some_file */ }; @case( :ErrorReadWrite ) { /* Ошибка чтения-записи в файл some_file */ }; @default @forward; /* Остальные ошибки пробросить дальше */ }; }; Использование менеджера контекста - это гарантия закрытия файла и освобождения буфера вне зависимости от того, как будет завершён вложенный код. Распространенный паттерн использования контекстных менеджеров - блокирование и разблокирование ресурсов при многопоточном доступе к объетам, а также закрытие открытых файлов или освобождение захваченных ресурсов.\nprintf(format:FmtChar, ...):Int32 := %printf...; \u0026\u0026 holder: Integer[] = [,]; # Empty tensor Runnable(cnt:Integer) := { $i := 1; @while( $i \u003c= $cnt ) { *holder []= $i; # Lock and add new value $i += 1; @if( $i % ($cnt // 10) == 0) { @with(*holder){ # Lock only printf(\".\"); } } } } $count = 10000; thread1 = :Thread(Runnable, $count); thread2 = :Thread(Runnable, $count); thread3 = :Thread(Runnable, $count); thread4 = :Thread(Runnable, $count); thread5 = :Thread(Runnable, $count); thread1.start(); thread2.start(); thread3.start(); thread4.start(); thread5.start(); thread1.join(); thread2.join(); thread3.join(); thread4.join(); thread5.join(); @assert(*holder.size() == 5*$count); printf(\"Complete %d!\\n\", *holder.size()); Вывод:\n\u003e.................................................. \u003eComplete 50000! \u003e_ ","categories":"","description":"","excerpt":"Одиночный оператор захвата ссылки и синхронизации доступа к объекту …","ref":"/docs/ops/with/","tags":"","title":"Менеджер контекста"},{"body":"Одиночный оператор захвата ссылки и синхронизации доступа к объекту ‘*’ или ‘*(…)’ выполняется только для одной переменной при использовании в одном действии. Но захват ссылки и объекта синхронизации, это относительно медленная операция и выполнять её для каждого действия над переменной не рационально.\nДля того, чтобы захватить одновременно сразу несколько объектов синхронизации для выполнения группы последовательных действий используется менеджер контекста.\n**( val1 = *ref1, val2 = *ref2, __timeout__ = 10000 ){ ... }; **( ... ){ ... } , [...] { # Ветка else при ошибке захвата ссылки # Информация об ошибке в переменной $^ ... }; Или таже самая запись с использованием макросов DSL:\n@with( val1 = *ref1, val2 = *ref2, __timeout__ = 10000 ){ ... }; @with( ... ){ ... } @else { # Ветка else при ошибке захвата ссылки # Информация об ошибке в переменной $^ ... }; Захват легких ссылок совместного доступа При захвате обычной легкой ссылки всегда сравнивается идентификатор текущего потока с идентифкатором потока - владельца объекта. Использование обычных легких ссылок допускается только в рамках одного потока - владельца объекта.\nЧтобы можно было использовать ссылки на легкие объекты в других потоках, для них требуется создать легкие ссылки для совместного доступа (\"\u0026?\").\nЗахват легких ссылок для совместного доступа возможен только с помощью оператора группового захвата, при условии, что как миниму одна из первых ссылок будет тяжелой. т.е. с реализованным объектом синхронизации.\nПример реализации критической секции с помощью оператора группового захвата @with и статической переменной @::sync в качестве флага блокировки доступа:\n# Функция для вызова в разных потоках show( \u0026? win1, \u0026? win2) := { \u0026\u0026 @::sync := @false; # Global (static) synchronization object @with (*sync, w1 = *win1, w2 = *win2){ ... # Критическая секция } } Расширенный синтаксис определения ссылок При определении переменной, у которой допускается создание ссылок и синхронизация доступа, можно указать дополнительные параметры работы. Это делается с помощью указания системных параметров в типе разрешенных ссылок при определении объекта.\nУсловный пример:\n\u0026\u0026 sync; # Объект синхронизации \u0026\u0026(__timeout__=1000) sync_other; # Объект синхронизации c таймаутом на блокировку with(*sync_other) { # Блокировка с таймаутом ... } # Переменная value с конкретным объектом синхроинзации \u0026?(sync) value := 123; with(*sync, lock = *value) { # ОК ... } with(*sync_other, val = *value) { # Ошибка компиляции # для синхронизации должен использоваться sync ... } Автоматическое освобождение ресурсов Менеджер контекста, кроме захвата слабых ссылок в локальные переменные и блокировки доступа, одновременно с этим позволяет выделять и освобождать ресурсы, автоматически вызывая декструктор локального объекта при выходе из блока кода оператора.\nОсвобождение ресурсов (вызов деструктора у объекта) происходит до попадания в ветку else, если она присутствует.\nСамый популярный пример использования менеджера контекста - связанные операции открытия, чтения/записи и закрытия файла в одном блоке кода.\nНапример:\n# Фрагмент определения класса File File(name, mode) := :Class() { .file ::= fopen($name, $mode); # Handle file ~File() := { # Destructor of class @if(@this.file){ fclose(@this.file); @this.file := _; } } ... }; @with( file = :File('some_file', 'w') ) { file.write('Oppa!'); }; Код выше открывает файл, записывает в него данные и закрывает файл при выходе из блока кода.\nЭтот код эквивалентен следующему на Python:\nwith open('some_file', 'w') as file: file.write('Oppa!') # Или без менеджера контекста file = open('some_file', 'w') try: file.write('Oppa!') finally: file.close() Более сложный пример чтение файла с одновремнным захватом ссылки на буфер и обработкой ошибок:\n@with( file = :File('some_file', 'r'), buffer = *ref_buffer ) { file.read(buffer); } @else { @match(@latter){ @case( :ErrorLock ) { /* Ошибка захвата ссылки ref_buffer */ }; @case( :ErrorOpenFile ) { /* Ошибка открытия для записи файла some_file */ }; @case( :ErrorReadWrite ) { /* Ошибка чтения-записи в файл some_file */ }; @default @forward; /* Остальные ошибки пробросить дальше */ }; }; Использование менеджера контекста - это гарантия закрытия файла и освобождения буфера вне зависимости от того, как будет завершён вложенный код. Распространенный паттерн использования контекстных менеджеров - блокирование и разблокирование ресурсов при многопоточном доступе к объетам, а также закрытие открытых файлов или освобождение захваченных ресурсов.\nprintf(format:FmtChar, ...):Int32 := %printf...; \u0026\u0026 holder: Integer[] = [,]; # Empty tensor Runnable(cnt:Integer) := { $i := 1; @while( $i \u003c= $cnt ) { *holder []= $i; # Lock and add new value $i += 1; @if( $i % ($cnt // 10) == 0) { @with(*holder){ # Lock only printf(\".\"); } } } } $count = 10000; thread1 = :Thread(Runnable, $count); thread2 = :Thread(Runnable, $count); thread3 = :Thread(Runnable, $count); thread4 = :Thread(Runnable, $count); thread5 = :Thread(Runnable, $count); thread1.start(); thread2.start(); thread3.start(); thread4.start(); thread5.start(); thread1.join(); thread2.join(); thread3.join(); thread4.join(); thread5.join(); @assert(*holder.size() == 5*$count); printf(\"Complete %d!\\n\", *holder.size()); Вывод:\n\u003e.................................................. \u003eComplete 50000! \u003e_ ","categories":"","description":"","excerpt":"Одиночный оператор захвата ссылки и синхронизации доступа к объекту …","ref":"/ru/docs/ops/with/","tags":"","title":"Менеджер контекста"},{"body":"Последовательность команд (блок кода) можно прервать в любом месте с помощью специальных операторов.\nДля этого используются две разные команды, которые условно можно назвать положительным и отрицательным прерыванием потока выполнения, что примерно соответствует семантике их записи. “Отрицательное” прерывание записывается в виде двух минусов, а “положительное” прерывание в виде двух плюсов, т.е. -- или ++.\nОператор прерывания не возвращает никакого значения (точнее, возвращает пустое значение). Чтобы прерывание вернуло другое значение, возвращаемые данные нужно записать между парой соответствующих символов, т.е. -- 100 --, что является примерным аналогом оператора return 100; в других языках программирования, а ++‘Строка’++ - аналогом return 'Строка';.\nЛокальный переход Именованные блоки кода могут выступать в качестве локальных меток для передачи потока выполнения. Если перед оператором прерывания указать пространство имен, то оператор прерывания станет именованным и будет действовать только для указанного блока кода.\nВ этом случае отрицательное прерывание будет работать как оператор continue, передавая поток выполнения на первую инструкцию блока кода, а положительное прерывание как оператор break, выходя из него.\nЛокальная передача потока управления работает с именованными блоками кода, поэтому переход в начало блока кода или выход из него, возможны в том числе и изнутри нескольких вложенных именнованных блоков кода.\nb1 := 1; # Бесконечный цикл с именованным блоком кода [1] \u003c-\u003e outer_loop:: { # Именованный блок кода outer_loop b2 := 1; [1] \u003c-\u003e inner_loop { # Именованный блок кода inner_loop printf(\"Values: b1=%d, b2=%d\", b1, b2); # Проверка условий [b1 == 2 \u0026\u0026 b2 == 2] --\u003e { outer_loop:: ++; # Прерываем outer_loop }, [b2 == 5] --\u003e { inner_loop:: ++; # Прерываем inner_loop } b2 += 1; } b1 += 1; } Тоже самое с использованием макросов DSL.:\nb1 := 1; @loop outer_loop:: { # @while(@true) b2 := 1; @loop inner_loop { printf(\"Values: b1=%d, b2=%d\", b1, b2); @if( b1 == 2 @and b2 == 2) { @break outer_loop; } @elif( b2 == 5 ) { @break inner_loop; } b2 += 1; } b1 += 1; } Возврат результата Для возврата результата из тела функции используется положительное прерывание из блока кода, меткой которого является полное имя функции, включая текущую область имен. Имя блока кода тела функции соответствует её имени.\nns:: { # Пространство имен ns func_name(val):Int32 ::= { # Блок кода тела функции ns::func_name:: ... # Возврат из функции func_name ++ 0 ++; # Или @return(0); с ипользованием DSL :: ++ 0 ++; # Завершение программы? exit(0) :: -- ; # Прерывание выполенения программы? abort() }; }; Для оператора прерывания выполенения можно указать и глобальную область видимости. Тогда при выполнении такого прерывания происходит выход из самого верхнеуровневого блока кода, что приводит к завершение работы приложения.\nАналогом такого поведения являются функции exit() для положительного прерывания и abort() для отрицательного, что отражено в DSL.\nПерехват прерывааний Именованные прерывания потока выполнения можно использовать только внутри именованных блоков кода, что контроллируется во время компиляции программы на уровне исходного кода.\nДля не именованных прерываний такое ограничение отсуствует, поэтому более точным аналогом не именованного прерывания будет не return или break, а throw, т.к. эти операторы не только прерывают выполнение последовательности команд в любом блоке кода и возвращают результат, но их еще и можно “ловить”.\nДля перехвата не именованных прерываний используются блоки кода с соответствующей семантикой, {+ … +} - блок кода, который перехватывает положительные прерывания и {- … -} - блок кода, который перехватывает отрицательные прерывания, созданные операторами --, и блок кода {* … *}, который перехватывает сразу оба типа прерываний.\nНапример, возврат из нескольких вложенных функций без необходимости обрабатывать результат возврата в каждой из них. В этом примере функция Test перехватывает “положительные” прерывания из вложенных функций:\nLevel2(arg) := { if($arg==2) { ++ \"Level - 2\" ++; }; \"Level2 - DONE\"; }; Level1(arg) := { if($arg==1) { ++ \"Level - 1\" ++; }; Level2($arg); }; Test(arg) := {+ if($arg \u003e= 0) { Level1($arg); } $arg; +}; Test(2); # Вернет \"Level — 2\" возврат из вложенной функции Level2 Test(1); # Вернет \"Level — 1\" возврат из вложенной функции Level1 Test(0); # Вернет \"Level2 - DONE\" возврат из вложенной функции Level2 Test(-2); # Вернет -2 — возврат из функции Test Обработка ошибок Оба варианта прерываний равнозначны и “отрицательное” прерывание для возврата ошибки используется только условно. Блоки кода с перехватом прерываний, совместно с оператором оценки выражения, можно использовать для обработки исключений в классическом стиле.\n[ {* # Перехват всех исключений на базовом синтаксисе op1; op2; ... *} ] ~\u003e { # Сопоставление по типу возвращенного значения [:ErrorType1] --\u003e { code }; [:ErrorType2, :ErrorType3] --\u003e { code }; [...] --\u003e { code default }; }; # Семантика с применением DSL @try { op1; op2; ... } @catch (...) { # Перехват всех исключений @case(:Error){ ... }; @default @forward; }; # Тоже самое, только для заданных типов @try { op1; op2; ... } @catch (:Type, :Type2, :Type3) { @case(:Type){ ... }; @case(:Type2, :Type3){ ... }; @default @forward; }; Расширенные варинаты прерывания выполнения Добавить реализациию для короутин после их полной реализации в clang (скорее всего на уровне аннотаций)\n@@ coroutine @@ ::= @@ __ANNOTATION_SET__(coroutine) @@; @@ co_yield(...) @@ ::= @@ __ANNOTATION_CHECK__(coroutine) @__FUNC_BLOCK__ :: -- @$... -- @@ co_await @@ ::= @@ __ANNOTATION_CHECK__(coroutine) @__FUNC_BLOCK__ :: +- @@ co_return(...) @@ ::= @@ __ANNOTATION_CHECK__(coroutine) @__FUNC_BLOCK__ :: ++ @$... ++ ns { @coroutine co_func(val):Int32 ::= { # Блок кода тела функции ... # Возврат и приостановка выполнения функции @__FUNC_BLOCK__ :: -- 0 --; # ns::co_func:: -- 0 --; # Или @co_yield(0); с ипользованием DSL # Приостановить и вернуть управление @__FUNC_BLOCK__ :: +-; # ns::co_func:: +-; # Или @co_await; с ипользованием DSL # Возврат и завершение функции @__FUNC_BLOCK__ :: ++ 0 ++; # ns::co_func:: ++ 0 ++; # Или @co_return(0); с ипользованием DSL }; }; Выражение co_yield возвращает значение вызывающей стороне и приостанавливает текущую сопрограмму: это общий строительный блок возобновляемых функций-генераторов.\nco_await +-\nУнарный оператор co_await приостанавливает сопрограмму и возвращает управление вызывающей стороне. Его операнд представляет собой выражение, которое либо (1) относится к типу класса, определяющему оператор-член co_await, либо может быть передано оператору, не являющемуся членом co_await, либо (2) может быть преобразовано в такой тип класса с помощью текущей сопрограммы.\nauto request = await socket.read(...); auto result = await db_client.do_query(prepare_request(request)); await socket.write(prepare_result(result)); socket.close(); request := (){ socket.read(...) }; auto result = (){ request, db_client.do_query(prepare_request(request)) }; (){ socket.write(prepare_result(result)) }; socket.close(); ","categories":"","description":"","excerpt":"Последовательность команд (блок кода) можно прервать в любом месте с …","ref":"/docs/ops/throw/","tags":"","title":"Ввозврат, прерывания и обработка ошибок"},{"body":"Последовательность команд (блок кода) можно прервать в любом месте с помощью специальных операторов.\nДля этого используются две разные команды, которые условно можно назвать положительным и отрицательным прерыванием потока выполнения, что примерно соответствует семантике их записи. “Отрицательное” прерывание записывается в виде двух минусов, а “положительное” прерывание в виде двух плюсов, т.е. -- или ++.\nОператор прерывания не возвращает никакого значения (точнее, возвращает пустое значение). Чтобы прерывание вернуло другое значение, возвращаемые данные нужно записать между парой соответствующих символов, т.е. -- 100 --, что является примерным аналогом оператора return 100; в других языках программирования, а ++‘Строка’++ - аналогом return 'Строка';.\nЛокальный переход Именованные блоки кода могут выступать в качестве локальных меток для передачи потока выполнения. Если перед оператором прерывания указать пространство имен, то оператор прерывания станет именованным и будет действовать только для указанного блока кода.\nВ этом случае отрицательное прерывание будет работать как оператор continue, передавая поток выполнения на первую инструкцию блока кода, а положительное прерывание как оператор break, выходя из него.\nЛокальная передача потока управления работает с именованными блоками кода, поэтому переход в начало блока кода или выход из него, возможны в том числе и изнутри нескольких вложенных именнованных блоков кода.\nb1 := 1; # Бесконечный цикл с именованным блоком кода [1] \u003c-\u003e outer_loop:: { # Именованный блок кода outer_loop b2 := 1; [1] \u003c-\u003e inner_loop { # Именованный блок кода inner_loop printf(\"Values: b1=%d, b2=%d\", b1, b2); # Проверка условий [b1 == 2 \u0026\u0026 b2 == 2] --\u003e { outer_loop:: ++; # Прерываем outer_loop }, [b2 == 5] --\u003e { inner_loop:: ++; # Прерываем inner_loop } b2 += 1; } b1 += 1; } Тоже самое с использованием макросов DSL.:\nb1 := 1; @loop outer_loop:: { # @while(@true) b2 := 1; @loop inner_loop { printf(\"Values: b1=%d, b2=%d\", b1, b2); @if( b1 == 2 @and b2 == 2) { @break outer_loop; } @elif( b2 == 5 ) { @break inner_loop; } b2 += 1; } b1 += 1; } Возврат результата Для возврата результата из тела функции используется положительное прерывание из блока кода, меткой которого является полное имя функции, включая текущую область имен.\nИменованный блок кода при перехвате прерываний возвращают объект, который передавался с помощью прервывания, либо пусто, если возвращаемое значение отсуствует.\nИмя блока кода тела функции соответствует её имени.\nns:: { # Пространство имен ns func_name(val):Int32 ::= { # Блок кода тела функции ns::func_name:: ... # Возврат из функции func_name ++ 0 ++; # Или @return(0); с ипользованием DSL :: ++ 0 ++; # Завершение программы? exit(0) :: -- ; # Прерывание выполенения программы? abort() }; }; Для оператора прерывания выполенения можно указать и глобальную область видимости. Тогда при выполнении такого прерывания происходит выход из самого верхнеуровневого блока кода, что приводит к завершение работы приложения.\nАналогом такого поведения являются функции exit() для положительного прерывания и abort() для отрицательного, что отражено в DSL.\nПерехват прерывааний Именованные прерывания потока выполнения можно использовать только внутри именованных блоков кода, что контроллируется во время компиляции программы на уровне исходного кода.\nДля не именованных прерываний такое ограничение отсуствует, поэтому более точным аналогом не именованного прерывания будет не return или break, а throw, т.к. эти операторы не только прерывают выполнение последовательности команд в любом блоке кода и возвращают результат, но их еще и можно “ловить”.\nДля перехвата не именованных прерываний используются блоки кода с соответствующей семантикой, {+ … +} - блок кода, который перехватывает положительные прерывания и {- … -} - блок кода, который перехватывает отрицательные прерывания, созданные операторами --, и блок кода {* … *}, который перехватывает сразу оба типа прерываний.\nПринципиальное отличие блоков кода для перехвата прерываний от именованных блоков кода состоит в типе возвращаемого значения. Если именованные блоки кода возвращают значение, то при перехвате прервывания, возвращается непосредственно само прерывание, а не возращаемое с его помощью значение.\nНапример, возврат из нескольких вложенных функций без необходимости обрабатывать результат возврата в каждой из них. В этом примере функция Test перехватывает “положительные” прерывания из вложенных функций:\nLevel2(arg) := { if($arg==2) { ++ \"Level - 2\" ++; }; \"Level2 - DONE\"; }; Level1(arg) := { if($arg==1) { ++ \"Level - 1\" ++; }; Level2($arg); }; Test(arg) := * {+ if($arg \u003e= 0) { Level1($arg); } $arg; +}; Test(2); # Вернет \"Level — 2\" возврат из вложенной функции Level2 Test(1); # Вернет \"Level — 1\" возврат из вложенной функции Level1 Test(0); # Вернет \"Level2 - DONE\" возврат из вложенной функции Level2 Test(-2); # Вернет -2 — возврат из функции Test Обработка ошибок Оба варианта прерываний равнозначны и “отрицательное” прерывание для возврата ошибки используется только условно. Блоки кода с перехватом прерываний, совместно с оператором оценки выражения, можно использовать для обработки исключений в классическом стиле.\n[ {* # Перехват всех исключений на базовом синтаксисе op1; op2; ... *} ] ~\u003e { # Сопоставление по типу возвращенного значения [:ErrorType1] --\u003e { code }; [:ErrorType2, :ErrorType3] --\u003e { code }; [...] --\u003e { code default }; }; # Семантика с применением DSL @try { op1; op2; ... } @catch (...) { # Перехват всех исключений @case(:Error){ ... }; @default @forward; }; # Тоже самое, только для заданных типов @try { op1; op2; ... } @catch (:Type, :Type2, :Type3) { @case(:Type){ ... }; @case(:Type2, :Type3){ ... }; @default @forward; }; Расширенные варинаты прерывания выполнения Добавить реализациию для короутин после их полной реализации в clang (скорее всего на уровне аннотаций)\n@@ coroutine @@ ::= @@ __ANNOTATION_SET__(coroutine) @@; @@ co_yield(...) @@ ::= @@ __ANNOTATION_CHECK__(coroutine) @__FUNC_BLOCK__ :: -- @$... -- @@ co_await @@ ::= @@ __ANNOTATION_CHECK__(coroutine) @__FUNC_BLOCK__ :: +- @@ co_return(...) @@ ::= @@ __ANNOTATION_CHECK__(coroutine) @__FUNC_BLOCK__ :: ++ @$... ++ ns { @coroutine co_func(val):Int32 ::= { # Блок кода тела функции ... # Возврат и приостановка выполнения функции @__FUNC_BLOCK__ :: -- 0 --; # ns::co_func:: -- 0 --; # Или @co_yield(0); с ипользованием DSL # Приостановить и вернуть управление @__FUNC_BLOCK__ :: +-; # ns::co_func:: +-; # Или @co_await; с ипользованием DSL # Возврат и завершение функции @__FUNC_BLOCK__ :: ++ 0 ++; # ns::co_func:: ++ 0 ++; # Или @co_return(0); с ипользованием DSL }; }; Выражение co_yield возвращает значение вызывающей стороне и приостанавливает текущую сопрограмму: это общий строительный блок возобновляемых функций-генераторов.\nco_await +-\nУнарный оператор co_await приостанавливает сопрограмму и возвращает управление вызывающей стороне. Его операнд представляет собой выражение, которое либо (1) относится к типу класса, определяющему оператор-член co_await, либо может быть передано оператору, не являющемуся членом co_await, либо (2) может быть преобразовано в такой тип класса с помощью текущей сопрограммы.\nauto request = await socket.read(...); auto result = await db_client.do_query(prepare_request(request)); await socket.write(prepare_result(result)); socket.close(); request := (){ socket.read(...) }; auto result = (){ request, db_client.do_query(prepare_request(request)) }; (){ socket.write(prepare_result(result)) }; socket.close(); ","categories":"","description":"","excerpt":"Последовательность команд (блок кода) можно прервать в любом месте с …","ref":"/ru/docs/ops/throw/","tags":"","title":"Ввозврат, прерывания и обработка ошибок"},{"body":"\nВнимание!!!\n“nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nssssssssssssssssssssssssssssssssssssssssssssss\n","categories":"","description":"","excerpt":"\nВнимание!!!\n“nj pfujnДанная статья содержит описание синтаксиса …","ref":"/blog/release-v0.4/","tags":"","title":"Релиз языка программрования NewLang 0.4"},{"body":"\nВнимание!!!\n“nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nssssssssssssssssssssssssssssssssssssssssssssss\n","categories":"","description":"","excerpt":"\nВнимание!!!\n“nj pfujnДанная статья содержит описание синтаксиса …","ref":"/ru/blog/release-v0.4/","tags":"","title":"Релиз языка программрования NewLang 0.4"},{"body":"\nНедавно прочитал на Хабре статью Свой язык, или как я устал от ассемблера и С, и невольно взглядом зацепился за один абзац:\nЯ решил не сильно париться, поэтому использовал библиотеку parglare. Она очень легкая и удобная, всем рекомендую. Для описания синтаксиса парсер принимает строку в соответствующем формате, использует регулярные выражения (не надо осуждать регулярки, они всесильны!).\nВ результате решил опубликовать статью на основе своих старых записей еще с тех времен, когда идея NewLang до конца еще не выкристаллизовалась, но уже хотелось писать реальный код и тестировать разные концепции.\nВедь в жизни практически любого программиста может наступить момент, когда ему в голову приходит светлая идея - разработать свой собственный язык программирования. Может быть и не ради захвата мира, наравне с C/C++, Python или хотя бы PHP, а в качестве личного пет-проекта, с которым он, длинными зимними вечерами будет оттачивать собственное мастерство.\nА так как у любого языка (не только программирования), все начинается с анализа его грамматики, то самой первой задачей создателя будет выбор инструментов для синтаксического анализа исходного текста.\nЭто история — заметки на память о муках выбора связки лексер-парсер для разбора грамматики NewLang. А так же попытка описать и систематизировать выводы об особенностях разных анализаторов с которыми пришлось поработать при выборе парсера для разбора грамматики у своего языка программирования.\nИспользуемые термины. Чтобы было понятно, о чем в дальнейшем пойдет речь.\nЛексер — компьютерная программа или библиотека, в задачи которой входит разделить входной поток данных на отдельные, не связанные между собой отдельные фрагменты, которые принято называть токенами или лексемами.\nПарсер — на основе последовательности токенов выполняется синтаксический анализ, например строит абстрактное синтаксическое дерево (AST).\nЗаход № 1 - Flex + Bison GitHub - westes/flex: The Fast Lexical Analyzer - scanner generator for lexing in C and C++ Bison - GNU Project - Free Software Foundation\nПосле прочтения умных книжек я начал с классики Flex + Bison. Это старые и давно отработанные приложения с широчайшими возможностями по настройке с помощью которых можно описать синтаксис и получить исходные файлы лексера и парсера для языка практически с любой грамматикой.\nК сожалению, у этих старичков очень большой порог входа и тяжелая наследственность. Чего только стоит определение собственного класса лексера через #define, а так же отсутствие нормальной поддержки С++. Вынужденные танцы с бубном для пасинга отдельной строки, когда не требуется анализировать файл целиком и прочие не всегда очевидные проблемы и разные не понятные условности.\nДругими словами, через несколько недель безуспешных мучений я решил посмотреть альтернативы, а так как начальный файл лексики после экспериментов с Flex + Bison кое-как уже был сделан, то следующая связка была Flex + lemon.\nЗаход № 2 - Flex + Lemon The Lemon LALR(1) Parser Generator\nТут все оказалось до примитивности просто и понятно. Реально очень быстрый старт с боевыми примерами, очень наглядный и понятный способ записи правил (по сравнению с Bison). Все хорошо кроме одного, хорошее быстро заканчивается, если приходится анализировать более одной строки.\nПо сути, Lemon с Bison, это как Инь и Янь. Lemon простой и удобный для работы с одной строкой (для этого он и создавался), а Bison супер-пупер-мега комбайн для парсинга файлов любых размеров.\nПоэтому, поиски связки лексер + парсер продолжились и после прочтения очередной статьи, что парсеры языков можно делать на регулярках, решил посмотреть, что есть в этом направлении:\nЗаход № 3 парсер на регулярках re2c Из описания re2c:\nПо сути, на этой штуке можно писать лексические анализаторы прямо на коленке за несколько минут.\n/*!re2c re2c:define:YYPEEK = \"*cursor\"; re2c:define:YYSKIP = \"++cursor;\"; re2c:define:YYBACKUP = \"marker = cursor;\"; re2c:define:YYRESTORE = \"cursor = marker;\"; re2c:define:YYBACKUPCTX = \"ctxmarker = cursor;\"; re2c:define:YYRESTORECTX = \"cursor = ctxmarker;\"; re2c:define:YYRESTORETAG = \"cursor = ${tag};\"; re2c:define:YYLESSTHAN = \"limit - cursor \u003c @@{len}\"; re2c:define:YYSTAGP = \"@@{tag} = cursor;\"; re2c:define:YYSTAGN = \"@@{tag} = NULL;\"; re2c:define:YYSHIFT = \"cursor += @@{shift};\"; re2c:define:YYSHIFTSTAG = \"@@{tag} += @@{shift};\"; */ Показалось, что это самый удобный способ указания шаблонов для парсера! Достаточно описать в комментариях нужные шаблоны, напустить на исходный файл компилятор регулярок и все готово! Но нет, действительно, это только показалось.\nВедь для простеньких парсеров или регулярных выражений re2c может быть и действительно хорош, но отлаживать синтаксис большого языка на регулярках слишком хлопотное занятие.\nПосле этого решил с ним не заморачиваться и посмотреть альтернативы классическим лексерам и парсерам.\nЗаход № 4 - flex (flexcpp) + bisoncpp Тогда как у традиционных flex + bison поддержка С++ реализована через одно место на уровне - работает и не трогай, то решил посмотреть их альтернативную реализация flexcpp + bisoncpp с нативной поддержкой С++.\nПервое впечатление было, то что доктор прописал!\nСинтаксис записи лексики хоть немного и отличается от классической, но это не принципиально. Зато есть нативная и логичная поддержка С++ без оберток и выкрутасов, и как дополнительный плюс - более удобный синтаксис указания правил в парсере. Но и тут не обошлось без шероховатостей.\nВ шаблонах правил bisoncpp не поддерживает юникод (хотя сам лексер-парсер с ним справляется на ура), и совсем не понятная ситуация с поддержкой. Как я понял, разработчиком является вроде бы один человек, но пообщаться с ним насчет ошибок при обработке русских символов так и не получилось.*\nПотом еще одно непонятное поведение вылезло в другом месте. В результате решил отказаться от недружелюбной поддержки и посмотреть, какие есть еще варианты парсеров.\n*) Через два года мой тикет был закрыт с комментарием, что поддерживаются только ascii символы.\nЗаход № 5 - неродной парсер ANTLR От использования ANTLR (от англ. ANother Tool for Language Recognition — «ещё одно средство распознавания языков») — генератора нисходящих анализаторов для формальных языков, я решил сразу отказать из-за того, что он написан на Java,.\nВ этом нет никаких религиозных предпочтений, так как я искал генератор парсеров, который можно было бы сделать встроенным прямо в среду выполнения, а в случае с ANTLR и JRE это было бы затруднительно.\nТаким образом я опять вернулся к старичкам Flex и Bison, с которых все и начиналось.\nЗаход № 6, последний - возвращение к Flex + Bison Все описанные выше эксперименты заняли в общем итоге несколько месяцев, в результате которых были написаны килобайты исходного кода и тестовых примеров, прочитано десятки статей и как результат - возврат к изначальной связке Flex + Bison, но уже с солидным багажом опыта в применении различных вариантов лексеров-парсеров.\nНо самое главное, с пониманием того, что же в результате хочется получить, и очень большой базой тестовых примеров синтаксиса.\nВыводы на память В итоге для себя решил следующее: если нужен простенький шаблонизатор, то идеальный вариант re2c (если почему-то не подходит regexp). Если требуется анализировать синтаксис сложнее обычных регулярок, но в одну строку, то идеальной будет связка flex+lemon, а если нужна серьезная артиллерия, то тут однозначно flex + bison.\nОт связки flexcpp + bisoncpp отказался совсем. Что с поддержкой — не понятно, синтаксис от классики отличается не очень сильно (хотя тоже нужно ломать голову), а обход выявленных косяков не стоят того синтаксического сахара.\nИ по итогам множества экспериментов с разными вариантами синтаксиса удалось сформулировать пару важных архитектурных моментов, которые могут очень сильно упростить жизнь создателям языком программирования:\nСтратегия обработки ошибок синтаксиса Обычно принято обрабатывать синтаксические ошибки непосредственно в парсере и для этого есть определенный резон — в этом случае нет необходимости в каких либо дальнейших действиях, нужна только полностью описанная корректная грамматика.\nНо если грамматика языка очень сложная (привет C++), и её описание становится сложной задачей, то можно отказался и от анализа ошибок синтаксиса непосредственно в парсере! То есть, лучше сделать максимально широкую лексику (даже с теми вариантами, которые являются для языка ошибочными), но ловить эти ошибки уже при анализе AST!\nВ этом случае, поддерживать описание грамматики языка становится значительно проще (меньше синтаксических правил, проще их формальное описание и т.д.), а самое главное, при описании грамматики не нужно думать про lval или rval, где можно указывать ссылку, а где нет — т. е. можно указывать все и везде, а вот анализ допустимости использования конкретных терминов будет выполняться позднее при анализе AST.\nОтказа от полного анализа грамматики языка на уровне лексера — парсера и перенос проверки корректности синтаксических конструкций на этап разбора синтаксического дерева позволяет в разы, если не на порядки сократить и значительно упростить описание грамматических правил!\nПодобное допущение очень полезно на начальном этапе создания языка (можно сосредоточиться на общей концепции, вместо постоянных правок в грамматике), а так же значительно упростить в будущем поддержку и/или расширение синтаксиса.\nМакросы и модификация грамматики в Runtime Какими бы мощными не были flex+bison, но у этой связки есть одна архитектурная проблема. Логика flex и bison построена на конечных автоматах и изменить грамматику языка во время выполнения приложения невозможно, тем более Bison сам вызывает лексер для получения очередной порции данных и ему очень непросто подсунуть измененные данные прямо во время работы. А так хотелось сделать возможность раскрытия макросов и модификации синтаксиса за один проход анализатора!\nДля этого пришлось переделать логику работы flex+bison, чтобы парсер получал данные из лексера не напрямую из yylex, а через функцию — прокси. Эта промежуточная функция, складывает считанные лексемы во внутренний буфер. Данные в буфере анализируется на предмет наличия макросов и только после их раскрытия, лексемы отдаются в парсер из вершины буфера по одной за раз. Подробнее о макросах NewLang можно почитать тут.\nСамое главное при разработке грамматики! Но самый важный совет мне подсказал друг, который некогда участвовал в проекте по разработке парсера для языка программирования. И в правильности его совета - пиши тесты для грамматики - я убеждался уже множество раз. Даже так, ПИШИ ТЕСТЫ ДЛЯ ГРАММАТИКИ.\nТесты для грамматики языка гораздо более важная вещь, чем любой из используемых инструментов. Только тесты позволяют убедиться в том, что новая фича в языке не сломала старые наработки. А если все же сломала, то в первую очередь нужно добавить новый тест, который бы фиксировал сломавшийся сценарий и только после этого можно будет со спокойной душой продолжать эксперименты с новыми грамматическими конструкциями.\nИ удачи всем языкописателям!\nСсылка на первую публикаци\n","categories":"","description":"","excerpt":"\nНедавно прочитал на Хабре статью Свой язык, или как я устал от …","ref":"/blog/parser-nuances/","tags":"","title":"Нюансы разработки парсера для своего языка программирования"},{"body":"\nНедавно прочитал на Хабре статью Свой язык, или как я устал от ассемблера и С, и невольно взглядом зацепился за один абзац:\nЯ решил не сильно париться, поэтому использовал библиотеку parglare. Она очень легкая и удобная, всем рекомендую. Для описания синтаксиса парсер принимает строку в соответствующем формате, использует регулярные выражения (не надо осуждать регулярки, они всесильны!).\nВ результате решил опубликовать статью на основе своих старых записей еще с тех времен, когда идея NewLang до конца еще не выкристаллизовалась, но уже хотелось писать реальный код и тестировать разные концепции.\nВедь в жизни практически любого программиста может наступить момент, когда ему в голову приходит светлая идея - разработать свой собственный язык программирования. Может быть и не ради захвата мира, наравне с C/C++, Python или хотя бы PHP, а в качестве личного пет-проекта, с которым он, длинными зимними вечерами будет оттачивать собственное мастерство.\nА так как у любого языка (не только программирования), все начинается с анализа его грамматики, то самой первой задачей создателя будет выбор инструментов для синтаксического анализа исходного текста.\nЭто история — заметки на память о муках выбора связки лексер-парсер для разбора грамматики NewLang. А так же попытка описать и систематизировать выводы об особенностях разных анализаторов с которыми пришлось поработать при выборе парсера для разбора грамматики у своего языка программирования.\nИспользуемые термины. Чтобы было понятно, о чем в дальнейшем пойдет речь.\nЛексер — компьютерная программа или библиотека, в задачи которой входит разделить входной поток данных на отдельные, не связанные между собой отдельные фрагменты, которые принято называть токенами или лексемами.\nПарсер — на основе последовательности токенов выполняется синтаксический анализ, например строит абстрактное синтаксическое дерево (AST).\nЗаход № 1 - Flex + Bison GitHub - westes/flex: The Fast Lexical Analyzer - scanner generator for lexing in C and C++ Bison - GNU Project - Free Software Foundation\nПосле прочтения умных книжек я начал с классики Flex + Bison. Это старые и давно отработанные приложения с широчайшими возможностями по настройке с помощью которых можно описать синтаксис и получить исходные файлы лексера и парсера для языка практически с любой грамматикой.\nК сожалению, у этих старичков очень большой порог входа и тяжелая наследственность. Чего только стоит определение собственного класса лексера через #define, а так же отсутствие нормальной поддержки С++. Вынужденные танцы с бубном для пасинга отдельной строки, когда не требуется анализировать файл целиком и прочие не всегда очевидные проблемы и разные не понятные условности.\nДругими словами, через несколько недель безуспешных мучений я решил посмотреть альтернативы, а так как начальный файл лексики после экспериментов с Flex + Bison кое-как уже был сделан, то следующая связка была Flex + lemon.\nЗаход № 2 - Flex + Lemon The Lemon LALR(1) Parser Generator\nТут все оказалось до примитивности просто и понятно. Реально очень быстрый старт с боевыми примерами, очень наглядный и понятный способ записи правил (по сравнению с Bison). Все хорошо кроме одного, хорошее быстро заканчивается, если приходится анализировать более одной строки.\nПо сути, Lemon с Bison, это как Инь и Янь. Lemon простой и удобный для работы с одной строкой (для этого он и создавался), а Bison супер-пупер-мега комбайн для парсинга файлов любых размеров.\nПоэтому, поиски связки лексер + парсер продолжились и после прочтения очередной статьи, что парсеры языков можно делать на регулярках, решил посмотреть, что есть в этом направлении:\nЗаход № 3 парсер на регулярках re2c Из описания re2c:\nПо сути, на этой штуке можно писать лексические анализаторы прямо на коленке за несколько минут.\n/*!re2c re2c:define:YYPEEK = \"*cursor\"; re2c:define:YYSKIP = \"++cursor;\"; re2c:define:YYBACKUP = \"marker = cursor;\"; re2c:define:YYRESTORE = \"cursor = marker;\"; re2c:define:YYBACKUPCTX = \"ctxmarker = cursor;\"; re2c:define:YYRESTORECTX = \"cursor = ctxmarker;\"; re2c:define:YYRESTORETAG = \"cursor = ${tag};\"; re2c:define:YYLESSTHAN = \"limit - cursor \u003c @@{len}\"; re2c:define:YYSTAGP = \"@@{tag} = cursor;\"; re2c:define:YYSTAGN = \"@@{tag} = NULL;\"; re2c:define:YYSHIFT = \"cursor += @@{shift};\"; re2c:define:YYSHIFTSTAG = \"@@{tag} += @@{shift};\"; */ Показалось, что это самый удобный способ указания шаблонов для парсера! Достаточно описать в комментариях нужные шаблоны, напустить на исходный файл компилятор регулярок и все готово! Но нет, действительно, это только показалось.\nВедь для простеньких парсеров или регулярных выражений re2c может быть и действительно хорош, но отлаживать синтаксис большого языка на регулярках слишком хлопотное занятие.\nПосле этого решил с ним не заморачиваться и посмотреть альтернативы классическим лексерам и парсерам.\nЗаход № 4 - flex (flexcpp) + bisoncpp Тогда как у традиционных flex + bison поддержка С++ реализована через одно место на уровне - работает и не трогай, то решил посмотреть их альтернативную реализация flexcpp + bisoncpp с нативной поддержкой С++.\nПервое впечатление было, то что доктор прописал!\nСинтаксис записи лексики хоть немного и отличается от классической, но это не принципиально. Зато есть нативная и логичная поддержка С++ без оберток и выкрутасов, и как дополнительный плюс - более удобный синтаксис указания правил в парсере. Но и тут не обошлось без шероховатостей.\nВ шаблонах правил bisoncpp не поддерживает юникод (хотя сам лексер-парсер с ним справляется на ура), и совсем не понятная ситуация с поддержкой. Как я понял, разработчиком является вроде бы один человек, но пообщаться с ним насчет ошибок при обработке русских символов так и не получилось.*\nПотом еще одно непонятное поведение вылезло в другом месте. В результате решил отказаться от недружелюбной поддержки и посмотреть, какие есть еще варианты парсеров.\n*) Через два года мой тикет был закрыт с комментарием, что поддерживаются только ascii символы.\nЗаход № 5 - неродной парсер ANTLR От использования ANTLR (от англ. ANother Tool for Language Recognition — «ещё одно средство распознавания языков») — генератора нисходящих анализаторов для формальных языков, я решил сразу отказать из-за того, что он написан на Java,.\nВ этом нет никаких религиозных предпочтений, так как я искал генератор парсеров, который можно было бы сделать встроенным прямо в среду выполнения, а в случае с ANTLR и JRE это было бы затруднительно.\nТаким образом я опять вернулся к старичкам Flex и Bison, с которых все и начиналось.\nЗаход № 6, последний - возвращение к Flex + Bison Все описанные выше эксперименты заняли в общем итоге несколько месяцев, в результате которых были написаны килобайты исходного кода и тестовых примеров, прочитано десятки статей и как результат - возврат к изначальной связке Flex + Bison, но уже с солидным багажом опыта в применении различных вариантов лексеров-парсеров.\nНо самое главное, с пониманием того, что же в результате хочется получить, и очень большой базой тестовых примеров синтаксиса.\nВыводы на память В итоге для себя решил следующее: если нужен простенький шаблонизатор, то идеальный вариант re2c (если почему-то не подходит regexp). Если требуется анализировать синтаксис сложнее обычных регулярок, но в одну строку, то идеальной будет связка flex+lemon, а если нужна серьезная артиллерия, то тут однозначно flex + bison.\nОт связки flexcpp + bisoncpp отказался совсем. Что с поддержкой — не понятно, синтаксис от классики отличается не очень сильно (хотя тоже нужно ломать голову), а обход выявленных косяков не стоят того синтаксического сахара.\nИ по итогам множества экспериментов с разными вариантами синтаксиса удалось сформулировать пару важных архитектурных моментов, которые могут очень сильно упростить жизнь создателям языком программирования:\nСтратегия обработки ошибок синтаксиса Обычно принято обрабатывать синтаксические ошибки непосредственно в парсере и для этого есть определенный резон — в этом случае нет необходимости в каких либо дальнейших действиях, нужна только полностью описанная корректная грамматика.\nНо если грамматика языка очень сложная (привет C++), и её описание становится сложной задачей, то можно отказался и от анализа ошибок синтаксиса непосредственно в парсере! То есть, лучше сделать максимально широкую лексику (даже с теми вариантами, которые являются для языка ошибочными), но ловить эти ошибки уже при анализе AST!\nВ этом случае, поддерживать описание грамматики языка становится значительно проще (меньше синтаксических правил, проще их формальное описание и т.д.), а самое главное, при описании грамматики не нужно думать про lval или rval, где можно указывать ссылку, а где нет — т. е. можно указывать все и везде, а вот анализ допустимости использования конкретных терминов будет выполняться позднее при анализе AST.\nОтказа от полного анализа грамматики языка на уровне лексера — парсера и перенос проверки корректности синтаксических конструкций на этап разбора синтаксического дерева позволяет в разы, если не на порядки сократить и значительно упростить описание грамматических правил!\nПодобное допущение очень полезно на начальном этапе создания языка (можно сосредоточиться на общей концепции, вместо постоянных правок в грамматике), а так же значительно упростить в будущем поддержку и/или расширение синтаксиса.\nМакросы и модификация грамматики в Runtime Какими бы мощными не были flex+bison, но у этой связки есть одна архитектурная проблема. Логика flex и bison построена на конечных автоматах и изменить грамматику языка во время выполнения приложения невозможно, тем более Bison сам вызывает лексер для получения очередной порции данных и ему очень непросто подсунуть измененные данные прямо во время работы. А так хотелось сделать возможность раскрытия макросов и модификации синтаксиса за один проход анализатора!\nДля этого пришлось переделать логику работы flex+bison, чтобы парсер получал данные из лексера не напрямую из yylex, а через функцию — прокси. Эта промежуточная функция, складывает считанные лексемы во внутренний буфер. Данные в буфере анализируется на предмет наличия макросов и только после их раскрытия, лексемы отдаются в парсер из вершины буфера по одной за раз. Подробнее о макросах NewLang можно почитать тут.\nСамое главное при разработке грамматики! Но самый важный совет мне подсказал друг, который некогда участвовал в проекте по разработке парсера для языка программирования. И в правильности его совета - пиши тесты для грамматики - я убеждался уже множество раз. Даже так, ПИШИ ТЕСТЫ ДЛЯ ГРАММАТИКИ.\nТесты для грамматики языка гораздо более важная вещь, чем любой из используемых инструментов. Только тесты позволяют убедиться в том, что новая фича в языке не сломала старые наработки. А если все же сломала, то в первую очередь нужно добавить новый тест, который бы фиксировал сломавшийся сценарий и только после этого можно будет со спокойной душой продолжать эксперименты с новыми грамматическими конструкциями.\nИ удачи всем языкописателям!\nСсылка на первую публикаци\n","categories":"","description":"","excerpt":"\nНедавно прочитал на Хабре статью Свой язык, или как я устал от …","ref":"/ru/blog/parser-nuances/","tags":"","title":"Нюансы разработки парсера для своего языка программирования"},{"body":"https://habr.com/articles/720416/\nThis is a translation of my own article\nThe release of NewLang language with a brand new “feature” is coming, a remodeled version of the preprocessor that allows you to extend the language syntax to create different DSL dialects using macros.\nWhat is it about? DSL (Subject Oriented Language) is a programming language specialized for a specific application area. It is believed that the use of DSL significantly increases the level of abstractness of the code, and this allows to develop more quickly and efficiently and greatly simplifies the solution of many problems.\nConditionally, we can distinguish two approaches to DSL implementation: Development of independent syntax translators using lexer and parser generators to define the grammar of the target language through BNF (Backus–Naur form) and regular expressions (Lex, Yacc, ANTLR, etc.) and then compiling the resulting grammar into machine code. Development or integration of the DSL dialect into a general-purpose language (metalanguage), including the use of various libraries or special parsers / preprocessors. We will talk about the second option, namely the implementation of DSL on the basis of general-purpose languages (metalanguages) and the new implementation of macros in NewLang as the basis for DSL development.\nTwo extremes It probably makes sense to start by describing two extremes in the implementation of a DSL based on a general-purpose language (metalanguage):\nLimited grammar. If a programming language is limited to its own fixed grammar and does not allow for its expansion, when implementing DSL the developer will be forced to use the existing grammar, the rules for recording operations and generally all syntax will remain the same as in the implementation language. For example, when using C/C++ as a base language, or using various libraries and frameworks in other general-purpose programming languages.\nIn this case, the term “DSL” will simply be a set of domain-specific terms, overridden macros and/or operators, but the use of which will be restricted by the implementation language grammar.\nUnrestricted grammar. If a language (metalanguage) allows you to modify its own grammar (for example at the level of AST), then DSL will no longer be strictly bounded by the syntax of the underlying programming language, and as a result its grammar can be whatever you want. Up to the point that “for every new project you will have to learn a new language…”. This can be done by using specialized metalanguages (Lisp, ML, Haskell, Nemerle, Forth, Tcl, Rebol, etc.).\nI strongly recommend you to read an excellent article on metaprogramming by @NeoCode [Metaprogramming: what it is and what it should be] (https://habr.com/post/258667/).\nThe following implementation of macros is offered for discussion “There is no perfection in the world”, and after the release of NewLang 0.2, I received a lot of feedback (mostly negative), about the first version of macro implementation and DSL based on it. And those criticisms were often valid. So I decided to try to redesign the macros a bit, in hopes of getting a “middle ground” between the two extremes described above when describing the DSL.\nTerminology Used Macros in NewLang, are one or more terms that are replaced by another term or by an entire lexical construct (a sequence of tokens). Macros are both an extension of basic language syntax, when implementing DSL’s own dialects, and a syntax sugar.\nThe main feature of macros is that they allow expressions to be changed before they are evaluated at runtime. Macros are expanded at runtime lexer, which allows you to substitute any other terms with them and even modify the language syntax itself.\nThat’s why if you don’t specify a modifier before the NewLang object name (****macros, **$**local_variable or **@**module), the program will first search among macros, then among local variables and finally among modules (object from module). This allows you to use terms without modifiers to specify types of objects.\nMacro definitions The definition of macros uses exactly the same syntax as for other language objects (the operators “::=”, “=” or “:=” are used respectively to create a new object, assign a new value to an existing object or to create/assign a new value to an object regardless of its presence or absence).\nIn general, a macro definition consists of three parts \u003c macro name \u003e \u003c creating/assignment operator \u003e \u003c macro body \u003e and final semicolon “;*”.\nMacro body The macro body can be a correct language expression, a sequence of tokens (framed in double backslashes, i.e. \\\\ lexem1 lexem2 \\\\) or a plain text string (framed in triple backslashes, i.e. \\\\\\ text string \\\\\\).\nTo connect two tokens into one (analogous to the ## operation in the C/C++ preprocessor), used by analogy syntax ##. A similar operator is used to frame a lexeme in quotes #, for example, \\macro($arg) := \\\\\\ func_ \\## \\$arg(\\#arg) \\;, then a call to macro(arg) will be expanded to func_arg (\"arg\");\nMacro Name The macro name can be a single identifier with the macro prefix “\\” or a sequence of several lexem. If a sequence of lexem is used as the macro name there must be at least one identifier among them and there can be one or more templates.\nA template is a special identifier that can be replaced by any single term during matching. With the help of templates the search by pattern and replacement of the set sequences of lexemes on a body of a macro is made.\nTo specify a template, you need to put a dollar sign at the beginning of the identifier (which corresponds to the local variable name record), i.e. \\\\one_lexem\\\\, \\\\total three tokens\\\\ \\\\ lexem $template1 $template2 \\\\.\nMacros are considered identical if their identifiers are equal, the number of elements in their names is the same, and identifiers and templates are in the same places.\nMacro Arguments Terms or templates in a macro name can have arguments, which are specified in parentheses. The passed arguments in the body of macro are written in the disclosure space as a local variable name, but a backslash must be added before the name, i.e. \\$name.\nAn arbitrary number of parameters in a macro is marked with a triple colon “…”, and the place for inserting these arguments is marked with the token $…. If a macro has several identifiers with arguments, the place marked with the desired identifier to insert arguments from a marked identifier, for example, $name….\nTo insert the number of actually passed arguments, the lexeme $# is used, or with the marked identifier, for example, $#name.\n*Macros work with lexem that contain various information, including the data type if it is specified. But at the moment data types in macro arguments are not handled in any way, and this is one of the mandatory features that will be implemented in the future.\nExamples: \\macros1 := 123; \\macros2(arg) := { func( \\$arg ); func2(123);}; \\\\ macros of(...) tokens \\\\ := \\\\ call1(); call2( \\$... ); call3() \\\\; \\text_macros := \\\\\\ string for the lexer \\\\\\; # Ordinary macros (macro body is a valid expression) \\macro := replace(); \\macro2($arg) := { call( \\$arg ); call() }; # The function takes the number of arguments and the arguments themselves \\\\func name1(...)\\\\ := name2( \\$#, \\$name1... ); # macro body from a sequence of tokens \\if(...) := \\\\ [ \\$... ] --\u003e \\\\; # Expression may not be complete \\else := \\\\ ,[ _ ] --\u003e \\\\; # Expression may not be complete # Macro body from text string (like in C/C++ preprocessor) \\macro_str := \\\\\\ string - macro body \\\\\\; # String for the lexer \\macro($arg) := \\\\ func_ \\## \\#arg(\\#arg)\\\\; # macro(arg) -\u003e func_arg (\"arg\") What possibilities does this offer? You can define macros in the following combinations this way:\n№ Macro name Macro body ---------------------------------------------------------------- 1. \\identifier expression 2. \\identifier \\\\lexem1 lexeme2\\\\ 3. \\Identifier \\\\\\string for the lexer\\\\\\. 4. \\\\lexeme1 lexeme2\\\\ expression 5. \\\\lexeme1 lexeme2\\\\ \\\\lexeme1 lexeme2\\\\ 6. \\\\lexeme1 lexeme2\\\\ \\\\\\ line for the lexer \\\\\\ Each of the above combinations has its own properties and limitations: Classic replacement of one term with another term or integer expression. It is handled by lexer and parser once during definition. The expression in the macro body has to be correct in terms of syntax, and if there are errors in it, a message about this is generated immediately, while still defining the macro.\nClassical replacement of one term by sequences of tokens, including incomplete syntactic constructions. It is processed by the lexer once during macro definition. The body of the macro is parsed by the parser when it is used, so possible syntax errors will be noticed only when the macro is expanded.\nClassic replacement of a single term with a text string, which is fed to the lexer’s input. Only the macro name is once processed by the lexer when it is defined, allowing you to modify the macro body and change/combine/modify lexemes before feeding them into the analyzer. Syntax errors will be noticed only when the macro is expanded.\n4, 5 и 6. Replacing a sequence of several tokens (templates) with an expression, a sequence of tokens or a text string, respectively.\nPurpose and examples of use Macros are also used to convert the basic NewLang syntax into a more familiar keyword-based syntax, because such text is much easier to understand when reading the source code later.\nIf no modifier is specified before the name of NewLang object (**\\**macros, **$**local_variable or **@**module), then macros name is searched first, then the name of local variable and last, the name of module (module object). This makes it possible to define DSL syntax in the usual way without the obligatory prefixes for different types of objects.\nFor example, writing a conditional statement in the basic syntax NewLang:\n[condition] --\u003e { ... } [ condition2 ] --\u003e { ... } [ _ ] { ... }; # With macros \\if(...) := \\\\ [ \\$... ]--\u003e \\\\; \\elif(...) := \\\\ ,[ \\$... ]--\u003e \\\\; \\else := \\\\ ,[ _ ]--\u003e \\\\; # Turns into classical notation if( condition ){ ... } elif( condition2 ){ ... } else { ... }; Or loop to 5:\ncount := 1; [ 1 ] \u003c-\u003e { [ count\u003e5 ] --\u003e { ++ 42 ++; }; count += 1; }; will look more familiar with the use of appropriate macros:\n\\while(...) := \\\\ [ \\$... ] \u003c-\u003e \\\\; \\return(...) := ++ \\$... ++; \\true := 1; count := 1; while( true ) { if( count \u003e 5 ) { return 42; }; count += 1; }; Deleting macros To delete a macro, you have to assign it an empty sequence of tokens \\macro_str := \\\\\\\\;. You can use a special syntax to delete it: \\\\\\\\ name \\\\\\\\; or \\\\\\\\ \\\\two terms\\\\ \\\\\\\\;, i.e. specify the macro name between four backslashes.\nThe necessity to use a separate syntax construct to remove macros is caused by the fact that macro names are processed by the lexer even before the parsing stage in the parser.\nWhat’s the upside? You can dilute the basic language syntax with additional keywords and turn it into a familiar “keyword-based” syntax. Macros are defined according to the language’s vocabulary, and macros are treated as normal objects. Ease of source code analysis and debugging. You can make explicit use of DSL terms and metaprogramming techniques, for example, always prefix the macro name. That way the compiler will know very well that the macro needs to be expanded. Although you can modify the language syntax significantly at your own risk, you can only do so within certain constraints (AST cannot be modified directly), which does not allow you to go very far and, for example, crash or hang the compiler. In spite of very big possibilities to modify the syntax, you get a very simple, fast and unambiguous implementation. And this positively affects the speed of source code analysis, detection and processing of possible errors and simultaneously represents a reasonable compromise between the complexity of implementation of this functionality and possibilities of defining own DSL dialects. If desired, there is room to develop metaprogramming capabilities. In the future we could add pattern-matching (e.g. based on regular expressions), make string parametrization for generating syntax in the body of a macro, including in runtime, and many other different ways to elegantly shoot yourself or your comrade in the foot. Conclusion Any feedback on this macro implementation would be appreciated. And twice as grateful if, in addition to criticism, there are suggestions for its improvement and refinement, if any point has been missed.\n","categories":"","description":"A short lead description about this content page. Text here can also be **bold** or _italic_ and can even be split over multiple paragraphs.\n","excerpt":"A short lead description about this content page. Text here can also …","ref":"/blog/dsl-domain-specific-language-implementation-with-macros/","tags":"","title":"DSL (domain-specific language) implementation with macros"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nБлизится релиз языка NewLang с принципиальной новой «фишкой», переделанным вариантом препроцессора, который позволяет расширять синтаксиса языка для создания различных диалектов DSL за счет макросов.\nИ, как всегда, используя ранее найденный лайфхак Хабр — ума палата, хотелось бы получить от читателей обратную связь насчет предлагаемого ниже подхода, который планируется к реализации в новом препроцессоре NewLang.\nО чем идет речь? DSL (Предметно-ориентированный язык) - язык программирования, специализированный для конкретной области применения. Считается, что использование DSL существенно повышает уровень абстрактности кода, а это позволяет вести разработку более быстро и эффективно и существенно упрощает решение многих задач.\nУсловно, можно выделить два подхода к реализации DSL: Разработка независимых трансляторов синтаксиса с помощью генераторов лексеров и парсеров для определения грамматики целевого языка посредством БНФ и регулярных выражений (Lex, Yacc, ANTLR и т. д.) и последующей компиляцией полученной грамматики в машинный код. Разработка или встраивание диалекта DSL на языке (метаязыке) общего назначения, в том числе за счет применения различных библиотек или специальных парсеров / препроцессоров. Далее речь пойдет о втором варианте, а именно, о реализации DSL на базе языков (метаязыков) общего назначения и новом варианте реализации макросов в NewLang как основы для разработки DSL.\nДве крайности Наверно имеет смысл начать с описания о двух крайностях при реализации DSL на базе языка (метаязыка) общего назначения:\nОграниченная грамматика Если язык программирования ограничен собственной фиксированной грамматикой и не допускает её расширения, то при реализации DSL разработчик будет вынужден использовать уже существующую грамматику, правила записи операций и вообще весь синтаксис будет оставаться такими же, как в языке реализации. Например, при использовании в качестве базового языка С/С++ или применении различных библиотек и фреймворков в других языках программирования общего назначения.\nВ этом случае под термином “DSL” будет скрываться просто набор специфических терминов предметной области, переопределенных макросов и/или операторов, но использование которых будет ограничено грамматикой языка реализации.\nНеограниченная грамматика Если же язык (метаязык) позволяет модифицировать собственную грамматику (например на уровне AST), то DSL уже не будет жестко огранен синтаксисом базового языка программирования, и в результате его грамматика может быть какой угодно. Вплоть до того, что «для каждого нового проекта придется изучать новый язык… ». Это можно сделать с помощью использования специализированных метаязыков (Lisp, ML, Haskell, Nemerle, Forth, Tcl, Rebol и пр.)\nОчень рекомендую прочитать о метапрограммровании великолепную статью @NeoCode Метапрограммирование: какое оно есть и каким должно быть.\nДля обсуждения предлагается следующая реализация макросов «Нет в мире совершенства», и после выпуска релиза NewLang 0.2 я получил много отзывов (по большей части негативных), по поводу первого варианта реализации макросов и DSL на их основе. И если положить руку на сердце, эта критика часто была обоснованной. Поэтому я решил попробовать немного переделать макросы, в надежде получить «золотую середину» между двумя описанными выше крайностями при описании DSL.\nИспользуемая терминология Макросы в NewLang, это один или несколько терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем). Макросы являются одновременно и расширением базового синтаксиса языка, при реализации собственных диалектов DSL, и синтаксическим сахаром.\nГлавная особенность макросов в том, что они позволяют изменять выражения еще до их вычисления во время выполнения. Раскрытие макросов происходит во время работы лексера, что позволяет подменять ими любые другие термины и даже модифицировать сам синтаксис языка.\nПоэтому, если перед именем объекта NewLang модификатор не указывать (**\\**макрос, **$**локальная_переменная или **@**модуль), то сперва будет производиться поиск объекта среди макросов, потом среди локальных переменных и в последнюю очередь среди модулей (объектов модуля). За счет этого можно использовать термины без обязательных модификаторов для указания конкретных типов объектов.\nОпределение макросов Для определения макросов используется точно такой синтаксис, как и для других объектов языка (применяются операторы «::=», «=» или «:=», соответственно для создания нового объекта, присвоение нового значения уже существующему или для создания объекта / присвоения нового значения объекту не зависимо от его наличия или отсутствия).\nВ общем виде, определение макроса состоит из трех частей \u003cимя макроса\u003e \u003cоператор создания/присвоения\u003e \u003cтело макроса\u003e и завершающая точка с запятой “;”.\nТело макроса Телом макроса могут быть корректное выражение языка, последовательность лексем (которые заключается в двойные обратные слеши, т.е. \\\\лексема1 лексема1\\\\) или обычная текстовая строка (обрамленная в тройные обратные слеши, т.е. \\\\\\ текстовая строка \\\\\\).\nДля соединения двух лексем в одну (аналог операции ## в препроцессоре С/С++), используется по аналогии синтаксис ##. Похожий оператор применяется и для обрамления лексемы в кавычки #, например, \\macro($arg) := \\\\ func_ \\## \\#arg(\\#arg) \\\\;? тогда вызов macro(arg) будет преобразован в func_arg (\"arg\");\nИмя макроса Именем макроса может быть одиночный идентификатор с префиксом макроса “\\” или последовательность из нескольких лексем. Если в качестве имени макроса используется последовательность лексем, то среди них должен быть как минимум один идентификатор и может присутствовать один или несколько шаблонов.\nШаблон — это специальный идентификатор который при сопоставлении может заменяться любым одиночным термином. С помощью шаблонов производится поиск по образцу и замена заданных последовательностей лексем на тело макроса.\nДля указания шаблона в начале идентификатора нужно поставить знак доллара (что соответствует записи имени локальной переменой), т. е. \\\\одна_лексема\\\\, \\\\целых три лексемы\\\\ **\\\\**лексема $шаблон1 $шаблон2 \\\\.\nМакросы считаются одинаковыми, если их идентификаторы равны, количество элементов в их именах совпадает, а идентификаторы и шаблоны располагаются на тех же самых местах.\nАргументы макросов Термины или шаблоны в имени макроса могут иметь аргументы, которые указываются в круглых скобках. Переданные аргументы в теле макроса записываются в месте для раскрытия как имя локальной переменой, но перед именем нужно добавить обратный слеш, т.е. \\$name.\nПроизвольное количество параметров у макроса отмечается троеточием “…”, а место для вставки этих аргументов отмечается лексемой $…. Если у макроса есть несколько идентификаторов с аргументами, то для вставки аргументов из конкретного идентификатора используется лексема с указанием нужного идентификатора, например, $name….\nЧтобы вставить количество реально переданных аргументов используется лексема $#, или с указанием нужного идентификатора, например, $#name.\nМакросы работают с лексемами, которые содержат различную информацию, в том числе и о типе данных, если она указана. Но на текущий момент типы данных в аргументах макросов никак не обрабатываются и это одна из обязательных фич, которая будет реализована в будущем.\nПримеры: \\макрос1 := 123; \\макрос2(arg) := {func( \\$arg ); func2(123);}; \\\\макрос из(...) лексем\\\\ := \\\\ call1(); call2( \\$... ); call3() \\\\; \\текстовый_макрос := \\\\\\ строка для для лексера \\\\\\; # Обычные макросы (тело макроса корректное выражение) \\macro := replace(); \\macro2($arg) := { call( \\$arg ); call()}; # В функцию передается кол-во аргументов и сами аргументы \\\\func name1(...)\\\\ := name2( \\$#, \\$name1... ); # Тело макросов из последовательности лексем \\if(...) := \\\\ [ \\$... ] --\u003e \\\\; # Выражение может быть не полным \\else := \\\\ ,[ _ ] --\u003e \\\\; # Выражение может быть не полным # Тело макроса из текстовой строки (как в препроцессоре С/С++) \\macro_str := \\\\\\ строка - тело макроса \\\\\\; # Строка для лексера \\macro($arg) := \\\\\\ func_ \\## \\#arg(\\#arg)\\\\\\; # macro(arg) -\u003e func_arg (\"arg\") Какие возможности это дает? Таким образом можно определить макросы в следующих комбинациях:\n№ п/п Имя макроса Тело макроса ---------------------------------------------------------------- 1. \\идентификатор выражение 2. \\идентификатор \\\\лексема1 лексема2\\\\ 3. \\идентификатор \\\\\\строка для лексера\\\\\\ 4. \\\\лексема1 лексема2\\\\ выражение 5. \\\\лексема1 лексема2\\\\ \\\\лексема1 лексема2\\\\ 6. \\\\лексема1 лексема2\\\\ \\\\\\строка для лексера\\\\\\ Каждая из перечисленных выше комбинации имеет свои свойства и ограничения:\nКлассическая замена одного термина на другой термин или целое выражение. Однократно обрабатывается лексером и парсером при определении. Выражение в теле макроса должно быть корректным с точки зрения синтаксиса и при наличии в нем ошибок, сообщение об этом формируется сразу, еще при определении макроса.\nКлассическая замена одного термина на последовательности лексем, в том числе и не полные синтаксические конструкции. Однократно обрабатывается лексером при определении макроса. Тело макроса анализируется парсером при его использовании, поэтому возможные синтаксические ошибки будут замечены только при раскрытии макроса.\nКлассическая замена одного термина на текстовую строку, которая подается на вход лексера. Однократно обрабатывается лексером только имя макроса при его определении, что позволяет модифицировать тело макроса и изменять/комбинировать/модифицировать лексемы до их подачи в анализатор. Синтаксические ошибки будут замечены только при раскрытии макроса.\n4, 5 и 6. Замена последовательности из нескольких лексем (шаблонов) на выражение, последовательность лексем или текстовую строку соответственно.\nНазначение и примеры использования Макросы используются и для преобразования базового синтаксиса NewLang в более привычный синтаксис на основе ключевых слов, так как такой текст гораздо легче воспринимается при последующем чтении исходного кода.\nЕсли перед именем объекта NewLang модификатор не указан (**\\**макрос, **$**локальная_переменная или **@**модуль), то сперва ищется имя макроса, потом имя локальной переменной и в последнюю очередь имя модуля (объекта модуля). За счет этого получается определять синтаксис DSL в привычной записи без обязательных префиксов у разных типов объектов.\nНапример, запись условного оператора на основном синтаксисе NewLang:\n[condition] --\u003e { ... } [ condition2 ] --\u003e { ... } [ _ ] { ... }; # С помощью макросов \\if(...) := \\\\ [ \\$... ]--\u003e \\\\; \\elif(...) := \\\\ ,[ \\$... ]--\u003e \\\\; \\else := \\\\ ,[ _ ]--\u003e \\\\; # Превращается в классическую запись if( condition ){ ... } elif( condition2 ) { ... } else { ... }; Или цикл до 5:\ncount:=1; [ 1 ] \u003c-\u003e { [count\u003e5] --\u003e { ++ 42 ++; }; count+=1; }; будет выглядеть более привычно с использованием соответствующих макросов:\n\\while(...) := \\\\ [ \\$... ] \u003c-\u003e \\\\; \\return(...) := ++ \\$... ++; \\true := 1; count := 1; while( true ) { if( count \u003e 5 ) { return 42; }; count += 1; }; Удаление макросов Для удаления макроса нужно присвоить ему пустую последовательность лексем \\macro_str := \\\\\\\\;. Так же для удаления можно использовать специальный синтаксис: \\\\\\\\ name \\\\\\\\; или \\\\\\\\ \\\\два термина\\\\ \\\\\\\\;, т.е. указать имя макроса между четырьмя обратными слешами.\nНеобходимость использования отдельной синтаксической конструкции для удаления макросов вызвана тем, что имена макросов обрабатываются лексером еще до этапа анализа в парсере.\nВ чем профит? Базовый синтаксис языка можно разбавлять дополнительными ключевыми словами и превратить его в привычный «keyword-based». Определение макросов соответствует лексике языка, а сами макросы обрабатываются как обычные объекты. Простота анализа исходного кода и его отладки. Использование терминов DSL и приемов метапрограммирование можно сделать явным, например, всегда перед именем макроса указывать префикс. В этом случае компилятор будет однозначно знать, что требуется выполнить раскрытие макроса. Несмотря на то, что синтаксис языка на свой страх и риск можно значительно модифицировать, но это можно сделать только в рамках определенные ограничений (AST нельзя модифицировать напрямую), что не позволяется очень сильно разгуляться и, например, обрушить или подвесить компилятор. Несмотря на очень большие возможности по модификации синтаксиса, получается очень простая, быстрая и однозначная реализация. А это положительно сказывается на скорости анализа исходников, детектирования и обработки возможных ошибок и одновременно является разумным компромиссом между сложностью реализации данного функционала и возможностями определения собственных диалектов DSL. При желании есть куда развивать возможности метапрограммирования. В будущем можно добавить сопоставление шаблона с образцом (например, на основе регулярных выражений), сделать параметризацию строки для генерации синтаксиса в теле макроса, в том числе и в рантайме, и много других разных способов изящно выстрелить себе в ногу или ногу своего товарища. Заключение Буду благодарен за любую обратную связь по данной реализации макросов. И дважды благодарен, если кроме критики будут высказаны еще и предложения по её улучшению и доработкам, если какой-то момент был упущен.\nСсылка на первую публикаци\n","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/ru/blog/dsl-with-macros/","tags":"","title":"Вариант реализации DSL (domain-specific language) с помощью макросов"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nNewLang — это язык программирования высокого уровня общего назначения. Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан на строгой системе грамматических правил. За счет использования макросов, синтаксис языка легко расширяется до более привычного вида на основе ключевых слов.\nNewLang находится в процессе активного развития. Это третий публичный релиз в который добавлены новые существенные возможности по сравнению с предыдущей версией.\nЗачем нужен NewLang? У всех современных языков программирования происходит постоянное развитие (усложнение) синтаксиса по мере выхода новых версий. Это является своего рода платой за появление новых возможностей и воспринимается пользователями как естественное явление.\nНо одновременно является и серьезной проблемой, так как с выходом версий добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки и поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.\nУ NewLang сложность языковых конструкций ограничена естественным образом за счет разделения синтаксиса языка на две части - это упрощает его изучение и использование.\nОсновной синтаксис — для написания программ в объектно-ориентированном (императивном) и декларативном стилях, который основан не на зарезервированных ключевых словах, а на системе строгих грамматических правил. Имеется возможность расширения основного синтаксиса за счет использования макросов. Расширенный синтаксис — программные вставки на языке реализации (С/С++), когда основного синтаксиса становится недостаточно.\nЕще одно неудобство современных языков в том, что большинство из них были созданы до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек. Это же касается и вычислений с неограниченной точностью, которые так же требуют применения дополнительных библиотечных функций.\nУ NewLang тензорные вычисления и рациональные числа неограниченной точности доступны «из коробки». Они поддерживаются на уровне синтаксиса для записи литералов соответствующих типов, а простые арифметические типы данных являются скалярами (тензорами нулевой размерности). Реализация тензорных вычислений сделана на базе библиотеки libtorch, а рациональные числа с использованием OpenSSL.\nНовые глобальные фичи и изменения в синтаксисе: Простые чистые функции удалены Раньше я пытался использовать синтаксис предикатов из Пролога, в котором проверки условий записываются через запятую. Но эта идея оказалась провальной, а сами операторы просто ужасными (тестировал разные варианты, но каждый раз получал много отрицательных отзывов), поэтому сейчас решил полностью от них отказаться.\nОни получались не только сложными для восприятия, но и по факту не нужными, так как легко заменялись обычной функцией с комбинации обычных логических операций.\nЗафиксирован синтаксис операторов проверки условия и циклов. Изменен и упрощен синтаксис операторов проверки условия (импликации) и цикла, для которых оставлено только по одному варианту. Проверка условия записывается в виде оператора математического следования –\u003e, а цикл с помощью оператора \u003c-\u003e.\nНо для упрощения записи можно пользоваться макросами, тогда в этом случае операции проверки условий и циклы превращаются в классические\n\\if(...){ ... } \\elif(...) { ... } \\else { ... }; или\n\\while( ... ){ ... }; Конструкция else у операторов цикла Теперь оператор цикла while поддерживает конструкцию else, которая выполняется если условие входа в цикл не было выполнено. Это поведение отличается от аналогичных конструкций в языке Python, у которого секция else выполняется всегда, кроме прерывания цикла по break.\nВетка else у оператора цикла записывается так же как и ветка иначе в условном операторе, т. е.\n[ cond ] \u003c-\u003e { ... }, [_] --\u003e { ... }; Или тоже самое, но с использованием макросов:\n\\while(cond) { ... } \\else { ... }; Пространства имен В синтаксис NewLang добавлены пространства имен, в стиле очень похожим на С++. Имена разделяются двойным двоеточием, а для определение пространства имен, его нужно указать перед открывающейся фигурной скобкой.\nns { name { var := 0; # Имя переменной будет ns::name::var ::var := 1; # Переменная из глобального пространства имен } } Программные модули Реализована концепция программных модулей - которая повторяет концепцию иерархического расположения файлов в структуре каталогов файловой системы, как в языках Python и Java.\nИмя модуля начинается на префикс @, а структура каталогов указывается через точку. Причем концепции программных модулей и пространства имен объединены, и полное имя переменой из предыдущего абзаца будет @root.dir.module::ns::name::var, где root и dir это каталоги в файловой системе, а module — имя файла.\nОбъектно ориентированное программирование Реализована часть концепции ООП и добавлена поддержка определения классов и их наследование, которая сейчас выглядит следующим образом:\n:NewClass := :Class() { # Новый тип (класс) field := 1; method() := {}; }; obj := :NewClass(); # Экземпляр класса Неожиданно для самого себя понял, что имея полный набор вариантов проверок при создании объектов (::= - создать новый объект, := - создать новый или присвоить значение существующему, = - только присвоить значение, а если объект не существует будет ошибка), концепция переопределения наследуемых функций не требует вообще никаких ключевых слов:\n:NewClass2 := :NewClass() { # Новый класс на базе существующего field ::= 2; # Будет ошибка, т. к. поле field уже есть в базовом классе method() = {}; # Аналог override, т.к. method должен существовать в базовом классе }; Прерывания, возврат и обработка ошибок Изменена, а точнее полностью переделана идеология возвратов из функций и обработки ошибок. Теперь она чем-то похожа на подход, примененный в Ruby. Любая последовательность команд заключенные в фигурные скобки (в том числе тело функции), рассматривается как блок кода у которого нет специального оператора аналога return, который возвращает какое либо значение. Просто любой блок кода всегда возвращает последнее вычисленное значение (это чем то похоже на оператор «запятая» в языках C/C++).\nДля того, чтобы прервать выполнение кода используются две разные команды - прерывания, которые условно можно назвать положительным и отрицательным результатом. Что примерно соответствует семантике их записи. “Отрицательное” прерывание записывается в виде двух минусов, а “положительное” прерывание в виде двух плюсов, т.е. -- или ++.\nПо умолчанию данные операции возвращают пустое значение. Чтобы прерывание вернуло результат, возвращаемые данные нужно записывать между парой соответствующих символов, т.е. -- 100 --, что является близким аналогом оператора return 100; в других языках программирования, а ++«Строка»++ - аналогом return «Строка»;.\nХотя более точным аналогом этих операторов будет все таки не return, а throw, т.к. эти команды не только прерывают выполнение последовательности команд в блоке, но их еще можно «ловить». Для этого используется блок кода с соответствующей семантикой, {+ … +} - блок кода, который перехватывает положительные прерывания и {- … -} - блок кода, который перехватывает прерывания, созданные операторами –.\nПодобная концепция (в явном виде не разделять возвраты из функций и обработку исключений), хоть и выглядит немного необычной, но позволяет реализовывать несколько очень полезных финтов, которые сложно реализуемые в обычных языках программирования.\nНапример, возврат из нескольких вложенных функций без необходимости обрабатывать результат возврата каждой из них. В этом примере функция Test перехватывает “положительные” прерывания из вложенных функций:\nTest0(arg) := { \\if($arg==0) \\return(\"DONE - 0\"); «FAIL» }; Test1(arg) := { \\if($arg==1) \\return(\"DONE - 1\"); Test0($arg); }; Test(arg) := {+ \\if($arg \u003e= 0) Test1($arg); $arg; +}; Test(0); # Вернет «DONE — 0» возврат из вложенной функции Test0 Test(1); # Вернет «DONE — 1» возврат из вложенной функции Test1 Test(2); # Вернет «FAIL» возврат из вложенной функции Test0 Test(-2); # Вернет -2 — возврат из функции Test Есть еще блок {* … *}, который перехватывает оба типа прерываний. Такой блок кода поддерживает типизацию возвращаемого значения, что позволяет в явном виде указывать типы данных, которые нужно перехватывать. Например, {* ... *} :Type1 — будет перехвачено прерывание вида ++ :Type1 ++ или --:Type1--, что позволяет очень гибко формировать логику работы программы.\nБлоки кода с перехватом исключений также поддерживают оператор иначе (\\else) который, по аналогии с оператором \\else в циклах, выполняется только тогда, если прерывания не произошло.\nМожно указать сразу несколько типов, которые нужно перехватывать:\n{* .... *} \u003c:Type1, :Type2, :Type3\u003e; Бинарная сборка под Windws: В текущем релизе версия clang повышена 15, а вызовы нативных функций опять реализованы с помощью libffi, что в итоге позволило собрать бинарную сборку не только под Linux, но и под Windows. И теперь чтобы поиграться с REPL read-eval-print loop можно скачать уже готовый бинарник.\nПодробная информация о языке: Синтаксис NewLang Подробное описание типов данных Операторы и управляющие конструкции Вся документация по NewLang на одной странице Обратная связь Если у вас появятся предложения по развитию нового или улучшению уже существующего функционала NewLang, пишите.\nПримеры кода #!../output/nlc --eval # Определение функции hello hello(str) := { # Импорт стандартной C функции printf := :Pointer('printf(format:FmtChar, ...):Int32'); # Вызов C функции с проверкой типов аргументов по строке формата printf('%s', $str); # Возврат значения из функции hello $str; }; hello('Привет, мир!'); # Вызвать функцию\u003c/code\u003e Вывод (первая строка выводится с помощью printf, а вторая — возвращаемое значение функции hello):\nПривет, мир! Привет, мир! Пример скрипта для вычисления факториала 1000\n#!../output/nlc --eval fact := 1\\1; # Рациональное число без ограничения точности mult := 1000..1..-1?; # Сделать из диапазона итератор для множителей от 1000 до 2 [mult ?!] \u003c-\u003e { # Цикл, пока не закончатся данные итератора # Получить текущий множитель и перейти на следующий элемент итератора fact *= mult !; }; fact # Вывести итоговый результат Вывод:\n402387260077093773543702433923003985719374864210714632543799910429938512398629 020592044208486969404800479988610197196058631666872994808558901323829669944590 997424504087073759918823627727188732519779505950995276120874975462497043601418 278094646496291056393887437886487337119181045825783647849977012476632889835955 735432513185323958463075557409114262417474349347553428646576611667797396668820 291207379143853719588249808126867838374559731746136085379534524221586593201928 090878297308431392844403281231558611036976801357304216168747609675871348312025 478589320767169132448426236131412508780208000261683151027341827977704784635868 170164365024153691398281264810213092761244896359928705114964975419909342221566 832572080821333186116811553615836546984046708975602900950537616475847728421889 679646244945160765353408198901385442487984959953319101723355556602139450399736 280750137837615307127761926849034352625200015888535147331611702103968175921510 907788019393178114194545257223865541461062892187960223838971476088506276862967 146674697562911234082439208160153780889893964518263243671616762179168909779911 903754031274622289988005195444414282012187361745992642956581746628302955570299 024324153181617210465832036786906117260158783520751516284225540265170483304226 143974286933061690897968482590125458327168226458066526769958652682272807075781 391858178889652208164348344825993266043367660176999612831860788386150279465955 131156552036093988180612138558600301435694527224206344631797460594682573103790 084024432438465657245014402821885252470935190620929023136493273497565513958720 559654228749774011413346962715422845862377387538230483865688976461927383814900 140767310446640259899490222221765904339901886018566526485061799702356193897017 860040811889729918311021171229845901641921068884387121855646124960798722908519 296819372388642614839657382291123125024186649353143970137428531926649875337218 940694281434118520158014123344828015051399694290153483077644569099073152433278 288269864602789864321139083506217095002597389863554277196742822248757586765752 344220207573630569498825087968928162753848863396909959826280956121450994871701 244516461260379029309120889086942028510640182154399457156805941872748998094254 742173582401063677404595741785160829230135358081840096996372524230560855903700 624271243416909004153690105933983835777939410970027753472000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000\\1 Как посмотреть? Бинарная сборка и тесты под Windows Бинарная сборка и тесты под Ubuntu Для запуска бинарных сборок потребуются разделяемые библиотеки libLLVM-15 и libtorch (архив с библиотеками для Windows), (архив с библиотеками для Ubuntu). Так же все можно собрать напрямую из исходников по инструкции в репозитории ","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/blog/release-v0.3/","tags":"","title":"Релиз языка программрования NewLang 0.3"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nNewLang — это язык программирования высокого уровня общего назначения. Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан на строгой системе грамматических правил. За счет использования макросов, синтаксис языка легко расширяется до более привычного вида на основе ключевых слов.\nNewLang находится в процессе активного развития. Это третий публичный релиз в который добавлены новые существенные возможности по сравнению с предыдущей версией.\nЗачем нужен NewLang? У всех современных языков программирования происходит постоянное развитие (усложнение) синтаксиса по мере выхода новых версий. Это является своего рода платой за появление новых возможностей и воспринимается пользователями как естественное явление.\nНо одновременно является и серьезной проблемой, так как с выходом версий добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки и поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.\nУ NewLang сложность языковых конструкций ограничена естественным образом за счет разделения синтаксиса языка на две части - это упрощает его изучение и использование.\nОсновной синтаксис — для написания программ в объектно-ориентированном (императивном) и декларативном стилях, который основан не на зарезервированных ключевых словах, а на системе строгих грамматических правил. Имеется возможность расширения основного синтаксиса за счет использования макросов. Расширенный синтаксис — программные вставки на языке реализации (С/С++), когда основного синтаксиса становится недостаточно.\nЕще одно неудобство современных языков в том, что большинство из них были созданы до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек. Это же касается и вычислений с неограниченной точностью, которые так же требуют применения дополнительных библиотечных функций.\nУ NewLang тензорные вычисления и рациональные числа неограниченной точности доступны «из коробки». Они поддерживаются на уровне синтаксиса для записи литералов соответствующих типов, а простые арифметические типы данных являются скалярами (тензорами нулевой размерности). Реализация тензорных вычислений сделана на базе библиотеки libtorch, а рациональные числа с использованием OpenSSL.\nНовые глобальные фичи и изменения в синтаксисе: Простые чистые функции удалены Раньше я пытался использовать синтаксис предикатов из Пролога, в котором проверки условий записываются через запятую. Но эта идея оказалась провальной, а сами операторы просто ужасными (тестировал разные варианты, но каждый раз получал много отрицательных отзывов), поэтому сейчас решил полностью от них отказаться.\nОни получались не только сложными для восприятия, но и по факту не нужными, так как легко заменялись обычной функцией с комбинации обычных логических операций.\nЗафиксирован синтаксис операторов проверки условия и циклов. Изменен и упрощен синтаксис операторов проверки условия (импликации) и цикла, для которых оставлено только по одному варианту. Проверка условия записывается в виде оператора математического следования –\u003e, а цикл с помощью оператора \u003c-\u003e.\nНо для упрощения записи можно пользоваться макросами, тогда в этом случае операции проверки условий и циклы превращаются в классические\n\\if(...){ ... } \\elif(...) { ... } \\else { ... }; или\n\\while( ... ){ ... }; Конструкция else у операторов цикла Теперь оператор цикла while поддерживает конструкцию else, которая выполняется если условие входа в цикл не было выполнено. Это поведение отличается от аналогичных конструкций в языке Python, у которого секция else выполняется всегда, кроме прерывания цикла по break.\nВетка else у оператора цикла записывается так же как и ветка иначе в условном операторе, т. е.\n[ cond ] \u003c-\u003e { ... }, [_] --\u003e { ... }; Или тоже самое, но с использованием макросов:\n\\while(cond) { ... } \\else { ... }; Пространства имен В синтаксис NewLang добавлены пространства имен, в стиле очень похожим на С++. Имена разделяются двойным двоеточием, а для определение пространства имен, его нужно указать перед открывающейся фигурной скобкой.\nns { name { var := 0; # Имя переменной будет ns::name::var ::var := 1; # Переменная из глобального пространства имен } } Программные модули Реализована концепция программных модулей - которая повторяет концепцию иерархического расположения файлов в структуре каталогов файловой системы, как в языках Python и Java.\nИмя модуля начинается на префикс @, а структура каталогов указывается через точку. Причем концепции программных модулей и пространства имен объединены, и полное имя переменой из предыдущего абзаца будет @root.dir.module::ns::name::var, где root и dir это каталоги в файловой системе, а module — имя файла.\nОбъектно ориентированное программирование Реализована часть концепции ООП и добавлена поддержка определения классов и их наследование, которая сейчас выглядит следующим образом:\n:NewClass := :Class() { # Новый тип (класс) field := 1; method() := {}; }; obj := :NewClass(); # Экземпляр класса Неожиданно для самого себя понял, что имея полный набор вариантов проверок при создании объектов (::= - создать новый объект, := - создать новый или присвоить значение существующему, = - только присвоить значение, а если объект не существует будет ошибка), концепция переопределения наследуемых функций не требует вообще никаких ключевых слов:\n:NewClass2 := :NewClass() { # Новый класс на базе существующего field ::= 2; # Будет ошибка, т. к. поле field уже есть в базовом классе method() = {}; # Аналог override, т.к. method должен существовать в базовом классе }; Прерывания, возврат и обработка ошибок Изменена, а точнее полностью переделана идеология возвратов из функций и обработки ошибок. Теперь она чем-то похожа на подход, примененный в Ruby. Любая последовательность команд заключенные в фигурные скобки (в том числе тело функции), рассматривается как блок кода у которого нет специального оператора аналога return, который возвращает какое либо значение. Просто любой блок кода всегда возвращает последнее вычисленное значение (это чем то похоже на оператор «запятая» в языках C/C++).\nДля того, чтобы прервать выполнение кода используются две разные команды - прерывания, которые условно можно назвать положительным и отрицательным результатом. Что примерно соответствует семантике их записи. “Отрицательное” прерывание записывается в виде двух минусов, а “положительное” прерывание в виде двух плюсов, т.е. -- или ++.\nПо умолчанию данные операции возвращают пустое значение. Чтобы прерывание вернуло результат, возвращаемые данные нужно записывать между парой соответствующих символов, т.е. -- 100 --, что является близким аналогом оператора return 100; в других языках программирования, а ++«Строка»++ - аналогом return «Строка»;.\nХотя более точным аналогом этих операторов будет все таки не return, а throw, т.к. эти команды не только прерывают выполнение последовательности команд в блоке, но их еще можно «ловить». Для этого используется блок кода с соответствующей семантикой, {+ … +} - блок кода, который перехватывает положительные прерывания и {- … -} - блок кода, который перехватывает прерывания, созданные операторами –.\nПодобная концепция (в явном виде не разделять возвраты из функций и обработку исключений), хоть и выглядит немного необычной, но позволяет реализовывать несколько очень полезных финтов, которые сложно реализуемые в обычных языках программирования.\nНапример, возврат из нескольких вложенных функций без необходимости обрабатывать результат возврата каждой из них. В этом примере функция Test перехватывает “положительные” прерывания из вложенных функций:\nTest0(arg) := { \\if($arg==0) \\return(\"DONE - 0\"); «FAIL» }; Test1(arg) := { \\if($arg==1) \\return(\"DONE - 1\"); Test0($arg); }; Test(arg) := {+ \\if($arg \u003e= 0) Test1($arg); $arg; +}; Test(0); # Вернет «DONE — 0» возврат из вложенной функции Test0 Test(1); # Вернет «DONE — 1» возврат из вложенной функции Test1 Test(2); # Вернет «FAIL» возврат из вложенной функции Test0 Test(-2); # Вернет -2 — возврат из функции Test Есть еще блок {* … *}, который перехватывает оба типа прерываний. Такой блок кода поддерживает типизацию возвращаемого значения, что позволяет в явном виде указывать типы данных, которые нужно перехватывать. Например, {* ... *} :Type1 — будет перехвачено прерывание вида ++ :Type1 ++ или --:Type1--, что позволяет очень гибко формировать логику работы программы.\nБлоки кода с перехватом исключений также поддерживают оператор иначе (\\else) который, по аналогии с оператором \\else в циклах, выполняется только тогда, если прерывания не произошло.\nМожно указать сразу несколько типов, которые нужно перехватывать:\n{* .... *} \u003c:Type1, :Type2, :Type3\u003e; Бинарная сборка под Windws: В текущем релизе версия clang повышена 15, а вызовы нативных функций опять реализованы с помощью libffi, что в итоге позволило собрать бинарную сборку не только под Linux, но и под Windows. И теперь чтобы поиграться с REPL read-eval-print loop можно скачать уже готовый бинарник.\nПодробная информация о языке: Синтаксис NewLang Подробное описание типов данных Операторы и управляющие конструкции Вся документация по NewLang на одной странице Обратная связь Если у вас появятся предложения по развитию нового или улучшению уже существующего функционала NewLang, пишите.\nПримеры кода #!../output/nlc --eval # Определение функции hello hello(str) := { # Импорт стандартной C функции printf := :Pointer('printf(format:FmtChar, ...):Int32'); # Вызов C функции с проверкой типов аргументов по строке формата printf('%s', $str); # Возврат значения из функции hello $str; }; hello('Привет, мир!'); # Вызвать функцию\u003c/code\u003e Вывод (первая строка выводится с помощью printf, а вторая — возвращаемое значение функции hello):\nПривет, мир! Привет, мир! Пример скрипта для вычисления факториала 1000\n#!../output/nlc --eval fact := 1\\1; # Рациональное число без ограничения точности mult := 1000..1..-1?; # Сделать из диапазона итератор для множителей от 1000 до 2 [mult ?!] \u003c-\u003e { # Цикл, пока не закончатся данные итератора # Получить текущий множитель и перейти на следующий элемент итератора fact *= mult !; }; fact # Вывести итоговый результат Вывод:\n402387260077093773543702433923003985719374864210714632543799910429938512398629 020592044208486969404800479988610197196058631666872994808558901323829669944590 997424504087073759918823627727188732519779505950995276120874975462497043601418 278094646496291056393887437886487337119181045825783647849977012476632889835955 735432513185323958463075557409114262417474349347553428646576611667797396668820 291207379143853719588249808126867838374559731746136085379534524221586593201928 090878297308431392844403281231558611036976801357304216168747609675871348312025 478589320767169132448426236131412508780208000261683151027341827977704784635868 170164365024153691398281264810213092761244896359928705114964975419909342221566 832572080821333186116811553615836546984046708975602900950537616475847728421889 679646244945160765353408198901385442487984959953319101723355556602139450399736 280750137837615307127761926849034352625200015888535147331611702103968175921510 907788019393178114194545257223865541461062892187960223838971476088506276862967 146674697562911234082439208160153780889893964518263243671616762179168909779911 903754031274622289988005195444414282012187361745992642956581746628302955570299 024324153181617210465832036786906117260158783520751516284225540265170483304226 143974286933061690897968482590125458327168226458066526769958652682272807075781 391858178889652208164348344825993266043367660176999612831860788386150279465955 131156552036093988180612138558600301435694527224206344631797460594682573103790 084024432438465657245014402821885252470935190620929023136493273497565513958720 559654228749774011413346962715422845862377387538230483865688976461927383814900 140767310446640259899490222221765904339901886018566526485061799702356193897017 860040811889729918311021171229845901641921068884387121855646124960798722908519 296819372388642614839657382291123125024186649353143970137428531926649875337218 940694281434118520158014123344828015051399694290153483077644569099073152433278 288269864602789864321139083506217095002597389863554277196742822248757586765752 344220207573630569498825087968928162753848863396909959826280956121450994871701 244516461260379029309120889086942028510640182154399457156805941872748998094254 742173582401063677404595741785160829230135358081840096996372524230560855903700 624271243416909004153690105933983835777939410970027753472000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000\\1 Как посмотреть? Бинарная сборка и тесты под Windows Бинарная сборка и тесты под Ubuntu Для запуска бинарных сборок потребуются разделяемые библиотеки libLLVM-15 и libtorch (архив с библиотеками для Windows), (архив с библиотеками для Ubuntu). Так же все можно собрать напрямую из исходников по инструкции в репозитории ","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/ru/blog/release-v0.3/","tags":"","title":"Релиз языка программрования NewLang 0.3"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nNewLang - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения.\nОсновной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка).\nNewLang находится в процессе активного развития и это второй публичный релиз в котором добавлены существенные новые возможности и произошли некоторые изменения по сравнению с предыдущей версией.\nОсобенности языка: Возможность работы как в режиме интерпретатора, так и компилятора*. Динамическая и статическая типизация с возможностью указания типов в явном виде. Статическая типизация является условно строгой (автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных, например, целое число может быть автоматически преобразовано в вещественное или рациональное, но не наоборот). Автоматическое управление памятью. ООП в виде явного наследования классов и «утиная» типизация. На уровне синтаксиса поддержка нескольких типов функций (обычные и чистые функции без побочных эффектов). Необязательные и именованные параметры функций. Возможны вставки кода на языке реализации (С/С++)*. Простая интеграция с уже существующими программными библиотеками (в том числе импорт нативных переменных и функций из С/С++). Имеется REPL read-eval-print loop — «цикл: чтение — вычисление — вывод». Новые глобальные фичи: Добавлены макросы. Теперь можно делать собственные языковые диалекты и использовать более привычную запись алгоритмических конструкций с использование ключевых слов. Например, цикл [ cond ] \u003c-\u003e { тело цикла }; можно записать в более привычный нотации\n\\while (cond) { тело цикла }; Добавлены итераторы для перебора элементов словарей или для запросов к другим контейнерам (например, к базам данных). На уровне базового синтаксиса поддерживается фильтрация данный, включая функциональный аналог LINQ за счет применения функций обратного вызова в качестве условия фильтра. Добавлен новый тип данных — рациональные числа с неограниченной точностью. Они записываются в виде обыкновенной дроби, у которой разделитель бекслеш, например единицу можно записать 1\\1, а число 0.5 как 1\\2. Реализован оператор распаковки словаря … (многоточие), который можно использовать чтобы передать несколько аргументов при вызове функции или для присвоения значения сразу нескольким переменным. Теперь оператор присвоения поддерживает установку значений сразу нескольким переменным. С правой стороны от оператора присвоения может находится одно или несколько значений или оператор распаковки словаря. Причем словарь может быть указан и с левой стороны от оператора присвоения и таким образом можно записать самый простой способ перебора всех его элементов, когда в цикле первый элемент словаря сохраняется в переменную item, а из самого словаря удаляется: [ dict ] \u003c-\u003e { item, dict := ... dict; }; Изменения в синтаксисе: Изменена запись циклов. Вместо двух разных типов с предусловием и постусловие, теперь используется единая форма записи, а тип цикла определяется взаимным расположением условия и его тела. Изменены названия арифметических и некоторых других типов данных на более логичные. В именах арифметических типов теперь указан их размер (Int8, Int16 … Float32, Float64 и т.д.). Многострочные комментарии стали вложенными Подробная информация о языке: Основные правила синтаксиса: Встроенные типы данных: Операторы и управляющие конструкции: Примеры кода ``` #!../output/nlc --eval Определение функции hello hello(str) := {\n# Импорт стандартной C функции printf := :Pointer('printf(format:FmtChar, ...):Int32'); # Вызов C функции с проверкой типов аргументов по строке формата printf('%s', $str); # Возврат значения из функции hello $str; };\nhello(‘Привет, мир!’); # Вызвать функцию\nВывод (первая строка выводится с помощью printf, а вторая - возвращаемое значение функции hello): Привет, мир! Привет, мир! \u003cspoiler title=\"Пример скрипта для вычисления факториала 1000\"\u003e #!../output/nlc –eval\n@fact := 1\\1; # Рациональное число без ограничения точности @mult := 1000..1..-1?; # Сделать из диапазона итератор для множителей от 1000 до 2 [mult ?!] \u003c-\u003e { # Цикл, пока не закончатся данные итератора # Получить текущий множитель и перейти на следующий элемент итератора fact *= mult !; }; fact # Вывести итоговый результат\nВывод: 402387260077093773543702433923003985719374864210714632543799910429938512398629 020592044208486969404800479988610197196058631666872994808558901323829669944590 997424504087073759918823627727188732519779505950995276120874975462497043601418 278094646496291056393887437886487337119181045825783647849977012476632889835955 735432513185323958463075557409114262417474349347553428646576611667797396668820 291207379143853719588249808126867838374559731746136085379534524221586593201928 090878297308431392844403281231558611036976801357304216168747609675871348312025 478589320767169132448426236131412508780208000261683151027341827977704784635868 170164365024153691398281264810213092761244896359928705114964975419909342221566 832572080821333186116811553615836546984046708975602900950537616475847728421889 679646244945160765353408198901385442487984959953319101723355556602139450399736 280750137837615307127761926849034352625200015888535147331611702103968175921510 907788019393178114194545257223865541461062892187960223838971476088506276862967 146674697562911234082439208160153780889893964518263243671616762179168909779911 903754031274622289988005195444414282012187361745992642956581746628302955570299 024324153181617210465832036786906117260158783520751516284225540265170483304226 143974286933061690897968482590125458327168226458066526769958652682272807075781 391858178889652208164348344825993266043367660176999612831860788386150279465955 131156552036093988180612138558600301435694527224206344631797460594682573103790 084024432438465657245014402821885252470935190620929023136493273497565513958720 559654228749774011413346962715422845862377387538230483865688976461927383814900 140767310446640259899490222221765904339901886018566526485061799702356193897017 860040811889729918311021171229845901641921068884387121855646124960798722908519 296819372388642614839657382291123125024186649353143970137428531926649875337218 940694281434118520158014123344828015051399694290153483077644569099073152433278 288269864602789864321139083506217095002597389863554277196742822248757586765752 344220207573630569498825087968928162753848863396909959826280956121450994871701 244516461260379029309120889086942028510640182154399457156805941872748998094254 742173582401063677404595741785160829230135358081840096996372524230560855903700 624271243416909004153690105933983835777939410970027753472000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000\\1\n## Как посмотреть? - [Загрузить собранный REPL и тесты (пока только под Ubuntu)](https://github.com/rsashka/newlang/releases/download/v0.2.0/nlc_bin.tar.xz) - Для запуска бинарных файлов потребуются разделяемые библиотеки libLLVM-13 и libtorch: [архив только с нужными библиотеками](https://github.com/rsashka/newlang/releases/download/v0.2.0/nlc_so.tar.xz). - Так же все можно собрать напрямую из исходников по инструкции в [репозитории](https://github.com/rsashka/newlang) ","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/blog/release-v0.2/","tags":"","title":"Релиз языка программрования NewLang 0.2"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nNewLang - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения.\nОсновной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка).\nNewLang находится в процессе активного развития и это второй публичный релиз в котором добавлены существенные новые возможности и произошли некоторые изменения по сравнению с предыдущей версией.\nОсобенности языка: Возможность работы как в режиме интерпретатора, так и компилятора*. Динамическая и статическая типизация с возможностью указания типов в явном виде. Статическая типизация является условно строгой (автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных, например, целое число может быть автоматически преобразовано в вещественное или рациональное, но не наоборот). Автоматическое управление памятью. ООП в виде явного наследования классов и «утиная» типизация. На уровне синтаксиса поддержка нескольких типов функций (обычные и чистые функции без побочных эффектов). Необязательные и именованные параметры функций. Возможны вставки кода на языке реализации (С/С++)*. Простая интеграция с уже существующими программными библиотеками (в том числе импорт нативных переменных и функций из С/С++). Имеется REPL read-eval-print loop — «цикл: чтение — вычисление — вывод». Новые глобальные фичи: Добавлены макросы. Теперь можно делать собственные языковые диалекты и использовать более привычную запись алгоритмических конструкций с использование ключевых слов. Например, цикл [ cond ] \u003c-\u003e { тело цикла }; можно записать в более привычный нотации\n\\while (cond) { тело цикла }; Добавлены итераторы для перебора элементов словарей или для запросов к другим контейнерам (например, к базам данных). На уровне базового синтаксиса поддерживается фильтрация данный, включая функциональный аналог LINQ за счет применения функций обратного вызова в качестве условия фильтра. Добавлен новый тип данных — рациональные числа с неограниченной точностью. Они записываются в виде обыкновенной дроби, у которой разделитель бекслеш, например единицу можно записать 1\\1, а число 0.5 как 1\\2. Реализован оператор распаковки словаря … (многоточие), который можно использовать чтобы передать несколько аргументов при вызове функции или для присвоения значения сразу нескольким переменным. Теперь оператор присвоения поддерживает установку значений сразу нескольким переменным. С правой стороны от оператора присвоения может находится одно или несколько значений или оператор распаковки словаря. Причем словарь может быть указан и с левой стороны от оператора присвоения и таким образом можно записать самый простой способ перебора всех его элементов, когда в цикле первый элемент словаря сохраняется в переменную item, а из самого словаря удаляется: [ dict ] \u003c-\u003e { item, dict := ... dict; }; Изменения в синтаксисе: Изменена запись циклов. Вместо двух разных типов с предусловием и постусловие, теперь используется единая форма записи, а тип цикла определяется взаимным расположением условия и его тела. Изменены названия арифметических и некоторых других типов данных на более логичные. В именах арифметических типов теперь указан их размер (Int8, Int16 … Float32, Float64 и т.д.). Многострочные комментарии стали вложенными Подробная информация о языке: Основные правила синтаксиса: Встроенные типы данных: Операторы и управляющие конструкции: Примеры кода ``` #!../output/nlc --eval Определение функции hello hello(str) := {\n# Импорт стандартной C функции printf := :Pointer('printf(format:FmtChar, ...):Int32'); # Вызов C функции с проверкой типов аргументов по строке формата printf('%s', $str); # Возврат значения из функции hello $str; };\nhello(‘Привет, мир!’); # Вызвать функцию\nВывод (первая строка выводится с помощью printf, а вторая - возвращаемое значение функции hello): Привет, мир! Привет, мир! \u003cspoiler title=\"Пример скрипта для вычисления факториала 1000\"\u003e #!../output/nlc –eval\n@fact := 1\\1; # Рациональное число без ограничения точности @mult := 1000..1..-1?; # Сделать из диапазона итератор для множителей от 1000 до 2 [mult ?!] \u003c-\u003e { # Цикл, пока не закончатся данные итератора # Получить текущий множитель и перейти на следующий элемент итератора fact *= mult !; }; fact # Вывести итоговый результат\nВывод: 402387260077093773543702433923003985719374864210714632543799910429938512398629 020592044208486969404800479988610197196058631666872994808558901323829669944590 997424504087073759918823627727188732519779505950995276120874975462497043601418 278094646496291056393887437886487337119181045825783647849977012476632889835955 735432513185323958463075557409114262417474349347553428646576611667797396668820 291207379143853719588249808126867838374559731746136085379534524221586593201928 090878297308431392844403281231558611036976801357304216168747609675871348312025 478589320767169132448426236131412508780208000261683151027341827977704784635868 170164365024153691398281264810213092761244896359928705114964975419909342221566 832572080821333186116811553615836546984046708975602900950537616475847728421889 679646244945160765353408198901385442487984959953319101723355556602139450399736 280750137837615307127761926849034352625200015888535147331611702103968175921510 907788019393178114194545257223865541461062892187960223838971476088506276862967 146674697562911234082439208160153780889893964518263243671616762179168909779911 903754031274622289988005195444414282012187361745992642956581746628302955570299 024324153181617210465832036786906117260158783520751516284225540265170483304226 143974286933061690897968482590125458327168226458066526769958652682272807075781 391858178889652208164348344825993266043367660176999612831860788386150279465955 131156552036093988180612138558600301435694527224206344631797460594682573103790 084024432438465657245014402821885252470935190620929023136493273497565513958720 559654228749774011413346962715422845862377387538230483865688976461927383814900 140767310446640259899490222221765904339901886018566526485061799702356193897017 860040811889729918311021171229845901641921068884387121855646124960798722908519 296819372388642614839657382291123125024186649353143970137428531926649875337218 940694281434118520158014123344828015051399694290153483077644569099073152433278 288269864602789864321139083506217095002597389863554277196742822248757586765752 344220207573630569498825087968928162753848863396909959826280956121450994871701 244516461260379029309120889086942028510640182154399457156805941872748998094254 742173582401063677404595741785160829230135358081840096996372524230560855903700 624271243416909004153690105933983835777939410970027753472000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000\\1\n## Как посмотреть? - [Загрузить собранный REPL и тесты (пока только под Ubuntu)](https://github.com/rsashka/newlang/releases/download/v0.2.0/nlc_bin.tar.xz) - Для запуска бинарных файлов потребуются разделяемые библиотеки libLLVM-13 и libtorch: [архив только с нужными библиотеками](https://github.com/rsashka/newlang/releases/download/v0.2.0/nlc_so.tar.xz). - Так же все можно собрать напрямую из исходников по инструкции в [репозитории](https://github.com/rsashka/newlang) ","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/ru/blog/release-v0.2/","tags":"","title":"Релиз языка программрования NewLang 0.2"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nNewLang - это язык программирования высокого уровня, в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения.\nОсновной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка).\nНовое по сравнению с прошлым выпуском:\nРеализованы все основные алгоритмические конструкции: проверка условий, различные варианты циклов, сравнение по образцу, прерывание последовательности команд и возврат данных, обработка ошибок и т.д. Переработан основной синтаксис для отдельных языковых конструкций. Реализованы большинство операций с переменными, включая операторы раскрытие списков и тензоров. Серьезно переработана система встроенных типов, реализованы функции для их преобразования и для определения данных (последнее можно назвать data comprehensions). Добавлены новые тесты и пр. Зачем нужен NewLang? У всех современных языков программирования происходит постоянное развитие (читай усложнение) синтаксиса по мере выхода новых версий. Это является своего рода, платой за появление новых возможностей и воспринимается пользователями как естественное явление.\nНо одновременно является и серьезной проблемой, т.к. с выходом новых версий добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки и трудоемкости поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.\nУ NewLang сложность языковых конструкций естественно ограничена за счет разделения синтаксиса языка на две части, что упрощает его изучение и использование.\nОсновной синтаксис — для написания программ в объектно-ориентированном (императивном) и декларативном стилях, который основан не на зарезервированных ключевых словах, а на строгих грамматических правилах и Расширенный синтаксис — когда основного синтаксиса становится недостаточно, или требуется использовать языковую конструкцию языка реализации.\nЕще одно неудобство современных мейнстримовых языков, большинство из них были созданы до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек, а не встроены в основной синтаксис языка и систему базовых типов.\nУ NewLang тензорные вычисления доступны «из коробки» (используется библиотека libtorch), а обычные числа являются скалярами (тензорами нулевой размерности).\nСинтаксис NewLang При разработке синтаксиса я старался придерживаться уже сложившихся в IT индустрии правил, чтобы не генерировать множественных смыслов, которые будут зависеть от контекста.\nОсновы\nОператоры разделяются точкой с запятой «;». Отступы и переводы строк игнорируются (очень хотелось иметь возможность автоматического форматирование кода). Многострочные комментарии в исходном коде соответствуют стилю С/С++ и должны располагаться между символами /* и */. Вложенность многострочных комментариев не поддерживается. Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash. Последовательность команд, которая должна выполняться как единое целое, заключается в фигурные скобки «{}». Программные вставки расширенного синтаксиса на языке реализации заключается в фигурные скобки со знаком процента %{ /* тут может быть любой код на C/C++*/ %}, как в лексерах lex и flex. Создания объектов и присвоения новых значений Для создания объектов и присвоения им новых значений в NewLang используется сразу три разных оператора:\n::= используется только для создания новых объектов, а если объект с таким именем уже существует, то генерируется ошибка. := используется для тех же целей, но если объект с таким именем уже существует, то ошибки не происходит, а новое значение присваивается уже существующему объекту. = применяется только для присвоения значения уже существующим объектам, и если объект с указанным именем отсутствует, то тоже происходит ошибка выполнения. Использование трех разных операторов для создания/изменения объектов позволяет более гибко контролировать подобные операции и выявлять логические ошибки в коде на более раннем этапе.\nvar ::= 1.0; # Создать новую переменную var без указания типа var = 100; # Присвоить новое значение уже существующей переменной printf := @import('printf(format:Format, ...):Int'); /* Создать новый или переопределить объект printf, который будет результатом выполнения глобальной функции @import */ Идентификаторы объектов и модификаторы В качестве идентификаторов можно использовать буквы, цифры и знаки подчеркивания в любых комбинациях, при условии, что первый символ идентификатора не является цифрой.\nВ NewLang существует возможность указания области видимости и времени жизни объекта с помощью модификатора — специального символа перед именем переменной. Это может показаться немного похожим на венгерскую нотацию, но в отличие от нее, модификатор не имеет отношения к типу объекта и не является частью имени идентификатора. К тому же в качестве модификаторов используется строго определённые символы, назначение которых определено заранее.\n$ - в начале имени обозначает локальную переменную, время жизни которой ограничено текущей областью видимости и при её завершении локальная переменная уничтожается. @ - обозначает глобальную переменную, а сам объект сохраняет свое состояние даже после выхода из текущей области видимости. : - двоеточие вначале имени используется в качестве модификатора для указания типа. Семантика обращения к аргументам функций очень похоже на работу с аргументами в bash скриптах, где $1 или $arg — порядковый номер или имя аргумента (происходит обращение к локальным переменным в текущей области видимости).\nИспользование модификаторов является обязательным только в двух случаях: При создании нового типа данных, так как типы всегда создаются в глобальной области видимости, а их символьные имена должны быть уникальными. При обращении к объектам NewLang внутри программных вставок кода на языке реализации, так как они используется как маркеры при поиске идентификаторов NewLang в коде С/С++. В остальных случаях, для обращения к переменным указывать их модификаторы необязательно. И если при обращении к объекту модификатор не указан, то сперва ищется локальная переменная, а потом глобальная с таким же именем. Причем, локальная переменная будет перекрывать глобальную.\nТак же следует иметь в виду, что компилятор может генерировать код для прямого обращения к локальным объектам уже на этапе компиляции, тогда как для обращения к глобальным объектам, или если модификатор области видимости отсутствует, компилятор вынужден каждый раз встраивать runtime вызов функции поиска объекта в глобальной таблице символов.\nСистема типов Так как система типов языка динамическая, то явное указание типа не влияет на размер переменной и является только своего рода логическим ограничением на возможность присвоения переменной значения другого типа.\nИнформация о типах используется при проверке их совместимости, когда существующему объекту присваивается значение другого типа. Такая операция возможна только когда типы совместимы между собой и допускают автоматическое приведение. Это справедливо как во время парсинга/компиляции исходного теста, так и во время выполнения в режимах интерпретатора и/или скомпилированного файла.\nПростые типы Арифметические значения Арифметические типы данных являются тензорами — массивами чисел одного типа с произвольным количеством измерений и одинаковым размером столбцов в каждом. Единичное число тоже тензор нулевого размера.\nПоддерживаются только знаковые целые числа, т.к. в беззнаковых числах особая нужда отсутствует, а проблем с ними можно найти очень много на ровном месте.\nПроблемы беззнаковых чисел (из интернета):\nВо-первых, вычитание двух беззнаковых чисел, например 3 и 5. 3 минус 5 равно 4294967294, т.к. -2 не может быть представлено как беззнаковое число. Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных значений со знаком и без знака. С++ может свободно преобразовывать числа со знаком и без знака, но не проверяет диапазон, чтобы убедиться, что вы не переполняете свой тип данных. В C++ всё же есть несколько случаев, когда можно (или необходимо) использовать беззнаковые числа. Во-первых, числа без знака предпочтительнее при работе с битами. Во-вторых, использование беззнаковых чисел связанных с индексацией массивов.\nНо это не мой случай, так как индекс может быть отрицательным и даже не числом, а диапазоном или многоточием.\nЗ.Ы. И даже зная об этом, все равно умудрился недавно словить баг с отрицательными индексами у словарей!\nИмена встроенных арифметических типов говорят сами за себя: Char, Short, Int, Long, Float, Double, ComplexFloat, ComplexDouble. Отдельным типом идет логический тип Bool, который может принимать значения только 0 или 1 (false/true соответственно), и в зависимости от выполняемой операции может быть отнесен к целочисленным типам, так и не входить в их состав (данный подход интерпретации логического типа данных был взят из библиотеки Torch).\n// Treat bool as a distinct \"category,\" to be consistent with type promotion // rules (e.g. `bool_tensor + 5 -\u003e int64_tensor`). If `5` was in the same // category as `bool_tensor`, we would not promote. Differing categories // implies `bool_tensor += 5` is disallowed. // // NB: numpy distinguishes \"unsigned\" as a category to get the desired // `bool_tensor + 5 -\u003e int64_tensor` behavior. We don't, because: // * We don't want the performance hit of checking the runtime sign of Scalars. // * `uint8_tensor + 5 -\u003e int64_tensor` would be undesirable. В будущем планируется добавить классы чисел для длинной арифметики и дробей, для чего зарезервированы названия типов BigNum, Currency и Fraction.\nДоступ к элементам тензора происходит по целочисленному индексу, который начинается с 0. Для многомерного тензора, индексы элемента перечисляются в квадратных скобках через запятую. Поддерживается доступ к элементам через отрицательный индекс, который обрабатывается точно так же, как в Python (-1 последний элемент, -2 предпоследний и т.д.).\nЛитерал тензор в тексте программы записывается в квадратных скобках с обязательной завершающей запятой, т.е. [1, 2,] — это литерал одномерный тензор из двух чисел. После закрывающей скобки тип тензора может быть указан в явном виде. Если тип не указан, то он выводится автоматически на основании указанных данных и выбирается минимально возможный байтовый размер, который позволяет сохранить все значения без потери точности.\nПримеры:\n$var_char := 123; # Тип Char выводится автоматически $var_short := 1000; # Тип Short выводится автоматически $var_bool := [0, 1, 0, 1,]; # Тензор из 4 элементов. Тип Bool выводится автоматически $tensor[10,10]:Int := 1; # Тензор Int размером 2x2 инициализированный 1 $scalar := $tensor[5,5]; # Присвоить скаляру значение указанного элемента тензора Строки Поддерживаются два типа строк, StrWide — символьные (широкие) и StrChar — байтовые. Различия между ними заключается в типе единичного элемента. У символьных строк единичным элементом является широкий символ wchar_t, а у байтовой строки единичным элементом является один байт (точнее char, т.е. байт со знаком). Символьные строки литералы в исходном тексте записывается в «двойных кавычках», а байтовые строки в ‘одинарных кавычках’.\nКоличество элементов символьной строки возвращается в широких символах, а размер байтовой строки в байтах, поэтому и обращение к элементу строки по индексу происходит соответственно либо к символу, либо к байту.\nВажный момент. К любой переменной можно обратиться так же, как к функции (записав после её имени круглые скобки). Результатом этой операции будет создание копии/клона объекта. Причем некоторые типы (словари, классы и символьные строки) можно использовать в качестве шаблона при создании копии объекта с модифицированными свойствами, если новые и/или изменяемые значения указать в скобках, как аргументы при вызовах функций. Так, если при создании копии в скобках указать набор новых данных, то результирующая копия будет содержать уже измененные данные.\nНапример:\n$template := \"${name} $1\"; # Обычная строка $result := $template(\"шаблон\", name = \"Строка\"); # result = \"Строка шаблон\" Системные :Pointer - указатель на системную область памяти Так как любой программе приходится взаимодействовать с внешним миром, то по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип Pointer. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. Но можно вывести его значение, например для отладки.\n:Plain - указатель на представление данных в бинарном виде Для взаимодействия с внешними библиотеками требуется еще и обмен данными. И для этих целей служит тип данных Plain - который также является указателем, но на двоичное представление данных в единой области памяти. Конечно, если их можно представить в виде единого фрагмента.\nСоставные типы данных: Словарь Словарь (:Dictionary) — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии (он похож и на tuple и на структуру одновременно). Словари от тензоров отличаются тем, что являются только одномерными массивами, но каждый элемент может содержать произвольное количество элементов любого типа, в том числе и другие словари.\nДоступ к элементам словарей происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. Индекс также начинается с 0 и как у тензоров и тоже может быть отрицательным.\nЛитерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, т. е. (,) — пустой словарь, (1, 2= «2», name=3,).\nПеречисление, структура и объединение :Enum, :Struct и :Union — это такие же словари, только на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера.\nКлассы Класс (реализован частично) — тип данных, с помощью которого реализуется один из принципов ООП — наследование. При создании экземпляра класса создается новая переменная, у которой сохраняется информацию о своем родителе и которая наследует от него свойства и методы. Тип данных :Class аналогичен словарю, но все свойства обязаны иметь имена (хотя доступ к свойствам класса по индексу так же возможен).\nФункции Синтаксис NewLang поддерживать несколько типов функций (а в будущем и методов классов): обычные функции, чистые функции и простые чистые функции.\nДля всех типов функций поддерживаются аргументы по умолчанию. При создании функции, её аргументы указываются как в Python, т.е. вначале идут обязательные аргументы, потом аргументы со значениями по умолчанию, где имя аргумента отделяется от его значения по умолчанию знаком равно =. Если функция допускает обработку произвольного количества аргументов, то последним в списке параметров указывается многоточие … (три точки подряд) .\nОбычная функция Обычная функция — такие функции являются именно обычными функциями в понимании С/С++. Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д.\nВнутри обычной функции можно обращаться к локальным и глобальным объектам, и они могут содержаться вставки на языке реализации*, например, для вызова функций из внешних библиотек.\nВставки на языке реализации оформляются в виде %{ %} и могут содержать любой текст на С/С++, а прямо из него можно обращаться к локальным и глобальным объектам NewLang так же, как и в обычном синтаксисе, указывая первым символом имени соответствующий модификатор ($ для локальных объектов и @ для глобальных).\nТехнически, такая программная вставка просто переносится трансплайтером непосредственно в исходный текст генерируемого файла, а все идентификаторы NewLang специальным образом декорируются (добавляются специальные маркеры для их идентификации), после этого исходный текст подается на вход обычному компилятору С++. Для локальных объектов трансплайтер может генерировать код для прямого доступа к объекту на этапе компиляции, а для работы с глобальными объектами вынужден использовать runtime вызовы функции поиска в таблице символов.\n*) - Программные вставки на языке реализации обрабатываются только во время компиляции\nНапример:\nprint(str) := { %{ printf(\"%s\", static_cast\u003cconst char *\u003e($str)); /* Прямой вызов С функции */ %} }; Чистые функции Чистая функция — это тоже обычная функция, только в том смысле, какой в него вкладывает функциональное программирование. Создания чистой функции происходит с помощью оператора :-, а сам оператор заимствован из языка Пролог. У чистой функции отсутствует доступ к контексту и глобальным переменным, поэтому она может обрабатывать только те данные, которые были ей переданы в качестве аргументов.\nПрограммные вставки на языке реализации внутри чистых функций не запрещены и могут использоваться, например, для отладки. Но делается это на страх и риск разработчика. Именно он отвечает за их «чистоту», например при вызове функций из внешних библиотек.\nSum(arg1, arg2) :- {$arg1+$arg2;}; # Вернуть сумму аргументов Простые чистые функции Простые чистые функции — отдельный класс чистых функций, которые предназначены только для вычисления логического результата (т.е. они являются предикатами) и их отличает упрощенная формой записи. Тело простой чистой функции состоит из последовательности операторов, которые разделяются запятыми и заканчиваются, как и любое выражение, точкой с запятой. Все операторы простой чистой функции всегда приводятся к булевому значению, а итоговый результат функции вычисляется по одной из возможных логических операций: И, ИЛИ и исключающее ИЛИ.\nНапример:\nfunc_and(arg1, arg2) :\u0026\u0026= arg1==3, arg2 \u003e 0; # Простая чистая функция Логическое И func_or(arg1, arg2) :||= arg1==3, arg2 \u003e 0; # Простая чистая функция Логическое ИЛИ func_xor(arg1, arg2) :^^= arg1==3, arg2 \u003e 0; # Простая чистая функция Исключающее ИЛИ Специальные типы данных: Пусто (:None) :None (пусто) — не содержит значения (точнее имеет одно значение None) и совместим с любым другим типом данных. Указывается в тексте программы как один подчерк «_». None имеют не инициализированные переменные и при попытке чтения из такой переменной возникает ошибка.\nТип переменной может быть явно указан или выведен автоматически из присваиваемого значения. Присвоить новое значение уже инициализированной переменной можно только для совместимого типа, так как неявное преобразование типов не допускаются.\n$var := _; # Создать не инициализированную переменную $var2 := var; # Ошибка!!! Нельзя прочитать неинициализированную переменную var $var = 1000; # У переменной будет тип Short (минимальный размер для хранения значения) $var = 0,5; # Ошибка!!! Short ← Float не совместимы $var = _; # Очистить значение переменной $var = 0,5; # Теперь можно, т. к. None совместим с любым типом Диапазон (:Range) Диапазон — специальный тип данных, являющейся приблизительным аналогом типа «генератор» в Python. К диапазону можно обращаться как к итератору и он будет поочередно выдавать элементы в указанном интервале с заданным шагом. Диапазон в тексте программы указывается как два или три элемента через две точки, например 1..5 — диапазон от единицы до пяти с шагом по умолчанию 1. В качестве параметров диапазона можно указывать не только литералы, но и имена переменных. Например, 0,1..$stop..0,1 — диапазон от 0,1 до значения, указанного в переменной $stop с шагом 0,1.\nДиапазон для целых чисел можно использовать в качестве индекса у тензоров (точнее, у любых объектов, которые допускают доступ к своим элементам по индексу, т.е. тензоры, словари и текстовые строки). Фактический, это поведение аналогично slice в языке Python и array[1:5] в Python означает тоже самое, что и array[1..5] в NewLang.\nВ качестве индекса у тензоров еще можно указать произвольное количество измерений с помощью многоточия, т.е.\n$tensor[…, 0] = 0; # Обнулить все первые элементы в каждом измерении. Преобразование типов Явное приведение типов Несмотря на динамическую типизацию языка, если тип переменной указан явно, то автоматическое приведение типов не выполняется, и чтобы присвоить переменой значение не совместимого типа, требуется явное преобразование.\nТак как символьные названия типов относятся к деталям реализации, то явное преобразование в конкретный тип данных производится с помощью вызова функции с именем типа, т.е. :Bool(), :StrWide(), :Long() и т.д.\nДля преобразования любого типа данных в строку ещё можно использовать оператор конкатенации строк, которой преобразует любой тип данных в строковое представление. Но, так как строковых типов два (байтовые и широкие строки), то тип строки определяется первым аргументом в операторе конкатенации/сцепления ++. Также преобразовать любое значение в строковое можно с помощью строки-шаблона.\n\"\" ++ 123; # \"123\" - Строка широких символов '' ++ 123; # '123' - Байтовая строка val := 12345; # Число \"$1\"(val); # Будет строка \"12345\" Так как тензоры могут иметь больше одного значения, то и в качестве аргументов могут принимать их произвольное количество, а итоговым результатом будет тензор, в котором все переданные данные преобразованы к требуемому типу автоматически.\nПримеры:\n\u003e tstr := :Tensor(\"Тест\"); # Создать тензор из строки широких символов [1058, 1077, 1089, 1090,]:Int \u003e t2 := :Tensor[2,2](\"Тест\"); # Тоже самое, но тензор указанной размерности [ [1058, 1077,], [1089, 1090,], ]:Int \u003e :StrWide(tstr) # Создать символьную строку из тензора Тест \u003e :Double(t2) # Изменить тип данных тезора без изменения размерности [ [1058, 1077,], [1089, 1090,], ]:Double \u003e t3 := :Char[4]( t2 ) # Изменить размерность тензора и его тип (в данном случае с частичной потерей данных) [34, 53, 65, 66,]:Char \u003e:Tensor( (1,2,3,) ); # Тензор из словаря [1, 2, 3,]:Char \u003e:Tensor( 'first second' ) # Байтовая строка в тензор [102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char \u003e:Tensor( (first='first', space=32, second='second',) ) # Получаем тензор из словаря с такими же данными [102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char \u003e:Double[10,2]( 0, ...) # Тензор заданного формата с нулями, где многоточие повторяет последние указанные данные до получения тензора требуемого размера [ [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], ]:Double \u003e:Int[3,2]( ... rand() ...) # Тензор со случайными данными, где между многоточиями указана функция, которую следует вызывать каждый раз при получении нового элемента тензора # Пришлось придумывать новую конструкцию, т.к. многоточие перед именем, это оператор раскрытия словаря, а многоточие после имени, это повторение последнего значения до конца заданной размерности. [ [1804289383, 846930886,], [1681692777, 1714636915,], [1957747793, 424238335,], ]:Int \u003e:Int[5,2]( 0..10 ); # Создание тензора из диапазона [ [0, 1,], [2, 3,], [4, 5,], [6, 7,], [8, 9,], ]:Int \u003e:Tensor( 0..0.99..0.1 ); # Или даже так [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,]:Double Операторы и управляющие конструкции Операторы: Все операторы имеют парный аналог с присвоением значения:\n+ и += - сложение арифметических типов данных; - и -= - вычитание арифметических типов данных; / и /= - деление (результат число с плавающей точкой); // и //= - целочисленное деление с округлением к меньшему числу (как в Python); * и *= - умножение; ** и **= - возведение в степень (он же используется и для повторения текстовых строк); ++ и ++= - конкатенация строк с автоматическим приведением аргументов к стоковому типу (символ инкремента специально используется вместо одиночного плюса для того, чтобы в явном виде разделить конкатенацию строк и операторы арифметического сложения). Операторы сравнения: \u003c, \u003e, \u003c=, \u003e= - классические для сравнения скаляров == и != - операторы сравнения с автоматическим приведением совместимых типов для любых объектов === и !== - оператор точного сравнения для любых объектов (автоматического приведения типов не выполняется) Проверки типа (имени класса объекта): Для оператора проверки имени класса объекта используется символ тильда ~. Он немного похож на оператор instanceof в Java. Левым операндом должен быть проверяемый объект, а правым — проверяемый тип, который можно указать строкой литералом, переменной строкового типа или именем проверяемого класса непосредственно. Результатом операции будет истина, если правый операнд содержит название класса проверяемого объекта или он присутствует в иерархии наследования.\nname := \"class\"; # Строковая переменная с именем класса var ~ name; var ~ :class; # Имя типа var ~ \"class\"; # Строка литерал с именем типа Утиная типизация Оператор утиной типизации, два символа тильны ~~ — приблизительный аналог функции isinstance() в Python, который для простых типов сравнивает непосредственную совместимость типа левого операнда по отношению к правому. А для словарей и классов в левом операнде проверяется наличие всех имен полей, присутствующих у правого операнда, т.е.:\n(field1=«value», field2=2,) ~~ (); # Истина (т. е. левый операнд словарь) (field1=«value», field2=2,) ~~ (field1=_); # Тоже истина (т. к. поле field1 присутствует у левого операнда) (field1=«value», field2=2,) ~~ (not_found=_); # Ложь, т.к. поле not_found у левого операнда отсутствует Строгая утиная типизация ~~~ — для простых типов сравнивается идентичности типов без учета совместимости, а для составных типов происходит сравнение всех свойств с помощью оператора строгого равенства. Для данной операции, пустой тип совместим только с другим пустим типом.\nУправляющие конструкции К управляющим конструкциям языка NewLang относятся условный оператор, два вида циклов, оператор оценки выражения, оператор прерывания последовательности выполнения команд и перехват прерывания. Операторы проверки условий всегда указываются в квадратных скобках, а последовательность команд для выполнения - в фигурных.\nУсловный оператор В качестве оператора проверки условия используется синтаксическая конструкция, соответствующая по смыслу термину «следует», т.е. тире и угловая скобка -\u003e или с двумя тире для большей наглядности –\u003e. Такая запись условного оператора очень похожа на математическую и легко объединяется в последовательности для проверки множественных условий вида «else if».\nВ общем случае условный оператор имеет вид: [ условие ] -\u003e действие; или [ условие ] -\u003e {действие}; или [ условие1 || условие2 ] --\u003e {действие}, [_] --\u003e {действие иначе};\nДля наглядности записанный с отступами:\n[ условие1 ] -\u003e { действие1 }, [ условие2 ] -\u003e действие2, [ условие3 ] -\u003e действие3, [_] -\u003e {действие_иначе}; Оценка выражения Синтаксическая конструкция с помощью которой реализуется аналог оператора switch выглядит следующим образом:\n[ $var ] ==\u003e { [1] -\u003e { code }; # Выполнится проверка условия $var == 1 [1, 2] -\u003e { code }; # Выполнится проверка условия ($var == 1 || $var == 2) [_] -\u003e { code default }; # Ветка условия иначе }; Причем в качестве оператора для оценки могут быть использован любые имеющиеся операторы сравнения на равенство:\n==\u003e - проверка на равенство с приведением типов; ===\u003e - проверка на точное равенство; ~\u003e - проверка типа (имени класса); ~~\u003e - утиная типизация; ~~~\u003e - строгая утиная типизация. И если в качестве оператора сравнения использовать оператор утиной типизации, то оценка выражения превращается в классический Pattern Matching:\n$value := (f1=1, f2=\"2\",); [ $value ] ~~~\u003e { [ (f1=_, ), (f1=_, f2=0, ) ] -\u003e { code }; # Поле f2 отсутствует или число [(f1=_, f2=\"\",), (f1=_, f2='',)] -\u003e { code }; # Поле f2 строка [_] -\u003e { code default }; # Код по умолчанию }; Операторы циклов Для указания операторов циклов используются управляющие -» или –» (с двумя стрелками по направлению от проверки условия к телу цикла). И в зависимости от расположения условия и тела цикла, он может быть с предусловием (while) или постусловием (do while). Хотя пока эти синтаксические конструкции не “отлежались” и их можно считать временными из-за того, что их легко перепутать с условным оператором, и, возможно, имеет смысл заменить разные операторы цикла одной единственной конструкцией вида: \u003c–\u003e или «-», которая сильнее отличается от оператора следования.\nНо в настоящий момент циклы реализованы вот так:\n[условие while] -\u003e\u003e { тело цикла while }; { тело цикла do while } \u003c\u003c-- [условие do while]; Реализация цикла foreach на примере суммирования всех элементов словаря (или одномерного тензора):\nsumma := 0; dict := (1,2,3,4,5,); [ dict ] --\u003e\u003e { # Условие цикла, пока есть данные item, dict := ... dict; # Результат оператора раскрытия словаря - первый его элемент перемещается в item summa += item; # Вычисление суммы всех элементов словаря }; Операторы прерывания (возврата) В качестве оператора прерывания/возврата используется два символа минус –. Оператор позволяет прервать выполнение последовательности команд и/или вернуть данные из текущей функции/блока кода и является самым близким аналогом оператора return и throw одновременно. Для того чтобы вернуть данные, их необходимо указать между двумя операторами прерывания, т.е. --100--; # Вернуть указанное значение. Если возвращаемое значение не указано явно, то будет возвращено значение None.\nСледование (блок кода/лямбда функция) Алгоритмическая конструкция, которая отвечает последовательное выполнение нескольких команд/операторов и возвращающая результат выполнения последнего из них. Также, результатом выполнения может быть значение, которое возвращается с помощью оператора прерывания (возврата). Это очень похоже на классическую лямбда функцию, только она выполняется сразу во время определения, а в переменную сохраняется уже результат её выполнения.\nСледование без перехвата прерывания оформляется в виде последовательности обычных и фигурных скобок, т.е. (){ run code }; или тоже самое, но сохраняет результата выполнения в переменной: $result := (){ run(); code() };. Но если внутри такой функции будет выполнен оператор прерывания, то она никогда вернет управления и не сохранит возвращаемое значение в переменой $result!\nЧтобы перехватывать прерывания, в том числе и возвращаемые значения, необходимо использовать конструкция следования с перехватом прерываний, которая оформляется в виде последовательности обычных и двойных фигурных скобок, т.е. $error := (){{ run(); error();code() }};. Такая конструкция перехватывает все возвраты и прерывания, если они возникают во время выполнения последовательности команд. В этом случае любой результат будет сохранен в переменной $error как при нормальном завершении, так и в случае возникновения ошибки.\nДля более тонкой настройки перехвата прерываний следует использовать типизированную конструкцию, когда в явном виде указывается, какие типы прерываний следует перехватывать. $runtime := (){{ run(); error(); code() }}:ErrorRuntime;. Такая конструкция вернет результат только в случае успешного завершения (когда с помощью оператора прерывания возвращается не типизированное значение, например, --\"Строка\"--;), или при создании прерывания с указанием конкретного типа –:ErrorRuntime(“Описание ошибки”)–;. А вот при возникновении любого другого типизированного прерывания, значение перехвачено не будет и все отработает как самый первый вариант, т.е. без перехвата прерывания и без сохранения возвращаемого значения в переменную.\nСтратегия обработки ошибок Обработка ошибок состоит из комбинации двух элементов: оператора прерывания выполнения с указанием типа возвращаемого значения и алгоритмической конструкции следование с возможностью перехвата прерывания заданного типа.\nЭто немного отличается от классического варианта обработки исключений, который в обычных языках программирования обычно оформляется ключевыми словами try… catch… finally с различными вариациями. Ведь основная цель подобных синтаксических конструкций — выделить участок кода, где возможно возникновение ошибки, перехватить и обработать правильный тип данных (исключений), т.к. NewLang не делает различий между операторами возврата и генерации исключения.\nПодход к обработке исключений следующий: Программный код, который может привести к ошибке, заключается в двойные фигурные скобки, а результат выполнения такого блока кода присваивается переменной. После этого анализируется возвращенное значение, например, оператором сравнения по образцу:\n$result := (){{ # начало аналога блока try $value := call_or_exception1(); [условие1] -\u003e { -- :Error -- }; [условие2] -\u003e { -- $value -- }; $value := call_or_exception2(); }}; # конец аналога блока try [$result] ~\u003e { # Для сравнения по образцу использовать оператор проверки типа (имени класса) [:ErrorParser] -\u003e {Код обработки ошибок парсера}; [:ErrorRunTime] -\u003e {Код обработки ошибок времени выполнения}; [:Error] -\u003e { Код обработки остальных ошибок }; [_] -\u003e { Обработка нормальных данных $value без ошибок }; }; Сборка REPL из исходников (пока только под Linux) Подготовка репозитория Скачать исходники Скачать и развернуть архив libtorch в каталоге contrib (PyTorch Build: Stable (1.10.*) -\u003e Your OS: Linux -\u003e Package: LibTorch -\u003e Language: C++ / Java -\u003e Compute Platform: CPU -\u003e Download here (cxx11 ABI): libtorch-cxx11-abi-shared-with-deps-1.10.2+cpu.zip) Активировать и скачать исходники субмодулей (git submodule init \u0026\u0026 git submodule update) В каталоге contrib запустить файл build.sh для сборки библиотеки libffi В каталоге core запустить файл compile_syntax.sh для генерации файлов парсера и лексического анализатора. Также может потребоваться установка утилит flex и bison. Если что, у меня установлены flex 2.6.4 и bison (GNU Bison) 3.7.4 Собрать Юнит-тесты (newlang_test): в каталоге core выполнить команду make CONF=UnitTest* Интерпретатор (nlc): в каталоге core выполнить команду make CONF=Debug* *) - Сборка проекта выполняется обычной утилитой make, но сборочные файлы генерируются автоматически в давно устаревшей версии NetBeans 8.2, т.к. это единственная универсальная среда разработки с поддержкой Makefile “из коробки”, тогда как в текущей версии Apache NetBeans полноценная поддержка разработки на С/С++ вообще отсутствует. Начал постепенный переход на использование редактора VSCodium (аналога VSCode, в котором вычищена телеметрия от Microsoft) и генерацию скриптов сборки с помощью сmake, но этот процесс пока не завершен.\nПланы на будущее Текущая версия языка значительно обогатилась возможностями, но все еще является тестовой платформой для проверки декларируемых концепций и основного синтаксиса. Если говорить о планах, то в настоящий момент роадмап развития NewLang следующий:\nРеализовать макросы для более привычного использования языка (за счет использования DSL); Добавить в арифметические типы длинные числа и дроби; Сделать какую-нибудь логическую игру (крестики нолики, судоку или что-то похожее) с алгоритмическим выбором следующего хода и его вычислением с помощью машинного обучения; Написать еще больше разных примеров для оценки синтаксиса; Зафиксировать синтаксис с учетом полученного опыта и обратной связи; Восстановить работоспособность компилятора для генерации исполняемых файлов; Сделать очередную большую чистку кода; Переработать и задокументировать получившуюся семантику языка с учетом всех возможностей и выпустить первую полнофункциональную версию NewLang. ","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/blog/release-v0.1/","tags":"","title":"Релиз языка программрования NewLang"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nNewLang - это язык программирования высокого уровня, в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения.\nОсновной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка).\nНовое по сравнению с прошлым выпуском:\nРеализованы все основные алгоритмические конструкции: проверка условий, различные варианты циклов, сравнение по образцу, прерывание последовательности команд и возврат данных, обработка ошибок и т.д. Переработан основной синтаксис для отдельных языковых конструкций. Реализованы большинство операций с переменными, включая операторы раскрытие списков и тензоров. Серьезно переработана система встроенных типов, реализованы функции для их преобразования и для определения данных (последнее можно назвать data comprehensions). Добавлены новые тесты и пр. Зачем нужен NewLang? У всех современных языков программирования происходит постоянное развитие (читай усложнение) синтаксиса по мере выхода новых версий. Это является своего рода, платой за появление новых возможностей и воспринимается пользователями как естественное явление.\nНо одновременно является и серьезной проблемой, т.к. с выходом новых версий добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки и трудоемкости поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.\nУ NewLang сложность языковых конструкций естественно ограничена за счет разделения синтаксиса языка на две части, что упрощает его изучение и использование.\nОсновной синтаксис — для написания программ в объектно-ориентированном (императивном) и декларативном стилях, который основан не на зарезервированных ключевых словах, а на строгих грамматических правилах и Расширенный синтаксис — когда основного синтаксиса становится недостаточно, или требуется использовать языковую конструкцию языка реализации.\nЕще одно неудобство современных мейнстримовых языков, большинство из них были созданы до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек, а не встроены в основной синтаксис языка и систему базовых типов.\nУ NewLang тензорные вычисления доступны «из коробки» (используется библиотека libtorch), а обычные числа являются скалярами (тензорами нулевой размерности).\nСинтаксис NewLang При разработке синтаксиса я старался придерживаться уже сложившихся в IT индустрии правил, чтобы не генерировать множественных смыслов, которые будут зависеть от контекста.\nОсновы\nОператоры разделяются точкой с запятой «;». Отступы и переводы строк игнорируются (очень хотелось иметь возможность автоматического форматирование кода). Многострочные комментарии в исходном коде соответствуют стилю С/С++ и должны располагаться между символами /* и */. Вложенность многострочных комментариев не поддерживается. Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash. Последовательность команд, которая должна выполняться как единое целое, заключается в фигурные скобки «{}». Программные вставки расширенного синтаксиса на языке реализации заключается в фигурные скобки со знаком процента %{ /* тут может быть любой код на C/C++*/ %}, как в лексерах lex и flex. Создания объектов и присвоения новых значений Для создания объектов и присвоения им новых значений в NewLang используется сразу три разных оператора:\n::= используется только для создания новых объектов, а если объект с таким именем уже существует, то генерируется ошибка. := используется для тех же целей, но если объект с таким именем уже существует, то ошибки не происходит, а новое значение присваивается уже существующему объекту. = применяется только для присвоения значения уже существующим объектам, и если объект с указанным именем отсутствует, то тоже происходит ошибка выполнения. Использование трех разных операторов для создания/изменения объектов позволяет более гибко контролировать подобные операции и выявлять логические ошибки в коде на более раннем этапе.\nvar ::= 1.0; # Создать новую переменную var без указания типа var = 100; # Присвоить новое значение уже существующей переменной printf := @import('printf(format:Format, ...):Int'); /* Создать новый или переопределить объект printf, который будет результатом выполнения глобальной функции @import */ Идентификаторы объектов и модификаторы В качестве идентификаторов можно использовать буквы, цифры и знаки подчеркивания в любых комбинациях, при условии, что первый символ идентификатора не является цифрой.\nВ NewLang существует возможность указания области видимости и времени жизни объекта с помощью модификатора — специального символа перед именем переменной. Это может показаться немного похожим на венгерскую нотацию, но в отличие от нее, модификатор не имеет отношения к типу объекта и не является частью имени идентификатора. К тому же в качестве модификаторов используется строго определённые символы, назначение которых определено заранее.\n$ - в начале имени обозначает локальную переменную, время жизни которой ограничено текущей областью видимости и при её завершении локальная переменная уничтожается. @ - обозначает глобальную переменную, а сам объект сохраняет свое состояние даже после выхода из текущей области видимости. : - двоеточие вначале имени используется в качестве модификатора для указания типа. Семантика обращения к аргументам функций очень похоже на работу с аргументами в bash скриптах, где $1 или $arg — порядковый номер или имя аргумента (происходит обращение к локальным переменным в текущей области видимости).\nИспользование модификаторов является обязательным только в двух случаях: При создании нового типа данных, так как типы всегда создаются в глобальной области видимости, а их символьные имена должны быть уникальными. При обращении к объектам NewLang внутри программных вставок кода на языке реализации, так как они используется как маркеры при поиске идентификаторов NewLang в коде С/С++. В остальных случаях, для обращения к переменным указывать их модификаторы необязательно. И если при обращении к объекту модификатор не указан, то сперва ищется локальная переменная, а потом глобальная с таким же именем. Причем, локальная переменная будет перекрывать глобальную.\nТак же следует иметь в виду, что компилятор может генерировать код для прямого обращения к локальным объектам уже на этапе компиляции, тогда как для обращения к глобальным объектам, или если модификатор области видимости отсутствует, компилятор вынужден каждый раз встраивать runtime вызов функции поиска объекта в глобальной таблице символов.\nСистема типов Так как система типов языка динамическая, то явное указание типа не влияет на размер переменной и является только своего рода логическим ограничением на возможность присвоения переменной значения другого типа.\nИнформация о типах используется при проверке их совместимости, когда существующему объекту присваивается значение другого типа. Такая операция возможна только когда типы совместимы между собой и допускают автоматическое приведение. Это справедливо как во время парсинга/компиляции исходного теста, так и во время выполнения в режимах интерпретатора и/или скомпилированного файла.\nПростые типы Арифметические значения Арифметические типы данных являются тензорами — массивами чисел одного типа с произвольным количеством измерений и одинаковым размером столбцов в каждом. Единичное число тоже тензор нулевого размера.\nПоддерживаются только знаковые целые числа, т.к. в беззнаковых числах особая нужда отсутствует, а проблем с ними можно найти очень много на ровном месте.\nПроблемы беззнаковых чисел (из интернета):\nВо-первых, вычитание двух беззнаковых чисел, например 3 и 5. 3 минус 5 равно 4294967294, т.к. -2 не может быть представлено как беззнаковое число. Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных значений со знаком и без знака. С++ может свободно преобразовывать числа со знаком и без знака, но не проверяет диапазон, чтобы убедиться, что вы не переполняете свой тип данных. В C++ всё же есть несколько случаев, когда можно (или необходимо) использовать беззнаковые числа. Во-первых, числа без знака предпочтительнее при работе с битами. Во-вторых, использование беззнаковых чисел связанных с индексацией массивов.\nНо это не мой случай, так как индекс может быть отрицательным и даже не числом, а диапазоном или многоточием.\nЗ.Ы. И даже зная об этом, все равно умудрился недавно словить баг с отрицательными индексами у словарей!\nИмена встроенных арифметических типов говорят сами за себя: Char, Short, Int, Long, Float, Double, ComplexFloat, ComplexDouble. Отдельным типом идет логический тип Bool, который может принимать значения только 0 или 1 (false/true соответственно), и в зависимости от выполняемой операции может быть отнесен к целочисленным типам, так и не входить в их состав (данный подход интерпретации логического типа данных был взят из библиотеки Torch).\n// Treat bool as a distinct \"category,\" to be consistent with type promotion // rules (e.g. `bool_tensor + 5 -\u003e int64_tensor`). If `5` was in the same // category as `bool_tensor`, we would not promote. Differing categories // implies `bool_tensor += 5` is disallowed. // // NB: numpy distinguishes \"unsigned\" as a category to get the desired // `bool_tensor + 5 -\u003e int64_tensor` behavior. We don't, because: // * We don't want the performance hit of checking the runtime sign of Scalars. // * `uint8_tensor + 5 -\u003e int64_tensor` would be undesirable. В будущем планируется добавить классы чисел для длинной арифметики и дробей, для чего зарезервированы названия типов BigNum, Currency и Fraction.\nДоступ к элементам тензора происходит по целочисленному индексу, который начинается с 0. Для многомерного тензора, индексы элемента перечисляются в квадратных скобках через запятую. Поддерживается доступ к элементам через отрицательный индекс, который обрабатывается точно так же, как в Python (-1 последний элемент, -2 предпоследний и т.д.).\nЛитерал тензор в тексте программы записывается в квадратных скобках с обязательной завершающей запятой, т.е. [1, 2,] — это литерал одномерный тензор из двух чисел. После закрывающей скобки тип тензора может быть указан в явном виде. Если тип не указан, то он выводится автоматически на основании указанных данных и выбирается минимально возможный байтовый размер, который позволяет сохранить все значения без потери точности.\nПримеры:\n$var_char := 123; # Тип Char выводится автоматически $var_short := 1000; # Тип Short выводится автоматически $var_bool := [0, 1, 0, 1,]; # Тензор из 4 элементов. Тип Bool выводится автоматически $tensor[10,10]:Int := 1; # Тензор Int размером 2x2 инициализированный 1 $scalar := $tensor[5,5]; # Присвоить скаляру значение указанного элемента тензора Строки Поддерживаются два типа строк, StrWide — символьные (широкие) и StrChar — байтовые. Различия между ними заключается в типе единичного элемента. У символьных строк единичным элементом является широкий символ wchar_t, а у байтовой строки единичным элементом является один байт (точнее char, т.е. байт со знаком). Символьные строки литералы в исходном тексте записывается в «двойных кавычках», а байтовые строки в ‘одинарных кавычках’.\nКоличество элементов символьной строки возвращается в широких символах, а размер байтовой строки в байтах, поэтому и обращение к элементу строки по индексу происходит соответственно либо к символу, либо к байту.\nВажный момент. К любой переменной можно обратиться так же, как к функции (записав после её имени круглые скобки). Результатом этой операции будет создание копии/клона объекта. Причем некоторые типы (словари, классы и символьные строки) можно использовать в качестве шаблона при создании копии объекта с модифицированными свойствами, если новые и/или изменяемые значения указать в скобках, как аргументы при вызовах функций. Так, если при создании копии в скобках указать набор новых данных, то результирующая копия будет содержать уже измененные данные.\nНапример:\n$template := \"${name} $1\"; # Обычная строка $result := $template(\"шаблон\", name = \"Строка\"); # result = \"Строка шаблон\" Системные :Pointer - указатель на системную область памяти Так как любой программе приходится взаимодействовать с внешним миром, то по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип Pointer. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. Но можно вывести его значение, например для отладки.\n:Plain - указатель на представление данных в бинарном виде Для взаимодействия с внешними библиотеками требуется еще и обмен данными. И для этих целей служит тип данных Plain - который также является указателем, но на двоичное представление данных в единой области памяти. Конечно, если их можно представить в виде единого фрагмента.\nСоставные типы данных: Словарь Словарь (:Dictionary) — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии (он похож и на tuple и на структуру одновременно). Словари от тензоров отличаются тем, что являются только одномерными массивами, но каждый элемент может содержать произвольное количество элементов любого типа, в том числе и другие словари.\nДоступ к элементам словарей происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. Индекс также начинается с 0 и как у тензоров и тоже может быть отрицательным.\nЛитерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, т. е. (,) — пустой словарь, (1, 2= «2», name=3,).\nПеречисление, структура и объединение :Enum, :Struct и :Union — это такие же словари, только на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера.\nКлассы Класс (реализован частично) — тип данных, с помощью которого реализуется один из принципов ООП — наследование. При создании экземпляра класса создается новая переменная, у которой сохраняется информацию о своем родителе и которая наследует от него свойства и методы. Тип данных :Class аналогичен словарю, но все свойства обязаны иметь имена (хотя доступ к свойствам класса по индексу так же возможен).\nФункции Синтаксис NewLang поддерживать несколько типов функций (а в будущем и методов классов): обычные функции, чистые функции и простые чистые функции.\nДля всех типов функций поддерживаются аргументы по умолчанию. При создании функции, её аргументы указываются как в Python, т.е. вначале идут обязательные аргументы, потом аргументы со значениями по умолчанию, где имя аргумента отделяется от его значения по умолчанию знаком равно =. Если функция допускает обработку произвольного количества аргументов, то последним в списке параметров указывается многоточие … (три точки подряд) .\nОбычная функция Обычная функция — такие функции являются именно обычными функциями в понимании С/С++. Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д.\nВнутри обычной функции можно обращаться к локальным и глобальным объектам, и они могут содержаться вставки на языке реализации*, например, для вызова функций из внешних библиотек.\nВставки на языке реализации оформляются в виде %{ %} и могут содержать любой текст на С/С++, а прямо из него можно обращаться к локальным и глобальным объектам NewLang так же, как и в обычном синтаксисе, указывая первым символом имени соответствующий модификатор ($ для локальных объектов и @ для глобальных).\nТехнически, такая программная вставка просто переносится трансплайтером непосредственно в исходный текст генерируемого файла, а все идентификаторы NewLang специальным образом декорируются (добавляются специальные маркеры для их идентификации), после этого исходный текст подается на вход обычному компилятору С++. Для локальных объектов трансплайтер может генерировать код для прямого доступа к объекту на этапе компиляции, а для работы с глобальными объектами вынужден использовать runtime вызовы функции поиска в таблице символов.\n*) - Программные вставки на языке реализации обрабатываются только во время компиляции\nНапример:\nprint(str) := { %{ printf(\"%s\", static_cast\u003cconst char *\u003e($str)); /* Прямой вызов С функции */ %} }; Чистые функции Чистая функция — это тоже обычная функция, только в том смысле, какой в него вкладывает функциональное программирование. Создания чистой функции происходит с помощью оператора :-, а сам оператор заимствован из языка Пролог. У чистой функции отсутствует доступ к контексту и глобальным переменным, поэтому она может обрабатывать только те данные, которые были ей переданы в качестве аргументов.\nПрограммные вставки на языке реализации внутри чистых функций не запрещены и могут использоваться, например, для отладки. Но делается это на страх и риск разработчика. Именно он отвечает за их «чистоту», например при вызове функций из внешних библиотек.\nSum(arg1, arg2) :- {$arg1+$arg2;}; # Вернуть сумму аргументов Простые чистые функции Простые чистые функции — отдельный класс чистых функций, которые предназначены только для вычисления логического результата (т.е. они являются предикатами) и их отличает упрощенная формой записи. Тело простой чистой функции состоит из последовательности операторов, которые разделяются запятыми и заканчиваются, как и любое выражение, точкой с запятой. Все операторы простой чистой функции всегда приводятся к булевому значению, а итоговый результат функции вычисляется по одной из возможных логических операций: И, ИЛИ и исключающее ИЛИ.\nНапример:\nfunc_and(arg1, arg2) :\u0026\u0026= arg1==3, arg2 \u003e 0; # Простая чистая функция Логическое И func_or(arg1, arg2) :||= arg1==3, arg2 \u003e 0; # Простая чистая функция Логическое ИЛИ func_xor(arg1, arg2) :^^= arg1==3, arg2 \u003e 0; # Простая чистая функция Исключающее ИЛИ Специальные типы данных: Пусто (:None) :None (пусто) — не содержит значения (точнее имеет одно значение None) и совместим с любым другим типом данных. Указывается в тексте программы как один подчерк «_». None имеют не инициализированные переменные и при попытке чтения из такой переменной возникает ошибка.\nТип переменной может быть явно указан или выведен автоматически из присваиваемого значения. Присвоить новое значение уже инициализированной переменной можно только для совместимого типа, так как неявное преобразование типов не допускаются.\n$var := _; # Создать не инициализированную переменную $var2 := var; # Ошибка!!! Нельзя прочитать неинициализированную переменную var $var = 1000; # У переменной будет тип Short (минимальный размер для хранения значения) $var = 0,5; # Ошибка!!! Short ← Float не совместимы $var = _; # Очистить значение переменной $var = 0,5; # Теперь можно, т. к. None совместим с любым типом Диапазон (:Range) Диапазон — специальный тип данных, являющейся приблизительным аналогом типа «генератор» в Python. К диапазону можно обращаться как к итератору и он будет поочередно выдавать элементы в указанном интервале с заданным шагом. Диапазон в тексте программы указывается как два или три элемента через две точки, например 1..5 — диапазон от единицы до пяти с шагом по умолчанию 1. В качестве параметров диапазона можно указывать не только литералы, но и имена переменных. Например, 0,1..$stop..0,1 — диапазон от 0,1 до значения, указанного в переменной $stop с шагом 0,1.\nДиапазон для целых чисел можно использовать в качестве индекса у тензоров (точнее, у любых объектов, которые допускают доступ к своим элементам по индексу, т.е. тензоры, словари и текстовые строки). Фактический, это поведение аналогично slice в языке Python и array[1:5] в Python означает тоже самое, что и array[1..5] в NewLang.\nВ качестве индекса у тензоров еще можно указать произвольное количество измерений с помощью многоточия, т.е.\n$tensor[…, 0] = 0; # Обнулить все первые элементы в каждом измерении. Преобразование типов Явное приведение типов Несмотря на динамическую типизацию языка, если тип переменной указан явно, то автоматическое приведение типов не выполняется, и чтобы присвоить переменой значение не совместимого типа, требуется явное преобразование.\nТак как символьные названия типов относятся к деталям реализации, то явное преобразование в конкретный тип данных производится с помощью вызова функции с именем типа, т.е. :Bool(), :StrWide(), :Long() и т.д.\nДля преобразования любого типа данных в строку ещё можно использовать оператор конкатенации строк, которой преобразует любой тип данных в строковое представление. Но, так как строковых типов два (байтовые и широкие строки), то тип строки определяется первым аргументом в операторе конкатенации/сцепления ++. Также преобразовать любое значение в строковое можно с помощью строки-шаблона.\n\"\" ++ 123; # \"123\" - Строка широких символов '' ++ 123; # '123' - Байтовая строка val := 12345; # Число \"$1\"(val); # Будет строка \"12345\" Так как тензоры могут иметь больше одного значения, то и в качестве аргументов могут принимать их произвольное количество, а итоговым результатом будет тензор, в котором все переданные данные преобразованы к требуемому типу автоматически.\nПримеры:\n\u003e tstr := :Tensor(\"Тест\"); # Создать тензор из строки широких символов [1058, 1077, 1089, 1090,]:Int \u003e t2 := :Tensor[2,2](\"Тест\"); # Тоже самое, но тензор указанной размерности [ [1058, 1077,], [1089, 1090,], ]:Int \u003e :StrWide(tstr) # Создать символьную строку из тензора Тест \u003e :Double(t2) # Изменить тип данных тезора без изменения размерности [ [1058, 1077,], [1089, 1090,], ]:Double \u003e t3 := :Char[4]( t2 ) # Изменить размерность тензора и его тип (в данном случае с частичной потерей данных) [34, 53, 65, 66,]:Char \u003e:Tensor( (1,2,3,) ); # Тензор из словаря [1, 2, 3,]:Char \u003e:Tensor( 'first second' ) # Байтовая строка в тензор [102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char \u003e:Tensor( (first='first', space=32, second='second',) ) # Получаем тензор из словаря с такими же данными [102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char \u003e:Double[10,2]( 0, ...) # Тензор заданного формата с нулями, где многоточие повторяет последние указанные данные до получения тензора требуемого размера [ [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], ]:Double \u003e:Int[3,2]( ... rand() ...) # Тензор со случайными данными, где между многоточиями указана функция, которую следует вызывать каждый раз при получении нового элемента тензора # Пришлось придумывать новую конструкцию, т.к. многоточие перед именем, это оператор раскрытия словаря, а многоточие после имени, это повторение последнего значения до конца заданной размерности. [ [1804289383, 846930886,], [1681692777, 1714636915,], [1957747793, 424238335,], ]:Int \u003e:Int[5,2]( 0..10 ); # Создание тензора из диапазона [ [0, 1,], [2, 3,], [4, 5,], [6, 7,], [8, 9,], ]:Int \u003e:Tensor( 0..0.99..0.1 ); # Или даже так [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,]:Double Операторы и управляющие конструкции Операторы: Все операторы имеют парный аналог с присвоением значения:\n+ и += - сложение арифметических типов данных; - и -= - вычитание арифметических типов данных; / и /= - деление (результат число с плавающей точкой); // и //= - целочисленное деление с округлением к меньшему числу (как в Python); * и *= - умножение; ** и **= - возведение в степень (он же используется и для повторения текстовых строк); ++ и ++= - конкатенация строк с автоматическим приведением аргументов к стоковому типу (символ инкремента специально используется вместо одиночного плюса для того, чтобы в явном виде разделить конкатенацию строк и операторы арифметического сложения). Операторы сравнения: \u003c, \u003e, \u003c=, \u003e= - классические для сравнения скаляров == и != - операторы сравнения с автоматическим приведением совместимых типов для любых объектов === и !== - оператор точного сравнения для любых объектов (автоматического приведения типов не выполняется) Проверки типа (имени класса объекта): Для оператора проверки имени класса объекта используется символ тильда ~. Он немного похож на оператор instanceof в Java. Левым операндом должен быть проверяемый объект, а правым — проверяемый тип, который можно указать строкой литералом, переменной строкового типа или именем проверяемого класса непосредственно. Результатом операции будет истина, если правый операнд содержит название класса проверяемого объекта или он присутствует в иерархии наследования.\nname := \"class\"; # Строковая переменная с именем класса var ~ name; var ~ :class; # Имя типа var ~ \"class\"; # Строка литерал с именем типа Утиная типизация Оператор утиной типизации, два символа тильны ~~ — приблизительный аналог функции isinstance() в Python, который для простых типов сравнивает непосредственную совместимость типа левого операнда по отношению к правому. А для словарей и классов в левом операнде проверяется наличие всех имен полей, присутствующих у правого операнда, т.е.:\n(field1=«value», field2=2,) ~~ (); # Истина (т. е. левый операнд словарь) (field1=«value», field2=2,) ~~ (field1=_); # Тоже истина (т. к. поле field1 присутствует у левого операнда) (field1=«value», field2=2,) ~~ (not_found=_); # Ложь, т.к. поле not_found у левого операнда отсутствует Строгая утиная типизация ~~~ — для простых типов сравнивается идентичности типов без учета совместимости, а для составных типов происходит сравнение всех свойств с помощью оператора строгого равенства. Для данной операции, пустой тип совместим только с другим пустим типом.\nУправляющие конструкции К управляющим конструкциям языка NewLang относятся условный оператор, два вида циклов, оператор оценки выражения, оператор прерывания последовательности выполнения команд и перехват прерывания. Операторы проверки условий всегда указываются в квадратных скобках, а последовательность команд для выполнения - в фигурных.\nУсловный оператор В качестве оператора проверки условия используется синтаксическая конструкция, соответствующая по смыслу термину «следует», т.е. тире и угловая скобка -\u003e или с двумя тире для большей наглядности –\u003e. Такая запись условного оператора очень похожа на математическую и легко объединяется в последовательности для проверки множественных условий вида «else if».\nВ общем случае условный оператор имеет вид: [ условие ] -\u003e действие; или [ условие ] -\u003e {действие}; или [ условие1 || условие2 ] --\u003e {действие}, [_] --\u003e {действие иначе};\nДля наглядности записанный с отступами:\n[ условие1 ] -\u003e { действие1 }, [ условие2 ] -\u003e действие2, [ условие3 ] -\u003e действие3, [_] -\u003e {действие_иначе}; Оценка выражения Синтаксическая конструкция с помощью которой реализуется аналог оператора switch выглядит следующим образом:\n[ $var ] ==\u003e { [1] -\u003e { code }; # Выполнится проверка условия $var == 1 [1, 2] -\u003e { code }; # Выполнится проверка условия ($var == 1 || $var == 2) [_] -\u003e { code default }; # Ветка условия иначе }; Причем в качестве оператора для оценки могут быть использован любые имеющиеся операторы сравнения на равенство:\n==\u003e - проверка на равенство с приведением типов; ===\u003e - проверка на точное равенство; ~\u003e - проверка типа (имени класса); ~~\u003e - утиная типизация; ~~~\u003e - строгая утиная типизация. И если в качестве оператора сравнения использовать оператор утиной типизации, то оценка выражения превращается в классический Pattern Matching:\n$value := (f1=1, f2=\"2\",); [ $value ] ~~~\u003e { [ (f1=_, ), (f1=_, f2=0, ) ] -\u003e { code }; # Поле f2 отсутствует или число [(f1=_, f2=\"\",), (f1=_, f2='',)] -\u003e { code }; # Поле f2 строка [_] -\u003e { code default }; # Код по умолчанию }; Операторы циклов Для указания операторов циклов используются управляющие -» или –» (с двумя стрелками по направлению от проверки условия к телу цикла). И в зависимости от расположения условия и тела цикла, он может быть с предусловием (while) или постусловием (do while). Хотя пока эти синтаксические конструкции не “отлежались” и их можно считать временными из-за того, что их легко перепутать с условным оператором, и, возможно, имеет смысл заменить разные операторы цикла одной единственной конструкцией вида: \u003c–\u003e или «-», которая сильнее отличается от оператора следования.\nНо в настоящий момент циклы реализованы вот так:\n[условие while] -\u003e\u003e { тело цикла while }; { тело цикла do while } \u003c\u003c-- [условие do while]; Реализация цикла foreach на примере суммирования всех элементов словаря (или одномерного тензора):\nsumma := 0; dict := (1,2,3,4,5,); [ dict ] --\u003e\u003e { # Условие цикла, пока есть данные item, dict := ... dict; # Результат оператора раскрытия словаря - первый его элемент перемещается в item summa += item; # Вычисление суммы всех элементов словаря }; Операторы прерывания (возврата) В качестве оператора прерывания/возврата используется два символа минус –. Оператор позволяет прервать выполнение последовательности команд и/или вернуть данные из текущей функции/блока кода и является самым близким аналогом оператора return и throw одновременно. Для того чтобы вернуть данные, их необходимо указать между двумя операторами прерывания, т.е. --100--; # Вернуть указанное значение. Если возвращаемое значение не указано явно, то будет возвращено значение None.\nСледование (блок кода/лямбда функция) Алгоритмическая конструкция, которая отвечает последовательное выполнение нескольких команд/операторов и возвращающая результат выполнения последнего из них. Также, результатом выполнения может быть значение, которое возвращается с помощью оператора прерывания (возврата). Это очень похоже на классическую лямбда функцию, только она выполняется сразу во время определения, а в переменную сохраняется уже результат её выполнения.\nСледование без перехвата прерывания оформляется в виде последовательности обычных и фигурных скобок, т.е. (){ run code }; или тоже самое, но сохраняет результата выполнения в переменной: $result := (){ run(); code() };. Но если внутри такой функции будет выполнен оператор прерывания, то она никогда вернет управления и не сохранит возвращаемое значение в переменой $result!\nЧтобы перехватывать прерывания, в том числе и возвращаемые значения, необходимо использовать конструкция следования с перехватом прерываний, которая оформляется в виде последовательности обычных и двойных фигурных скобок, т.е. $error := (){{ run(); error();code() }};. Такая конструкция перехватывает все возвраты и прерывания, если они возникают во время выполнения последовательности команд. В этом случае любой результат будет сохранен в переменной $error как при нормальном завершении, так и в случае возникновения ошибки.\nДля более тонкой настройки перехвата прерываний следует использовать типизированную конструкцию, когда в явном виде указывается, какие типы прерываний следует перехватывать. $runtime := (){{ run(); error(); code() }}:ErrorRuntime;. Такая конструкция вернет результат только в случае успешного завершения (когда с помощью оператора прерывания возвращается не типизированное значение, например, --\"Строка\"--;), или при создании прерывания с указанием конкретного типа –:ErrorRuntime(“Описание ошибки”)–;. А вот при возникновении любого другого типизированного прерывания, значение перехвачено не будет и все отработает как самый первый вариант, т.е. без перехвата прерывания и без сохранения возвращаемого значения в переменную.\nСтратегия обработки ошибок Обработка ошибок состоит из комбинации двух элементов: оператора прерывания выполнения с указанием типа возвращаемого значения и алгоритмической конструкции следование с возможностью перехвата прерывания заданного типа.\nЭто немного отличается от классического варианта обработки исключений, который в обычных языках программирования обычно оформляется ключевыми словами try… catch… finally с различными вариациями. Ведь основная цель подобных синтаксических конструкций — выделить участок кода, где возможно возникновение ошибки, перехватить и обработать правильный тип данных (исключений), т.к. NewLang не делает различий между операторами возврата и генерации исключения.\nПодход к обработке исключений следующий: Программный код, который может привести к ошибке, заключается в двойные фигурные скобки, а результат выполнения такого блока кода присваивается переменной. После этого анализируется возвращенное значение, например, оператором сравнения по образцу:\n$result := (){{ # начало аналога блока try $value := call_or_exception1(); [условие1] -\u003e { -- :Error -- }; [условие2] -\u003e { -- $value -- }; $value := call_or_exception2(); }}; # конец аналога блока try [$result] ~\u003e { # Для сравнения по образцу использовать оператор проверки типа (имени класса) [:ErrorParser] -\u003e {Код обработки ошибок парсера}; [:ErrorRunTime] -\u003e {Код обработки ошибок времени выполнения}; [:Error] -\u003e { Код обработки остальных ошибок }; [_] -\u003e { Обработка нормальных данных $value без ошибок }; }; Сборка REPL из исходников (пока только под Linux) Подготовка репозитория Скачать исходники Скачать и развернуть архив libtorch в каталоге contrib (PyTorch Build: Stable (1.10.*) -\u003e Your OS: Linux -\u003e Package: LibTorch -\u003e Language: C++ / Java -\u003e Compute Platform: CPU -\u003e Download here (cxx11 ABI): libtorch-cxx11-abi-shared-with-deps-1.10.2+cpu.zip) Активировать и скачать исходники субмодулей (git submodule init \u0026\u0026 git submodule update) В каталоге contrib запустить файл build.sh для сборки библиотеки libffi В каталоге core запустить файл compile_syntax.sh для генерации файлов парсера и лексического анализатора. Также может потребоваться установка утилит flex и bison. Если что, у меня установлены flex 2.6.4 и bison (GNU Bison) 3.7.4 Собрать Юнит-тесты (newlang_test): в каталоге core выполнить команду make CONF=UnitTest* Интерпретатор (nlc): в каталоге core выполнить команду make CONF=Debug* *) - Сборка проекта выполняется обычной утилитой make, но сборочные файлы генерируются автоматически в давно устаревшей версии NetBeans 8.2, т.к. это единственная универсальная среда разработки с поддержкой Makefile “из коробки”, тогда как в текущей версии Apache NetBeans полноценная поддержка разработки на С/С++ вообще отсутствует. Начал постепенный переход на использование редактора VSCodium (аналога VSCode, в котором вычищена телеметрия от Microsoft) и генерацию скриптов сборки с помощью сmake, но этот процесс пока не завершен.\nПланы на будущее Текущая версия языка значительно обогатилась возможностями, но все еще является тестовой платформой для проверки декларируемых концепций и основного синтаксиса. Если говорить о планах, то в настоящий момент роадмап развития NewLang следующий:\nРеализовать макросы для более привычного использования языка (за счет использования DSL); Добавить в арифметические типы длинные числа и дроби; Сделать какую-нибудь логическую игру (крестики нолики, судоку или что-то похожее) с алгоритмическим выбором следующего хода и его вычислением с помощью машинного обучения; Написать еще больше разных примеров для оценки синтаксиса; Зафиксировать синтаксис с учетом полученного опыта и обратной связи; Восстановить работоспособность компилятора для генерации исполняемых файлов; Сделать очередную большую чистку кода; Переработать и задокументировать получившуюся семантику языка с учетом всех возможностей и выпустить первую полнофункциональную версию NewLang. ","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/ru/blog/release-v0.1/","tags":"","title":"Релиз языка программрования NewLang"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nБолее года назад я начал публикацию статей с описанием особенностей нового языка программирования. С тех пор утекло много воды, было протестировано множество идей, в итоге несколько раз все поменялось кардинальным образом и сейчас представляю на суд читателей описание предфинальной версии языка и его особенностей.\nДанная статья предназначена в первую очередь для проверки основных концепций нового языка программирования, а также для получения обратной связи от читателей Хабра. Ведь согласно наблюдению Хабр-ума палата, не замыленный взгляд со стороны очень сильно помогает в проработке новых идей.\nЭтот проект очень долго был без собственного названия и в публикациях назывался просто и абстрактно “новый язык”. Но после нескольких статей, временное название “новый язык” постепенно превратилось в имя собственное NewLang, которое я и решил в конечном итоге оставить (что еще раз подтверждает поговорку, что нет ничего более постоянного, чем что-то временное).\nNewLang - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения.\nОсновной особенностью языка является легкий, логичный и непротиворечивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка). Основные свойства и особенности языка:\nВозможность работы как в режиме интерпретатора, так и компилятора. Динамическая и статическая типизация с возможностью указания типов в явном виде. Статическая типизация является условно строгой (автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных, например, целое число может быть автоматически преобразовано в вещественное, но не наоборот) Автоматическое управление памятью. ООП в виде явного наследования классов и утиная типизация. На уровне синтаксиса поддержка нескольких типов функций (обычные и чистые функции без побочных эффектов). Необязательные и именованные параметры функций. Возможны вставки кода на языке реализации (С/С++). Простая интеграция с уже существующими программными библиотеками (в том числе импорт нативных переменных и функций из С/С++). Имеется REPL read-eval-print loop — «цикл: чтение — вычисление — вывод». Зачем нужен NewLang? У всех современных языков программирования происходит постоянное развитие (читай усложнение) синтаксиса по мере выхода новых версий. Это является своего рода, платой за появление новых возможностей и воспринимается пользователями как естественное явление.\nНо одновременно является и серьезной проблемой, т.к. с выходом новых версий добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки и трудоемкости поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.\nУ NewLang сложность языковых конструкций естественно ограничена за счет разделения синтаксиса языка на две части, что упрощает его изучение и использование. Основной синтаксис — для написания программ в объектно-ориентированном (императивном) и декларативном стилях, который основан не на зарезервированных ключевых словах, а на строгих грамматических правилах и Расширенный синтаксис — когда основного синтаксиса становится недостаточно, или требуется использовать языковую конструкцию языка реализации.\nЕще одно неудобство современных мейнстримовых языков, большинство из них были созданы до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек, а не встроены в основной синтаксис языка и систему базовых типов. У NewLang тензорные вычисления доступны «из коробки» (используется библиотека libtorch), а арифметические типы данных являются скалярами (тензорами нулевой размерности).\nОсновной синтаксис Основной синтаксис NewLang - простой и логичный за счет того, что он построен исключительно на грамматических правилах и не использует каких либо зарезервированных ключевых слов, а все буквенно-символьные последовательности рассматриваются как идентификаторы в которых можно использовать любые не-ASCII символы.\nИдеализированная цель отказа от ключевых слов, приблизить чтение исходного текста программы к чтению обычного текста за счет использования знаков препинания при описании логики работы алгоритма.\nКонечно запятая человек может вычленять ключевые управляющие слова языка и слеш или учитывать форматирование программы запятая чтобы на их основе понимать синтаксические конструкции запятая хотя при обычном чтении мы привыкли опираться именно на семантику знаков препинания точка мы конечно можем писать знаки препинания и обычным текстом точка но согласитесь запятая что тогда открытая скобка например запятая вот такой вот текст закрытая скобка будет очень не удобно читать точка\nНазвания встроенных типов или имена служебных функций системной библиотеки определяются конкретной реализацией языка, поэтому не являются зарезервированными ключевыми словами и при необходимости могут быть переопределены, например, для создания собственного, предметно-ориентированного диалекта (DSL - domain-specific language), если в этом возникнет необходимость. Но сама структура программы и логика выполняемого алгоритма все равно останутся понятны всем, кто знаком с правилами основного синтаксиса NewLang.\nПример скрипта Hello world! на NewLang\n#!./nlc --eval # Определение функции hello hello(str) := { printf := @import('printf(format:Format, ...):Int'); # Импорт стандартной C функции printf('%s\\n', $str); # Вызов C функции с проверкой типов аргументов по строке формата }; hello('Привет, мир!'); # Вызвать функцию Вывод: Привет, мир!\nРасширенный синтаксис Расширенный синтаксис — это возможность вставить в текст программы NewLang исходный код на языке реализации. Сейчас это С/С++, что позволяет использовать любые возможности этого мощного языка программирования.\nОбработка расширенного синтаксиса происходит на этапе компиляции приложения, а взаимодействие между основным и расширенным синтаксисами происходит за счет совместного использования идентификаторов, которое полностью прозрачно для пользователя и подчиняется единым грамматическим правилам основного синтаксиса.\nЕще немного примеров: Любая последовательность вычислений возвращает результат выполнения последнего оператора. Поэтому выполнение одной команды или последовательности команд всегда возвращает какой-либо результат, а оператор возврата из функции необязателен, так как результатом будет значение последнего вычисленного выражения.\nСоздание переменных\nscalar := 42 42 tensor := [1,2,3,4,5,] # Тип тензора выводится автоматически [1, 2, 3, 4, 5,]:Char str := '$1 string' $1 string Арифметические операции\ntensor * 2 [2, 4, 6, 8, 10,]:Short tensor * 20 [20, 40, 60, 80, 100,]:Short tensor * 0.5 [0.5, 1, 1.5, 2, 2.5,]:Double tensor / 2 # Результат деления — число с плавающей точкой [0.5, 1, 1.5, 2, 2.5,]:Double tensor // 2 # Целочисленное деление без остатка [0, 1, 1, 2, 2,]:Char\u003c/source\u003e tensor % 2 # Целочисленный остаток от деления [1, 0, 1, 0, 1,]:Char\u003c/source\u003e Строковые операции\nstr = 'сцепеление строк ' ++ str; сцепеление строк $1 string str('строка как шаблон'); сцепеление строк строка как шаблон string Преобразование тензоров В эпоху машинного обучения тензоры являются основными элементами вычислений, поэтому для конвертирования данных в тензоры используется отдельная синтаксическая конструкция, состоящая из двойных квадратных скобок [[ данные ]]. Подробнее про особенности преобразования типов можно прочитать далее.\ntstr := [[\"Тест\"]] # Создать тензор из строки широких символов [1058, 1077, 1089, 1090,]:Int t2 := [[ \"Тест\" ]]:Int[2,2] # Тоже самое, но тензор двухмерный [ [1058, 1077,], [1089, 1090,], ]:Int\u003c/source\u003e StrWide(tstr) # Конвертировать тензор обратно в строку Тест Double(t2) # Изменить тип данных тезора [ [1058, 1077,], [1089, 1090,], ]:Double t3 := [[ t2 ]]:Char[4] # Преобразовать тип данных тензора и его размерность [34, 53, 65, 66,]:Char Синтаксис NewLang: При разработке синтаксиса я старался придерживаться уже сложившихся правил, чтобы не создавать множественных смыслов, зависящих от контекста. И одновременно «объять необъятное»\nОсновы Операторы разделяются точкой с запятой «;». Отступы и переводы строк игнорируются (очень хотелось иметь возможность автоматического форматирование кода). Многострочные комментарии в исходном коде соответствуют стилю С/С++ и должны располагаться между символами /* и */. Вложенность многострочных комментариев не поддерживается. Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash. Последовательность выполняемых команд, которая должна выполняться как единое целое, заключается в фигурные скобки «{}». Программные вставки расширенного синтаксиса на языке реализации заключается в фигурные скобки со знаком процента %{ /* тут может быть любой код на C/C++*/ %}. Создания объектов и присвоения новых значений Для создания объектов и присвоения им новых значений в NewLang используется сразу три разных оператора.\nОператор «::=» используется только для создания новых объектов, а если объект с таким именем уже существует, то генерируется ошибка.\nОператор «:=» используется для тех же целей, но если объект с таким именем уже существует, то ошибки не происходит, а новое значение присваивается уже существующему объекту.\nИ последний оператор «=» применяется только для присвоения значения уже существующим объектам, и если объект с указанным именем отсутствует, то тоже происходит ошибка.\nИспользование трех разных операторов для создания/изменения объектов позволяет более гибко контролировать подобные операции и выявлять логические ошибки в коде на более раннем этапе.\nvar ::= 1.0; # Создать новую переменную var без указания типа var = 100; # Присвоить новое значение уже существующей переменной printf := @import('printf(format:Format, ...):Int'); /* Создать новый или переопределить объект printf, который будет результатом выполнения глобальной функции @import */ Идентификаторы объектов и модификаторы В качестве идентификаторов можно использовать буквы, цифры и знаки подчеркивания в любых комбинациях, при условии, что первый символ идентификатора не является цифрой.\nВ NewLang существует возможность указания области видимости и времени жизни объекта с помощью модификатора — специального символа перед именем переменной. Это может показаться немного похожим на венгерскую нотацию, но в отличие от нее, модификатор не имеет отношения к типу объекта и не является частью имени идентификатора. К тому же в качестве модификаторов используется строго определённые символы, назначение которых определено заранее.\nТак, символ «$» в начале имени обозначает локальную переменную, время жизни которой ограничено текущей областью видимости и при её завершении локальная переменная уничтожается. Символ «@» обозначает глобальную переменную, а сам объект сохраняет свое состояние даже после выхода из текущей области видимости. Так же обозначаются и имена типов данных, например, при создания новых типов, а в качестве модификатора используется символа двоеточия «:»\nСемантика обращения к аргументам функций очень похоже на работу с аргументами в bash скриптах, где $1 или $arg — порядковый номер или имя аргумента (происходит обращение к локальным переменным в текущей области видимости).\nИспользование модификаторов является обязательным только в двух случаях: - При создании нового типа данных, так как типы всегда создаются в глобальной области видимости, а их символьные имена должны быть уникальными - При обращении к объектам NewLang внутри программных вставок кода на языке реализации, так как они используется как маркеры при поиске идентификаторов NewLang в коде С/С++.\nВ остальных случаях, для обращения к переменным указывать их модификаторы не обязательно. И если при обращении к объекту модификатор не указан, то сперва ищется локальная переменная, а потом глобальная с таким же именем. Причем, локальная переменная будет перекрывать глобальную.\nТак же следует иметь в виду, что компилятор может генерировать код для прямого обращения к локальным объектам уже на этапе компиляции, тогда как для обращения к глобальным объектам, или если модификатор области видимости отсутствует, компилятор вынужден каждый раз встраивать runtime вызов функции поиска объекта в таблице символов.\nСистема типов Так как система типов языка динамическая, то явное указание типа не влияет на размер переменной и является только своего рода логическим ограничением на возможность присвоения переменной значения другого типа.\nИнформация о типах используется при проверке их совместимости, когда существующему объекту присваивается значение другого типа. Такая операция возможна только когда типы совместимы между собой и допускают автоматическое приведение. Это справедливо как во время парсинга/компиляции исходного теста, так и во время выполнения в режимах интерпретатора и/или скомпилированного файла.\nАрифметические типы: Арифметические типы данных являются тензорами - массивами чисел одного типа с произвольным количеством измерений и одинаковым размером столбцов в каждом. Единичное число тоже тензор нулевого размера.\nПоддерживаются только знаковые целые числа, т.к. в беззнаковых числах особая нужда отсутствует, а проблем с ними можно найти очень много на ровном месте.\nПроблемы беззнаковых чисел (из интернета)\nВо-первых, вычитание двух беззнаковых чисел, например 3 и 5. 3 минус 5 равно 4294967294, т.к. -2 не может быть представлено как беззнаковое число. Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных значений со знаком и без знака. С++ может свободно преобразовывать числа со знаком и без знака, но не проверяет диапазон, чтобы убедиться, что вы не переполняете свой тип данных.\nВ C++ всё же есть несколько случаев, когда можно (или необходимо) использовать беззнаковые числа. Во-первых, числа без знака предпочтительнее при работе с битами. Во-вторых, использование беззнаковых чисел связаных с индексацией массивов.\nНо это мой случай, так как индекс может быть отрицательным и даже не числом, а диапазоном или многоточием. З.Ы. И даже зная об этом, все равно умудрился недавно словить баг с отрицательными индексами у словарей!\nИмена встроенных арифметических типов говорят сами за себя: Char, Short, Int, Long, Float, Double, ComplexFloat, ComplexDouble. Отдельным типом идет логический тип Bool, который может принимать значения только 0 или 1 (false/true соответственно), и в зависимости от выполняемой операции может быть отнесен к целочисленным типам, так и не входить в их состав.\n(данный подход интерпретации логического типа данных был взят из библиотеки Torch)\n// Treat bool as a distinct \"category,\" to be consistent with type promotion // rules (e.g. `bool_tensor + 5 -\u003e int64_tensor`). If `5` was in the same // category as `bool_tensor`, we would not promote. Differing categories // implies `bool_tensor += 5` is disallowed. // // NB: numpy distinguishes \"unsigned\" as a category to get the desired // `bool_tensor + 5 -\u003e int64_tensor` behavior. We don't, because: // * We don't want the performance hit of checking the runtime sign of Scalars. // * `uint8_tensor + 5 -\u003e int64_tensor` would be undesirable. В будущем планируется добавить классы чисел для длинной арифметики и дробей, для чего зарезервированы названия типов BigNum, Currency и Fraction.\nДоступ к элементам тензора происходит по целочисленному индексу, который начинается с 0. Для многомерного тензора, индексы элемента перечисляются в квадратных скобках через запятую. Поддерживается доступ к элементам через отрицательный индекс, который обрабатывается точно так же, как в Python (-1 последний элемент, -2 предпоследний и т.д.).\nЛитерал тензор в тексте программы записывается в квадратных скобках с обязательной завершающей запятой, т.е. [1, 2,] - это литерал одномерный тензор из двух чисел. После закрывающей скобки тип тензора может быть указан в явном виде. Если тип не указан, то он выводится автоматически на основании указанных данных и выбирается минимально возможный байтовый размер, который позволяет сохранить все значения без потери точности.\nПримеры:\n$var_char := 123; # Тип Char выводится автоматически $var_short := 1000; # Тип Short выводится автоматически $var_bool := [0, 1, 0, 1,]; # Тензор из 4 элементов. Тип Bool выводится автоматически $tensor[10,10]:Int := 1; # Тензор Int размером 2x2 инициализированный 1 $scalar := $tensor[5,5]; # Присвоить скаляру значение указанного элемента тензора Строковые типы данных: Поддерживаются два типа строк, StrWide - символьные (широкие) и StrChar — байтовые. Различия между ними заключается в типе единичного элемента. У символьных строк единичным элементом является широкий символ wchar_t, а у байтовой строки единичным элементом является один байт (точнее char, т. е. байт со знаком). Символьные строки литералы в исходном тексте записывается в «двойных кавычках», а байтовые строки в ‘одинарных кавычках’.\nКоличество элементов символьной строки возвращается в широких символах, а размер байтовой строки в байтах, поэтому и обращение к элементу строки по индексу происходит соответственно либо к символу, либо к байту.\nВажный момент. К любой переменной можно обратиться так же, как к функции (записав после её имени круглые скобки). Результатом этой операции будет создание копии/клона объекта. Причем некоторые типы (словари, классы и символьные строки) можно использовать в качестве шаблона при создании копии объекта с модифицированными свойствами, если новые и/или изменяемые значения указать в скобках, как аргументы при вызовах функций. Так, если при создании копии в скобках указать набор новых данных, то результирующая копия будет содержать уже измененные данные.\nНапример:\n$template := \"${name} $1\"; # Обычная строка $result := $template(\"шаблон\", name = \"Строка\"); # result = \"Строка шаблон\" Составные типы данных: Словарь Словарь — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии (он похож и на tuple и на структуру одновременно). Словари от тензоров отличаются тем, что являются только одномерными массивами, но каждый элемент может содержать произвольное количество элементов любого типа, в том числе и другие словари.\nДоступ к элементам словарей происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. Индекс также начинается с 0 и как у тензоров, тоже может быть отрицательным.\nЛитерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, т.е. (,) - пустой словарь, (1, 2= «2», name=3,).\nПеречисление Перечисление - это не отдельный тип данных, а обычный словарь, у которого все элементы имеют уникальные имена и целочисленные значение, которое явно указывается при определении или вычисляется автоматически (на единицу больше предыдущего элемента). У перечислений тип значения указывается сразу после закрывающей скобки через двоеточие (ONE=1, TWO=, THREE=): Int.\nКлассы Класс (реализовано частично) - тип данных, с помощью которого реализуется один из принципов ООП - наследование. При создании экземпляра класса создается новая переменная, у которой сохраняется информацию о своем родителе и которая наследует от него свойства и методы. Тип данных «класс» аналогичен словарю, но все свойства обязаны иметь имена (хотя доступ к свойствам класса по индексу так же возможен). Литерал с типом «Класс» в тексте программы записывается в круглых скобках без завершающей запятой, т. е. () - пустой класс, (1, 2= «2», name=3).\nПока остальные детали классов до конца не реализованы, поэтому описывать их не буду, т. к. в итоговом варианте синтаксис классов и определения их методов могут поменяться.\nФункции Синтаксис NewLang поддерживать несколько типов функций (а в будущем и методов классов): обычные функции, чистые функции и простые чистые функции.\nДля всех типов функций поддерживаются аргументы по умолчанию. При создании функции, её аргументы указываются как в Питоне, т.е. вначале идут обязательные аргументы, потом аргументы со значениями по умолчанию, где имя аргумента отделяется от его значения по умолчанию знаком равно «=». Если функция допускает обработку произвольного количества аргументов, то последним в списке параметров указывается многоточие.\nОбычная функция Обычная функция — такие функции являются именно обычными функциями в понимании С/С++. Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д.\nВнутри обычной функции можно обращаться к локальным и глобальным объектам, и они могут содержаться вставки на языке реализации, например, для вызова функций из внешних библиотек.\nВставки на языке реализации оформляются в виде %{ %} и могут содержать любой текст на С/С++, а прямо из него можно обращаться к локальным и глобальным объектам NewLang так же, как и в обычном синтаксисе, указывая первым символом имени соответствующий модификатор ($ для локальных объектов и @ для глобальных).\nТехнически, такая программная вставка просто переносится трансплайтером непосредственно в исходный текст генерируемого файла, а все идентификаторы NewLang специальным образом декорируются (добавляются специальные маркеры для их идентификации), после этого исходный текст подается на вход обычному компилятору С++. Для локальных объектов трансплайтер может генерировать код для прямого доступа к объекту на этапе компиляции, а для работы с глобальными объектами вынужден использовать runtime вызовы функции поиска в таблице символов.\nНапример:\nprint(str) := { %{ printf(\"%s\", static_cast\u003cconst char *\u003e($str)); /* Прямой вызов С функции */ %} }; Чистые функции Чистая функция - это тоже обычная функция, только в том смысле, какой в него вкладывает функциональное программирование. Создания чистой функции происходит с помощью оператора «:-». У чистой функции отсутствует доступ к контексту и глобальным объектам, поэтому она может обрабатывать только те данные, которые были ей переданы в качестве аргументов.\nПрограммные вставки на языке реализации внутри чистых функций не запрещены и могут использоваться, например, для отладки. Но делается это на страх и риск разработчика. Именно он отвечает за их «чистоту», например при вызове функций из внешних библиотек.\nSum(arg1, arg2) :- {$arg1+$arg2;}; # Вернуть сумму аргументов Так как в языке отсутствует оператор возврата данных из текущего блока выполнения (аналог оператора return \u003cданные\u003e), то возвращаемым значением функции / блока кода всегда является результат выполнения последней операции.\nПростые чистые функции Простые чистые функции — отдельный класс чистых функций, которые предназначены только для вычисления логического результата (т.е. они являются предикатами) и их отличает упрощенная формой записи. Тело простой чистой функции состоит из последовательности операторов, которые разделяются запятыми и заканчиваются, как и любое выражение, точкой с запятой. Все операторы простой чистой функции всегда приводятся к булевому значению, а итоговый результат функции вычисляется по одной из возможных логических операций: И, ИЛИ и исключающее ИЛИ.\nНапример:\nfunc_and(arg1, arg2) \u0026\u0026= arg1==3, arg2 \u003e 0; # Простая чистая функция Логическое И func_or(arg1, arg2) ||= arg1==3, arg2 \u003e 0; # Простая чистая функция Логическое ИЛИ func_xor(arg1, arg2) ^^= arg1==3, arg2 \u003e 0; # Простая чистая функция Исключающее ИЛИ Специальные типы данных: None None (пустой тип) — не содержит значения (точнее имеет одно значение None) и совместим с любым другим типом данных. Указывается в тексте программы как один подчерк «_». Значение None имеют не инициализированные переменные и при попытке чтения из такой переменной возникает ошибка.\nТип переменной может быть явно указан или выведен автоматически из присваиваемого значения. Присвоить новое значение уже инициализированной переменной можно только для совместимого типа, так как неявное преобразование типов не допускаются.\n$var := _; # Создать переменную со значением None $var2 := var; # Ошибка!!! Нельзя прочитать неинициализированную переменную var $var = 1000; # У переменной будет тип Short (минимальный размер для хранения значения) $var = 0,5; # Ошибка!!! Short ← Float не совместимы $var = _; # Очистить значение переменной $var = 0,5; # Теперь можно, т. к. None совместим с любым типом Диапазон (Range) Диапазон (реализовано частично) — специальный тип данных, являющейся приблизительным аналогом типа «генератор» в Python. К диапазону можно обращаться как к итератору и он будет поочередно выдавать элементы в указанном интервале с заданным шагом. Диапазон в тексте программы указывается как два или три элемента через две точки, например 1..5 — диапазон от единицы до пяти с шагом по умолчанию 1. В качестве параметров диапазона можно указывать не только литералы, но и имена переменных. Например, 0,1..$stop..0,1 — диапазон от значения 0,1 до значения, указанного в переменной $stop с шагом 0,1.\nДиапазон для целых чисел можно использовать в качестве индекса у тензоров (точнее, у любых объектов, которые допускают доступ к своим элементам по индексу, т.е. тензоры, словари и текстовые строки). Фактический, это поведение аналогично slice в языке Python и array[1:5] в Python означает тоже самое, что и array[1..5] в NewLang.\nВ качестве индекса у тензоров еще можно указать произвольное количество измерений с помощью многоточия, т.е.\n$tensor[…, 0] = 0; # Обнулить все первые элементы в каждом измерении. Итераторы Итераторы (в разработке) - самый сложный и неоднозначный тип данных для работы с элементами коллекций.\nДля работы с итераторами зарезервированы символы “!” и “?”, но сами итераторы пока не реализованы.\nПреобразование типов Явное приведение типов Несмотря на динамическую типизацию языка, если тип переменной указан явно, то автоматическое приведение типов не выполняется, и чтобы присвоить переменой значение не совместимого типа, требуется явное преобразование.\nТак как символьные названия типов относятся к деталям реализации, то явное преобразование в конкретный тип данных производится с помощью вызова функции с системным именем, т. е. Bool(), StrWide(), Long и т. д. Причем у тензоров при таком преобразовании изменяется только тип данных, но размерность тензора не меняется.\nДля преобразования любого типа данных в строку ещё можно использовать оператор конкатенации строк, которой преобразует любой тип данных в строковое представление. Но так как строковых типов два (байтовые и широкие строки), то тип строки определяется первым аргументом в операторе конкатенации, т. е.\n\"\" ++ 123 # \"123\" - Строка широких символов '' ++ 123 # '123' - Байтовая строка Или преобразовать любое значение в строковое с помощью строки-шаблона: val := 12345; \"$1\"(val) # Будет строка \"12345\" Tensor comprehensions В эпоху машинного обучения тензоры являются основным элементом вычислений, поэтому для конвертирования данных в тензоры используется отдельная синтаксическая конструкция, состоящая из двойных квадратных скобок [[ данные ]]. Фактически это оператор и функция времени выполнения в зависимости от указанных между двойные квадратными скобками выражения.\nЧтобы преобразовать любую переменную в тензор (с учетом допустимости такого преобразования), её достаточно указать между двойными квадратными скобками. Выражение [[ varibale ]] - преобразует переменную varibale в одномерный тензор с автоматическим выводом типа данных. Для преобразования в одномерный тензор конкретного типа используется выражение [[ varibale ]]:Type, где _Type- - любой из арифметических типов.\nЕсли требуется преобразовать переменную не в одномерный тензор, а в тензор конкретного типа и заданной размерности, то это делается выражением [[ varibale ]]:Type[2,2], которая вернет тензор с размерностью 2х2 и типом Type у элементов.\nВнутри двойных квадратных скобок может быть не только любое выражение, но и литерал или диапазон. В этом случае, они также раскрываются в тензор по таким же правилам.\nВ будущем планирую добавить возможность указания сразу нескольких значений через запятую для их объединения в один тензор.\nПримеры:\n\u003e[[(1,2,3)]] # Тензор из словаря [1, 2, 3,]:Char \u003e[['first second']] # Байтовая строка в тензор [102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char \u003e [[(first='first', space=32, second='second')]] # Получаем тензор из словаря с такими же данными [102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char \u003e[[ 0 ... ]]:Double[10,2] # Тензор заданного формата с нулями [ [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], ]:Double \u003e[[ rand() ... ]]: Int[3,2] # Тензор со случайными данными [ [1804289383, 846930886,], [1681692777, 1714636915,], [1957747793, 424238335,], ]:Int \u003e[[ 0..10 ]]: Int[5,2] # Тензор из диапзона [ [0, 1,], [2, 3,], [4, 5,], [6, 7,], [8, 9,], ]:Int \u003e[[ 0..0.99..0.1 ]] # Или даже так [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,]:Double\u003c/source\u003e Операторы и управляющие конструкции Операторы: Все операторы имеют парный оператор с присвоением значения.\n+ и += сложение арифметических типов данных и -= вычитание арифметических типов данных / и /= деление (результат число с плавающей точкой) // и //= целочисленное деление с округлением к меньшему числу (как в Python) и *= умножение ** и **= возведение в степень (он же используется и для повторения текстовых строк) ++ и ++= конкатенация строк с автоматическим приведением аргументов к стоковому типу (символ инкремента специально используется вместо одиночного плюса для того, чтобы в явном виде разделить конкатенацию строк и операторы арифметического сложения) Операторы сравнения: \u003c, \u003e, \u003c=, \u003e= классические для сравнения скаляров ==, != операторы сравнения с автоматическим приведением совместимых типов для любых объектов ===, !== оператор точного сравнения для любых объектов (автоматического приведения типов не выполняется)s Проверки типов (в разработке): Проверка имени класса «~» - немного похож на оператор instanceof в Java. Левым оператором должен быть проверяемый объект, а правым оператором - название типа, строка литерал или объект строкового типа с именем класса. Результатом операции будет истина, если правый операнд содержит название класса проверяемого объекта или он присутствует в иерархии наследования у проверяемого класса.\nname := \"class\"; # Строка с именем класса var ~ :class; var ~ \"class\"; var ~ name; (field1=«value», field2=2, field3=«33»,) ~~ (); # Истина (т. е. левый операнд словарь) (field1=«value», field2=2, field3=«33»,) ~~ (field1=_); # Тоже истина (т. к. поле field1 присутствует у левого операнда) Утиная типизация «~~» - приблизительный аналог функции isinstance() в Python, который для простых типов сравнивает совместимость типа левого операнда по отношению к правому, а для словарей и классов в левом операнде проверяется наличие всех имен полей, присутствующих у правого операнда. т. е.\n(field1=«value», field2=2, field3=«33»,) ~~ (); # Истина (т. е. левый операнд словарь) (field1=«value», field2=2, field3=«33»,) ~~ (field1=_); # Тоже истина (т. к. поле field1 присутствует у левого операнда) Строгая утиная типизация «~~~» - для простых типов сравнивается идентичности типов без учета совместимости, а для составных типов происходит строгое сравнение всех свойств. Для данной операции, пустой тип совместим только с другим пустим типом!\nУправляющие конструкции (в разработке) Условный оператор В качестве оператора проверки условия используется синтаксическая конструкция, соответствующая по смыслу термину «следует», т.е. тире и угловая скобка «-\u003e». Такая запись условного оператора очень похожа на математическую и легко объединяется в последовательности для проверки множественных условий вида «else if».\nВ общем случае условный оператор имеет вид:\nусловие -\u003e действие; или (условие) -\u003e {действие}; или (условие1 || условие2) -\u003e {действие} -\u003e {действие иначе}; Или расширенный вариант «else if», для наглядности записанный с отступами:\n(условие1) -\u003e {действие1} (условие2) -\u003e {действие2} (условие3) -\u003e {действие3} -\u003e {действие_иначе}; Операторы циклов (в планах) Операторы циклов пока в разработке , т. к. плотно связаны с итераторами.\nПока планирую для циклов использовать конструкции: (условие) \u003c–\u003e {тело цикла};\nИли так: (условие) -» {тело цикла};\nИ хотя синтаксис мне не очень нравится, но я решил пока не ломать над этим голову и планирую попробовать несколько вариантов оформления циклов.\nОператоры прерывания потока выполнения команд (реализовано частично) Оператором прерывания потока выполнения команд и возврата из текущей функции, т.е. самым близким аналогом оператора return\nявляется оператор два символа минус «–». Но в отличие от классического return, оператор возврата не возвращает значения, т.к. значение из любой функции или блока кода возвращается всегда и им является результат выполнения самой последней операции (или None, если такая операция отсутствует).\nПока не придумал, как оформлять оператор прерывания потока выполнения в случае ошибки (при его выполнении будет происходить генерация исключения), поэтому, если будут предложения, пишите в комментариях к статье (и про оформление циклов тоже).\nОбработка ошибок (в планах) В самом начале работ я ориентировался на классический вариант обработки исключений, который в обычных языках программирования обычно оформляется ключевыми словами try .. catch .. finally с различными вариациями. Но в условиях жестких ограничений на синтаксис языка, и невозможности использовать ключевые слова, комбинировать символы для указания разных типов блоков при обработке исключений, было бы крайне сомнительной затеей. Ведь основная цель разработки NewLang — простота и понятность кода, а тут с самого начала могут появиться комбинации скобочек, стрелочек, палочек и других подобных символов.\nИ тут в голову пришла очень простая мысль. А ненужно повторять логику обработки ошибок из классических языков программирования! Ведь основная цель подобных синтаксических конструкций - выделить участок кода где возможно возникновение ошибки, перехватить и обработать правильный тип исключения. Ведь классические языки программирования изначально были жестко привязаны к машинному представлению данных в оперативной памяти компьютера и тип данных для них играл принципиально важное значение. Но это не является ограничением для языков с динамической типизацией!\nПоэтому, подход к обработке исключений планируется следующий: Программный код, который может привести к ошибке, заключается в двойные фигурные скобки {{ любой код или вызов одиночной функции }}, а результат выполнения такого блока кода присваивается переменной. После этого анализируется возвращенное значение и тип исключения может обрабатываться обычным условным оператором.\nНаверно, это проще показать на примере:\n$error := {{ # начало блока try call_or_exception1(); call_or_exception2(); }}; # конец блока try # Обычные условные операторы вместо типизированных блоков catch ($error ~ :type1)-\u003e{ код обработки ошибки 1} ($error ~ :type2)-\u003e{ код обработки ошибки 2}; Самое удивительное, что при таком подходе значительно упрощается и семантика блоков try … finally, которые вообще становятся не нужны.\nИсходный код на Java:\ntry { try { throw new Exception(\"a\"); } finally { throw new IOException(\"b\"); } } catch (IOException ex) { System.err.println(ex.getMessage()); } catch (Exception ex) { System.err.println(ex.getMessage()); } Эквивалентный ему на NewLang:\n$catch := {{ $finally := {{ Error1(\"1\"); }}; Error2(\"2\"); # Строка выполнится даже при возникновении исключении Error1 $finally;\t# Error1 вернется, если не будет Error2 }} ($catch ~ :Error1) -\u003e printf(«%s», $catch) ($catch ~ :Error2) -\u003e printf(«%s», $catch); Как все это попробовать? Сейчас сборка проекта реализована только под Linux и если кроме текстового описания захочется в живую поэкспериментировать на своей машине, то придется собрать интерпретатор из исходников самостоятельно.\nТак как текущий вариант предназначен первую очередь для отработки концепции, то часть из описанных возможностей пока не реализована (алгоритмические конструкции, наследование классов, итераторы, некоторые операции и т. д).\nНо можно поиграться с созданием переменных, вызовом функций и выполнением арифметических операций над данными, чтобы оценить синтаксис, основанный на правилах, и может быть, предложить свои собственные мысли и доработки для его улучшения.\nСборка REPL из исходников (пока только под Linux) Подготовка репозитория Скачать исходники Скачать и развернуть архив libtorch в каталоге contrib (PyTorch Build: Stable (1.10.*) -\u003e Your OS: Linux -\u003e Package: LibTorch -\u003e Language: C++ / Java -\u003e Compute Platform: CPU -\u003e Download here (cxx11 ABI): libtorch-cxx11-abi-shared-with-deps-1.10.2+cpu.zip) Активировать и скачать исходники субмодулей (git submodule init \u0026\u0026 git submodule update) В каталоге contrib запустить файл build.sh для сборки библиотеки libffi В каталоге core запустить файл compile_syntax.sh для генерации файлов парсера и лексического анализатора. Может потребоваться установка утилит flex и bison. Если что, у меня установлены flex 2.6.4 и bison (GNU Bison) 3.7.4 Собрать Юнит-тесты (newlang_test): в каталоге core выполнить команду make CONF=UnitTest Интерпретатор (nlc): в каталоге core выполнить команду make CONF=Debug Утилита nlc (NewLangCompiler) В текущее время nlc поддерживать работу только в режиме интерпретатора (несмотря на название). Для тестирования и простой проверки компилятор не нужен, хотя на первых порах я делал именно его. Но трудоемкость работ по постоянной переделке под новый синтаксис оказалась очень высокой, поэтому на время первичной отладки языковых конструкций было принято волевое решение ограничиться интерпретатором, как более простым и быстрым способом проверки различных гипотез, а разработку настоящего компилятора (в виде трансплайтера на язык С++), отложить до окончательной проработки синтаксиса.\nПланы на будущее Естественное, одна статья и несколько маленьких примеров не дают исчерпывающей информации о возможностях языка. Да и сами возможности пока не раскрыты в полной мере. Ведь текущая версия, это скорее тестовая платформа для проверки декларируемых концепций и основного синтаксиса.\nПока остаются не реализованными некоторые из заявленных возможностей и очень важных хотелок. Но протестировать основной подход можно уже сейчас, и я буду благодарен за любую обратную связь и предложения.\nЕсли говорить о планах (естественно, в будущих версиях что-то может добавиться или измениться порядок их реализации), но в настоящий момент роадмап развития NewLang мне видится следующим образом:\nДоделать стандартные управляющие конструкции, обработку ошибок и итераторы. Доработать систему типов с учетом множественного наследования классов. Реализовать длинную арифметику и дроби. Сделать какую нибудь логическую игру (крестики нолики, судоку или что-то похожее) с алгоритмическим выбором следующего хода и его вычислением с помощью машинного обучения. Написать много разных примеров для оценки синтаксиса. Доработать синтаксис с учетом полученного опыта и обратной связи. Восстановить работоспособность компилятора для генерации исполняемых файлов. Сделать очередную большую чистку кода. Переработать и задокументировать получившуюся семантику языка с учетом всех возможностей и выпустить первую полнофункциональную версию NewLang. Ссылка на первую публикаци\n","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/blog/newlang/","tags":"","title":"Новый язык программирования"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nБолее года назад я начал публикацию статей с описанием особенностей нового языка программирования. С тех пор утекло много воды, было протестировано множество идей, в итоге несколько раз все поменялось кардинальным образом и сейчас представляю на суд читателей описание предфинальной версии языка и его особенностей.\nДанная статья предназначена в первую очередь для проверки основных концепций нового языка программирования, а также для получения обратной связи от читателей Хабра. Ведь согласно наблюдению Хабр-ума палата, не замыленный взгляд со стороны очень сильно помогает в проработке новых идей.\nЭтот проект очень долго был без собственного названия и в публикациях назывался просто и абстрактно “новый язык”. Но после нескольких статей, временное название “новый язык” постепенно превратилось в имя собственное NewLang, которое я и решил в конечном итоге оставить (что еще раз подтверждает поговорку, что нет ничего более постоянного, чем что-то временное).\nNewLang - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения.\nОсновной особенностью языка является легкий, логичный и непротиворечивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка). Основные свойства и особенности языка:\nВозможность работы как в режиме интерпретатора, так и компилятора. Динамическая и статическая типизация с возможностью указания типов в явном виде. Статическая типизация является условно строгой (автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных, например, целое число может быть автоматически преобразовано в вещественное, но не наоборот) Автоматическое управление памятью. ООП в виде явного наследования классов и утиная типизация. На уровне синтаксиса поддержка нескольких типов функций (обычные и чистые функции без побочных эффектов). Необязательные и именованные параметры функций. Возможны вставки кода на языке реализации (С/С++). Простая интеграция с уже существующими программными библиотеками (в том числе импорт нативных переменных и функций из С/С++). Имеется REPL read-eval-print loop — «цикл: чтение — вычисление — вывод». Зачем нужен NewLang? У всех современных языков программирования происходит постоянное развитие (читай усложнение) синтаксиса по мере выхода новых версий. Это является своего рода, платой за появление новых возможностей и воспринимается пользователями как естественное явление.\nНо одновременно является и серьезной проблемой, т.к. с выходом новых версий добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки и трудоемкости поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.\nУ NewLang сложность языковых конструкций естественно ограничена за счет разделения синтаксиса языка на две части, что упрощает его изучение и использование. Основной синтаксис — для написания программ в объектно-ориентированном (императивном) и декларативном стилях, который основан не на зарезервированных ключевых словах, а на строгих грамматических правилах и Расширенный синтаксис — когда основного синтаксиса становится недостаточно, или требуется использовать языковую конструкцию языка реализации.\nЕще одно неудобство современных мейнстримовых языков, большинство из них были созданы до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек, а не встроены в основной синтаксис языка и систему базовых типов. У NewLang тензорные вычисления доступны «из коробки» (используется библиотека libtorch), а арифметические типы данных являются скалярами (тензорами нулевой размерности).\nОсновной синтаксис Основной синтаксис NewLang - простой и логичный за счет того, что он построен исключительно на грамматических правилах и не использует каких либо зарезервированных ключевых слов, а все буквенно-символьные последовательности рассматриваются как идентификаторы в которых можно использовать любые не-ASCII символы.\nИдеализированная цель отказа от ключевых слов, приблизить чтение исходного текста программы к чтению обычного текста за счет использования знаков препинания при описании логики работы алгоритма.\nКонечно запятая человек может вычленять ключевые управляющие слова языка и слеш или учитывать форматирование программы запятая чтобы на их основе понимать синтаксические конструкции запятая хотя при обычном чтении мы привыкли опираться именно на семантику знаков препинания точка мы конечно можем писать знаки препинания и обычным текстом точка но согласитесь запятая что тогда открытая скобка например запятая вот такой вот текст закрытая скобка будет очень не удобно читать точка\nНазвания встроенных типов или имена служебных функций системной библиотеки определяются конкретной реализацией языка, поэтому не являются зарезервированными ключевыми словами и при необходимости могут быть переопределены, например, для создания собственного, предметно-ориентированного диалекта (DSL - domain-specific language), если в этом возникнет необходимость. Но сама структура программы и логика выполняемого алгоритма все равно останутся понятны всем, кто знаком с правилами основного синтаксиса NewLang.\nПример скрипта Hello world! на NewLang\n#!./nlc --eval # Определение функции hello hello(str) := { printf := @import('printf(format:Format, ...):Int'); # Импорт стандартной C функции printf('%s\\n', $str); # Вызов C функции с проверкой типов аргументов по строке формата }; hello('Привет, мир!'); # Вызвать функцию Вывод: Привет, мир!\nРасширенный синтаксис Расширенный синтаксис — это возможность вставить в текст программы NewLang исходный код на языке реализации. Сейчас это С/С++, что позволяет использовать любые возможности этого мощного языка программирования.\nОбработка расширенного синтаксиса происходит на этапе компиляции приложения, а взаимодействие между основным и расширенным синтаксисами происходит за счет совместного использования идентификаторов, которое полностью прозрачно для пользователя и подчиняется единым грамматическим правилам основного синтаксиса.\nЕще немного примеров: Любая последовательность вычислений возвращает результат выполнения последнего оператора. Поэтому выполнение одной команды или последовательности команд всегда возвращает какой-либо результат, а оператор возврата из функции необязателен, так как результатом будет значение последнего вычисленного выражения.\nСоздание переменных\nscalar := 42 42 tensor := [1,2,3,4,5,] # Тип тензора выводится автоматически [1, 2, 3, 4, 5,]:Char str := '$1 string' $1 string Арифметические операции\ntensor * 2 [2, 4, 6, 8, 10,]:Short tensor * 20 [20, 40, 60, 80, 100,]:Short tensor * 0.5 [0.5, 1, 1.5, 2, 2.5,]:Double tensor / 2 # Результат деления — число с плавающей точкой [0.5, 1, 1.5, 2, 2.5,]:Double tensor // 2 # Целочисленное деление без остатка [0, 1, 1, 2, 2,]:Char\u003c/source\u003e tensor % 2 # Целочисленный остаток от деления [1, 0, 1, 0, 1,]:Char\u003c/source\u003e Строковые операции\nstr = 'сцепеление строк ' ++ str; сцепеление строк $1 string str('строка как шаблон'); сцепеление строк строка как шаблон string Преобразование тензоров В эпоху машинного обучения тензоры являются основными элементами вычислений, поэтому для конвертирования данных в тензоры используется отдельная синтаксическая конструкция, состоящая из двойных квадратных скобок [[ данные ]]. Подробнее про особенности преобразования типов можно прочитать далее.\ntstr := [[\"Тест\"]] # Создать тензор из строки широких символов [1058, 1077, 1089, 1090,]:Int t2 := [[ \"Тест\" ]]:Int[2,2] # Тоже самое, но тензор двухмерный [ [1058, 1077,], [1089, 1090,], ]:Int\u003c/source\u003e StrWide(tstr) # Конвертировать тензор обратно в строку Тест Double(t2) # Изменить тип данных тезора [ [1058, 1077,], [1089, 1090,], ]:Double t3 := [[ t2 ]]:Char[4] # Преобразовать тип данных тензора и его размерность [34, 53, 65, 66,]:Char Синтаксис NewLang: При разработке синтаксиса я старался придерживаться уже сложившихся правил, чтобы не создавать множественных смыслов, зависящих от контекста. И одновременно «объять необъятное»\nОсновы Операторы разделяются точкой с запятой «;». Отступы и переводы строк игнорируются (очень хотелось иметь возможность автоматического форматирование кода). Многострочные комментарии в исходном коде соответствуют стилю С/С++ и должны располагаться между символами /* и */. Вложенность многострочных комментариев не поддерживается. Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash. Последовательность выполняемых команд, которая должна выполняться как единое целое, заключается в фигурные скобки «{}». Программные вставки расширенного синтаксиса на языке реализации заключается в фигурные скобки со знаком процента %{ /* тут может быть любой код на C/C++*/ %}. Создания объектов и присвоения новых значений Для создания объектов и присвоения им новых значений в NewLang используется сразу три разных оператора.\nОператор «::=» используется только для создания новых объектов, а если объект с таким именем уже существует, то генерируется ошибка.\nОператор «:=» используется для тех же целей, но если объект с таким именем уже существует, то ошибки не происходит, а новое значение присваивается уже существующему объекту.\nИ последний оператор «=» применяется только для присвоения значения уже существующим объектам, и если объект с указанным именем отсутствует, то тоже происходит ошибка.\nИспользование трех разных операторов для создания/изменения объектов позволяет более гибко контролировать подобные операции и выявлять логические ошибки в коде на более раннем этапе.\nvar ::= 1.0; # Создать новую переменную var без указания типа var = 100; # Присвоить новое значение уже существующей переменной printf := @import('printf(format:Format, ...):Int'); /* Создать новый или переопределить объект printf, который будет результатом выполнения глобальной функции @import */ Идентификаторы объектов и модификаторы В качестве идентификаторов можно использовать буквы, цифры и знаки подчеркивания в любых комбинациях, при условии, что первый символ идентификатора не является цифрой.\nВ NewLang существует возможность указания области видимости и времени жизни объекта с помощью модификатора — специального символа перед именем переменной. Это может показаться немного похожим на венгерскую нотацию, но в отличие от нее, модификатор не имеет отношения к типу объекта и не является частью имени идентификатора. К тому же в качестве модификаторов используется строго определённые символы, назначение которых определено заранее.\nТак, символ «$» в начале имени обозначает локальную переменную, время жизни которой ограничено текущей областью видимости и при её завершении локальная переменная уничтожается. Символ «@» обозначает глобальную переменную, а сам объект сохраняет свое состояние даже после выхода из текущей области видимости. Так же обозначаются и имена типов данных, например, при создания новых типов, а в качестве модификатора используется символа двоеточия «:»\nСемантика обращения к аргументам функций очень похоже на работу с аргументами в bash скриптах, где $1 или $arg — порядковый номер или имя аргумента (происходит обращение к локальным переменным в текущей области видимости).\nИспользование модификаторов является обязательным только в двух случаях: - При создании нового типа данных, так как типы всегда создаются в глобальной области видимости, а их символьные имена должны быть уникальными - При обращении к объектам NewLang внутри программных вставок кода на языке реализации, так как они используется как маркеры при поиске идентификаторов NewLang в коде С/С++.\nВ остальных случаях, для обращения к переменным указывать их модификаторы не обязательно. И если при обращении к объекту модификатор не указан, то сперва ищется локальная переменная, а потом глобальная с таким же именем. Причем, локальная переменная будет перекрывать глобальную.\nТак же следует иметь в виду, что компилятор может генерировать код для прямого обращения к локальным объектам уже на этапе компиляции, тогда как для обращения к глобальным объектам, или если модификатор области видимости отсутствует, компилятор вынужден каждый раз встраивать runtime вызов функции поиска объекта в таблице символов.\nСистема типов Так как система типов языка динамическая, то явное указание типа не влияет на размер переменной и является только своего рода логическим ограничением на возможность присвоения переменной значения другого типа.\nИнформация о типах используется при проверке их совместимости, когда существующему объекту присваивается значение другого типа. Такая операция возможна только когда типы совместимы между собой и допускают автоматическое приведение. Это справедливо как во время парсинга/компиляции исходного теста, так и во время выполнения в режимах интерпретатора и/или скомпилированного файла.\nАрифметические типы: Арифметические типы данных являются тензорами - массивами чисел одного типа с произвольным количеством измерений и одинаковым размером столбцов в каждом. Единичное число тоже тензор нулевого размера.\nПоддерживаются только знаковые целые числа, т.к. в беззнаковых числах особая нужда отсутствует, а проблем с ними можно найти очень много на ровном месте.\nПроблемы беззнаковых чисел (из интернета)\nВо-первых, вычитание двух беззнаковых чисел, например 3 и 5. 3 минус 5 равно 4294967294, т.к. -2 не может быть представлено как беззнаковое число. Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных значений со знаком и без знака. С++ может свободно преобразовывать числа со знаком и без знака, но не проверяет диапазон, чтобы убедиться, что вы не переполняете свой тип данных.\nВ C++ всё же есть несколько случаев, когда можно (или необходимо) использовать беззнаковые числа. Во-первых, числа без знака предпочтительнее при работе с битами. Во-вторых, использование беззнаковых чисел связаных с индексацией массивов.\nНо это мой случай, так как индекс может быть отрицательным и даже не числом, а диапазоном или многоточием. З.Ы. И даже зная об этом, все равно умудрился недавно словить баг с отрицательными индексами у словарей!\nИмена встроенных арифметических типов говорят сами за себя: Char, Short, Int, Long, Float, Double, ComplexFloat, ComplexDouble. Отдельным типом идет логический тип Bool, который может принимать значения только 0 или 1 (false/true соответственно), и в зависимости от выполняемой операции может быть отнесен к целочисленным типам, так и не входить в их состав.\n(данный подход интерпретации логического типа данных был взят из библиотеки Torch)\n// Treat bool as a distinct \"category,\" to be consistent with type promotion // rules (e.g. `bool_tensor + 5 -\u003e int64_tensor`). If `5` was in the same // category as `bool_tensor`, we would not promote. Differing categories // implies `bool_tensor += 5` is disallowed. // // NB: numpy distinguishes \"unsigned\" as a category to get the desired // `bool_tensor + 5 -\u003e int64_tensor` behavior. We don't, because: // * We don't want the performance hit of checking the runtime sign of Scalars. // * `uint8_tensor + 5 -\u003e int64_tensor` would be undesirable. В будущем планируется добавить классы чисел для длинной арифметики и дробей, для чего зарезервированы названия типов BigNum, Currency и Fraction.\nДоступ к элементам тензора происходит по целочисленному индексу, который начинается с 0. Для многомерного тензора, индексы элемента перечисляются в квадратных скобках через запятую. Поддерживается доступ к элементам через отрицательный индекс, который обрабатывается точно так же, как в Python (-1 последний элемент, -2 предпоследний и т.д.).\nЛитерал тензор в тексте программы записывается в квадратных скобках с обязательной завершающей запятой, т.е. [1, 2,] - это литерал одномерный тензор из двух чисел. После закрывающей скобки тип тензора может быть указан в явном виде. Если тип не указан, то он выводится автоматически на основании указанных данных и выбирается минимально возможный байтовый размер, который позволяет сохранить все значения без потери точности.\nПримеры:\n$var_char := 123; # Тип Char выводится автоматически $var_short := 1000; # Тип Short выводится автоматически $var_bool := [0, 1, 0, 1,]; # Тензор из 4 элементов. Тип Bool выводится автоматически $tensor[10,10]:Int := 1; # Тензор Int размером 2x2 инициализированный 1 $scalar := $tensor[5,5]; # Присвоить скаляру значение указанного элемента тензора Строковые типы данных: Поддерживаются два типа строк, StrWide - символьные (широкие) и StrChar — байтовые. Различия между ними заключается в типе единичного элемента. У символьных строк единичным элементом является широкий символ wchar_t, а у байтовой строки единичным элементом является один байт (точнее char, т. е. байт со знаком). Символьные строки литералы в исходном тексте записывается в «двойных кавычках», а байтовые строки в ‘одинарных кавычках’.\nКоличество элементов символьной строки возвращается в широких символах, а размер байтовой строки в байтах, поэтому и обращение к элементу строки по индексу происходит соответственно либо к символу, либо к байту.\nВажный момент. К любой переменной можно обратиться так же, как к функции (записав после её имени круглые скобки). Результатом этой операции будет создание копии/клона объекта. Причем некоторые типы (словари, классы и символьные строки) можно использовать в качестве шаблона при создании копии объекта с модифицированными свойствами, если новые и/или изменяемые значения указать в скобках, как аргументы при вызовах функций. Так, если при создании копии в скобках указать набор новых данных, то результирующая копия будет содержать уже измененные данные.\nНапример:\n$template := \"${name} $1\"; # Обычная строка $result := $template(\"шаблон\", name = \"Строка\"); # result = \"Строка шаблон\" Составные типы данных: Словарь Словарь — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии (он похож и на tuple и на структуру одновременно). Словари от тензоров отличаются тем, что являются только одномерными массивами, но каждый элемент может содержать произвольное количество элементов любого типа, в том числе и другие словари.\nДоступ к элементам словарей происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. Индекс также начинается с 0 и как у тензоров, тоже может быть отрицательным.\nЛитерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, т.е. (,) - пустой словарь, (1, 2= «2», name=3,).\nПеречисление Перечисление - это не отдельный тип данных, а обычный словарь, у которого все элементы имеют уникальные имена и целочисленные значение, которое явно указывается при определении или вычисляется автоматически (на единицу больше предыдущего элемента). У перечислений тип значения указывается сразу после закрывающей скобки через двоеточие (ONE=1, TWO=, THREE=): Int.\nКлассы Класс (реализовано частично) - тип данных, с помощью которого реализуется один из принципов ООП - наследование. При создании экземпляра класса создается новая переменная, у которой сохраняется информацию о своем родителе и которая наследует от него свойства и методы. Тип данных «класс» аналогичен словарю, но все свойства обязаны иметь имена (хотя доступ к свойствам класса по индексу так же возможен). Литерал с типом «Класс» в тексте программы записывается в круглых скобках без завершающей запятой, т. е. () - пустой класс, (1, 2= «2», name=3).\nПока остальные детали классов до конца не реализованы, поэтому описывать их не буду, т. к. в итоговом варианте синтаксис классов и определения их методов могут поменяться.\nФункции Синтаксис NewLang поддерживать несколько типов функций (а в будущем и методов классов): обычные функции, чистые функции и простые чистые функции.\nДля всех типов функций поддерживаются аргументы по умолчанию. При создании функции, её аргументы указываются как в Питоне, т.е. вначале идут обязательные аргументы, потом аргументы со значениями по умолчанию, где имя аргумента отделяется от его значения по умолчанию знаком равно «=». Если функция допускает обработку произвольного количества аргументов, то последним в списке параметров указывается многоточие.\nОбычная функция Обычная функция — такие функции являются именно обычными функциями в понимании С/С++. Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д.\nВнутри обычной функции можно обращаться к локальным и глобальным объектам, и они могут содержаться вставки на языке реализации, например, для вызова функций из внешних библиотек.\nВставки на языке реализации оформляются в виде %{ %} и могут содержать любой текст на С/С++, а прямо из него можно обращаться к локальным и глобальным объектам NewLang так же, как и в обычном синтаксисе, указывая первым символом имени соответствующий модификатор ($ для локальных объектов и @ для глобальных).\nТехнически, такая программная вставка просто переносится трансплайтером непосредственно в исходный текст генерируемого файла, а все идентификаторы NewLang специальным образом декорируются (добавляются специальные маркеры для их идентификации), после этого исходный текст подается на вход обычному компилятору С++. Для локальных объектов трансплайтер может генерировать код для прямого доступа к объекту на этапе компиляции, а для работы с глобальными объектами вынужден использовать runtime вызовы функции поиска в таблице символов.\nНапример:\nprint(str) := { %{ printf(\"%s\", static_cast\u003cconst char *\u003e($str)); /* Прямой вызов С функции */ %} }; Чистые функции Чистая функция - это тоже обычная функция, только в том смысле, какой в него вкладывает функциональное программирование. Создания чистой функции происходит с помощью оператора «:-». У чистой функции отсутствует доступ к контексту и глобальным объектам, поэтому она может обрабатывать только те данные, которые были ей переданы в качестве аргументов.\nПрограммные вставки на языке реализации внутри чистых функций не запрещены и могут использоваться, например, для отладки. Но делается это на страх и риск разработчика. Именно он отвечает за их «чистоту», например при вызове функций из внешних библиотек.\nSum(arg1, arg2) :- {$arg1+$arg2;}; # Вернуть сумму аргументов Так как в языке отсутствует оператор возврата данных из текущего блока выполнения (аналог оператора return \u003cданные\u003e), то возвращаемым значением функции / блока кода всегда является результат выполнения последней операции.\nПростые чистые функции Простые чистые функции — отдельный класс чистых функций, которые предназначены только для вычисления логического результата (т.е. они являются предикатами) и их отличает упрощенная формой записи. Тело простой чистой функции состоит из последовательности операторов, которые разделяются запятыми и заканчиваются, как и любое выражение, точкой с запятой. Все операторы простой чистой функции всегда приводятся к булевому значению, а итоговый результат функции вычисляется по одной из возможных логических операций: И, ИЛИ и исключающее ИЛИ.\nНапример:\nfunc_and(arg1, arg2) \u0026\u0026= arg1==3, arg2 \u003e 0; # Простая чистая функция Логическое И func_or(arg1, arg2) ||= arg1==3, arg2 \u003e 0; # Простая чистая функция Логическое ИЛИ func_xor(arg1, arg2) ^^= arg1==3, arg2 \u003e 0; # Простая чистая функция Исключающее ИЛИ Специальные типы данных: None None (пустой тип) — не содержит значения (точнее имеет одно значение None) и совместим с любым другим типом данных. Указывается в тексте программы как один подчерк «_». Значение None имеют не инициализированные переменные и при попытке чтения из такой переменной возникает ошибка.\nТип переменной может быть явно указан или выведен автоматически из присваиваемого значения. Присвоить новое значение уже инициализированной переменной можно только для совместимого типа, так как неявное преобразование типов не допускаются.\n$var := _; # Создать переменную со значением None $var2 := var; # Ошибка!!! Нельзя прочитать неинициализированную переменную var $var = 1000; # У переменной будет тип Short (минимальный размер для хранения значения) $var = 0,5; # Ошибка!!! Short ← Float не совместимы $var = _; # Очистить значение переменной $var = 0,5; # Теперь можно, т. к. None совместим с любым типом Диапазон (Range) Диапазон (реализовано частично) — специальный тип данных, являющейся приблизительным аналогом типа «генератор» в Python. К диапазону можно обращаться как к итератору и он будет поочередно выдавать элементы в указанном интервале с заданным шагом. Диапазон в тексте программы указывается как два или три элемента через две точки, например 1..5 — диапазон от единицы до пяти с шагом по умолчанию 1. В качестве параметров диапазона можно указывать не только литералы, но и имена переменных. Например, 0,1..$stop..0,1 — диапазон от значения 0,1 до значения, указанного в переменной $stop с шагом 0,1.\nДиапазон для целых чисел можно использовать в качестве индекса у тензоров (точнее, у любых объектов, которые допускают доступ к своим элементам по индексу, т.е. тензоры, словари и текстовые строки). Фактический, это поведение аналогично slice в языке Python и array[1:5] в Python означает тоже самое, что и array[1..5] в NewLang.\nВ качестве индекса у тензоров еще можно указать произвольное количество измерений с помощью многоточия, т.е.\n$tensor[…, 0] = 0; # Обнулить все первые элементы в каждом измерении. Итераторы Итераторы (в разработке) - самый сложный и неоднозначный тип данных для работы с элементами коллекций.\nДля работы с итераторами зарезервированы символы “!” и “?”, но сами итераторы пока не реализованы.\nПреобразование типов Явное приведение типов Несмотря на динамическую типизацию языка, если тип переменной указан явно, то автоматическое приведение типов не выполняется, и чтобы присвоить переменой значение не совместимого типа, требуется явное преобразование.\nТак как символьные названия типов относятся к деталям реализации, то явное преобразование в конкретный тип данных производится с помощью вызова функции с системным именем, т. е. Bool(), StrWide(), Long и т. д. Причем у тензоров при таком преобразовании изменяется только тип данных, но размерность тензора не меняется.\nДля преобразования любого типа данных в строку ещё можно использовать оператор конкатенации строк, которой преобразует любой тип данных в строковое представление. Но так как строковых типов два (байтовые и широкие строки), то тип строки определяется первым аргументом в операторе конкатенации, т. е.\n\"\" ++ 123 # \"123\" - Строка широких символов '' ++ 123 # '123' - Байтовая строка Или преобразовать любое значение в строковое с помощью строки-шаблона: val := 12345; \"$1\"(val) # Будет строка \"12345\" Tensor comprehensions В эпоху машинного обучения тензоры являются основным элементом вычислений, поэтому для конвертирования данных в тензоры используется отдельная синтаксическая конструкция, состоящая из двойных квадратных скобок [[ данные ]]. Фактически это оператор и функция времени выполнения в зависимости от указанных между двойные квадратными скобками выражения.\nЧтобы преобразовать любую переменную в тензор (с учетом допустимости такого преобразования), её достаточно указать между двойными квадратными скобками. Выражение [[ varibale ]] - преобразует переменную varibale в одномерный тензор с автоматическим выводом типа данных. Для преобразования в одномерный тензор конкретного типа используется выражение [[ varibale ]]:Type, где _Type- - любой из арифметических типов.\nЕсли требуется преобразовать переменную не в одномерный тензор, а в тензор конкретного типа и заданной размерности, то это делается выражением [[ varibale ]]:Type[2,2], которая вернет тензор с размерностью 2х2 и типом Type у элементов.\nВнутри двойных квадратных скобок может быть не только любое выражение, но и литерал или диапазон. В этом случае, они также раскрываются в тензор по таким же правилам.\nВ будущем планирую добавить возможность указания сразу нескольких значений через запятую для их объединения в один тензор.\nПримеры:\n\u003e[[(1,2,3)]] # Тензор из словаря [1, 2, 3,]:Char \u003e[['first second']] # Байтовая строка в тензор [102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char \u003e [[(first='first', space=32, second='second')]] # Получаем тензор из словаря с такими же данными [102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char \u003e[[ 0 ... ]]:Double[10,2] # Тензор заданного формата с нулями [ [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], ]:Double \u003e[[ rand() ... ]]: Int[3,2] # Тензор со случайными данными [ [1804289383, 846930886,], [1681692777, 1714636915,], [1957747793, 424238335,], ]:Int \u003e[[ 0..10 ]]: Int[5,2] # Тензор из диапзона [ [0, 1,], [2, 3,], [4, 5,], [6, 7,], [8, 9,], ]:Int \u003e[[ 0..0.99..0.1 ]] # Или даже так [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,]:Double\u003c/source\u003e Операторы и управляющие конструкции Операторы: Все операторы имеют парный оператор с присвоением значения.\n+ и += сложение арифметических типов данных и -= вычитание арифметических типов данных / и /= деление (результат число с плавающей точкой) // и //= целочисленное деление с округлением к меньшему числу (как в Python) и *= умножение ** и **= возведение в степень (он же используется и для повторения текстовых строк) ++ и ++= конкатенация строк с автоматическим приведением аргументов к стоковому типу (символ инкремента специально используется вместо одиночного плюса для того, чтобы в явном виде разделить конкатенацию строк и операторы арифметического сложения) Операторы сравнения: \u003c, \u003e, \u003c=, \u003e= классические для сравнения скаляров ==, != операторы сравнения с автоматическим приведением совместимых типов для любых объектов ===, !== оператор точного сравнения для любых объектов (автоматического приведения типов не выполняется)s Проверки типов (в разработке): Проверка имени класса «~» - немного похож на оператор instanceof в Java. Левым оператором должен быть проверяемый объект, а правым оператором - название типа, строка литерал или объект строкового типа с именем класса. Результатом операции будет истина, если правый операнд содержит название класса проверяемого объекта или он присутствует в иерархии наследования у проверяемого класса.\nname := \"class\"; # Строка с именем класса var ~ :class; var ~ \"class\"; var ~ name; (field1=«value», field2=2, field3=«33»,) ~~ (); # Истина (т. е. левый операнд словарь) (field1=«value», field2=2, field3=«33»,) ~~ (field1=_); # Тоже истина (т. к. поле field1 присутствует у левого операнда) Утиная типизация «~~» - приблизительный аналог функции isinstance() в Python, который для простых типов сравнивает совместимость типа левого операнда по отношению к правому, а для словарей и классов в левом операнде проверяется наличие всех имен полей, присутствующих у правого операнда. т. е.\n(field1=«value», field2=2, field3=«33»,) ~~ (); # Истина (т. е. левый операнд словарь) (field1=«value», field2=2, field3=«33»,) ~~ (field1=_); # Тоже истина (т. к. поле field1 присутствует у левого операнда) Строгая утиная типизация «~~~» - для простых типов сравнивается идентичности типов без учета совместимости, а для составных типов происходит строгое сравнение всех свойств. Для данной операции, пустой тип совместим только с другим пустим типом!\nУправляющие конструкции (в разработке) Условный оператор В качестве оператора проверки условия используется синтаксическая конструкция, соответствующая по смыслу термину «следует», т.е. тире и угловая скобка «-\u003e». Такая запись условного оператора очень похожа на математическую и легко объединяется в последовательности для проверки множественных условий вида «else if».\nВ общем случае условный оператор имеет вид:\nусловие -\u003e действие; или (условие) -\u003e {действие}; или (условие1 || условие2) -\u003e {действие} -\u003e {действие иначе}; Или расширенный вариант «else if», для наглядности записанный с отступами:\n(условие1) -\u003e {действие1} (условие2) -\u003e {действие2} (условие3) -\u003e {действие3} -\u003e {действие_иначе}; Операторы циклов (в планах) Операторы циклов пока в разработке , т. к. плотно связаны с итераторами.\nПока планирую для циклов использовать конструкции: (условие) \u003c–\u003e {тело цикла};\nИли так: (условие) -» {тело цикла};\nИ хотя синтаксис мне не очень нравится, но я решил пока не ломать над этим голову и планирую попробовать несколько вариантов оформления циклов.\nОператоры прерывания потока выполнения команд (реализовано частично) Оператором прерывания потока выполнения команд и возврата из текущей функции, т.е. самым близким аналогом оператора return\nявляется оператор два символа минус «–». Но в отличие от классического return, оператор возврата не возвращает значения, т.к. значение из любой функции или блока кода возвращается всегда и им является результат выполнения самой последней операции (или None, если такая операция отсутствует).\nПока не придумал, как оформлять оператор прерывания потока выполнения в случае ошибки (при его выполнении будет происходить генерация исключения), поэтому, если будут предложения, пишите в комментариях к статье (и про оформление циклов тоже).\nОбработка ошибок (в планах) В самом начале работ я ориентировался на классический вариант обработки исключений, который в обычных языках программирования обычно оформляется ключевыми словами try .. catch .. finally с различными вариациями. Но в условиях жестких ограничений на синтаксис языка, и невозможности использовать ключевые слова, комбинировать символы для указания разных типов блоков при обработке исключений, было бы крайне сомнительной затеей. Ведь основная цель разработки NewLang — простота и понятность кода, а тут с самого начала могут появиться комбинации скобочек, стрелочек, палочек и других подобных символов.\nИ тут в голову пришла очень простая мысль. А ненужно повторять логику обработки ошибок из классических языков программирования! Ведь основная цель подобных синтаксических конструкций - выделить участок кода где возможно возникновение ошибки, перехватить и обработать правильный тип исключения. Ведь классические языки программирования изначально были жестко привязаны к машинному представлению данных в оперативной памяти компьютера и тип данных для них играл принципиально важное значение. Но это не является ограничением для языков с динамической типизацией!\nПоэтому, подход к обработке исключений планируется следующий: Программный код, который может привести к ошибке, заключается в двойные фигурные скобки {{ любой код или вызов одиночной функции }}, а результат выполнения такого блока кода присваивается переменной. После этого анализируется возвращенное значение и тип исключения может обрабатываться обычным условным оператором.\nНаверно, это проще показать на примере:\n$error := {{ # начало блока try call_or_exception1(); call_or_exception2(); }}; # конец блока try # Обычные условные операторы вместо типизированных блоков catch ($error ~ :type1)-\u003e{ код обработки ошибки 1} ($error ~ :type2)-\u003e{ код обработки ошибки 2}; Самое удивительное, что при таком подходе значительно упрощается и семантика блоков try … finally, которые вообще становятся не нужны.\nИсходный код на Java:\ntry { try { throw new Exception(\"a\"); } finally { throw new IOException(\"b\"); } } catch (IOException ex) { System.err.println(ex.getMessage()); } catch (Exception ex) { System.err.println(ex.getMessage()); } Эквивалентный ему на NewLang:\n$catch := {{ $finally := {{ Error1(\"1\"); }}; Error2(\"2\"); # Строка выполнится даже при возникновении исключении Error1 $finally;\t# Error1 вернется, если не будет Error2 }} ($catch ~ :Error1) -\u003e printf(«%s», $catch) ($catch ~ :Error2) -\u003e printf(«%s», $catch); Как все это попробовать? Сейчас сборка проекта реализована только под Linux и если кроме текстового описания захочется в живую поэкспериментировать на своей машине, то придется собрать интерпретатор из исходников самостоятельно.\nТак как текущий вариант предназначен первую очередь для отработки концепции, то часть из описанных возможностей пока не реализована (алгоритмические конструкции, наследование классов, итераторы, некоторые операции и т. д).\nНо можно поиграться с созданием переменных, вызовом функций и выполнением арифметических операций над данными, чтобы оценить синтаксис, основанный на правилах, и может быть, предложить свои собственные мысли и доработки для его улучшения.\nСборка REPL из исходников (пока только под Linux) Подготовка репозитория Скачать исходники Скачать и развернуть архив libtorch в каталоге contrib (PyTorch Build: Stable (1.10.*) -\u003e Your OS: Linux -\u003e Package: LibTorch -\u003e Language: C++ / Java -\u003e Compute Platform: CPU -\u003e Download here (cxx11 ABI): libtorch-cxx11-abi-shared-with-deps-1.10.2+cpu.zip) Активировать и скачать исходники субмодулей (git submodule init \u0026\u0026 git submodule update) В каталоге contrib запустить файл build.sh для сборки библиотеки libffi В каталоге core запустить файл compile_syntax.sh для генерации файлов парсера и лексического анализатора. Может потребоваться установка утилит flex и bison. Если что, у меня установлены flex 2.6.4 и bison (GNU Bison) 3.7.4 Собрать Юнит-тесты (newlang_test): в каталоге core выполнить команду make CONF=UnitTest Интерпретатор (nlc): в каталоге core выполнить команду make CONF=Debug Утилита nlc (NewLangCompiler) В текущее время nlc поддерживать работу только в режиме интерпретатора (несмотря на название). Для тестирования и простой проверки компилятор не нужен, хотя на первых порах я делал именно его. Но трудоемкость работ по постоянной переделке под новый синтаксис оказалась очень высокой, поэтому на время первичной отладки языковых конструкций было принято волевое решение ограничиться интерпретатором, как более простым и быстрым способом проверки различных гипотез, а разработку настоящего компилятора (в виде трансплайтера на язык С++), отложить до окончательной проработки синтаксиса.\nПланы на будущее Естественное, одна статья и несколько маленьких примеров не дают исчерпывающей информации о возможностях языка. Да и сами возможности пока не раскрыты в полной мере. Ведь текущая версия, это скорее тестовая платформа для проверки декларируемых концепций и основного синтаксиса.\nПока остаются не реализованными некоторые из заявленных возможностей и очень важных хотелок. Но протестировать основной подход можно уже сейчас, и я буду благодарен за любую обратную связь и предложения.\nЕсли говорить о планах (естественно, в будущих версиях что-то может добавиться или измениться порядок их реализации), но в настоящий момент роадмап развития NewLang мне видится следующим образом:\nДоделать стандартные управляющие конструкции, обработку ошибок и итераторы. Доработать систему типов с учетом множественного наследования классов. Реализовать длинную арифметику и дроби. Сделать какую нибудь логическую игру (крестики нолики, судоку или что-то похожее) с алгоритмическим выбором следующего хода и его вычислением с помощью машинного обучения. Написать много разных примеров для оценки синтаксиса. Доработать синтаксис с учетом полученного опыта и обратной связи. Восстановить работоспособность компилятора для генерации исполняемых файлов. Сделать очередную большую чистку кода. Переработать и задокументировать получившуюся семантику языка с учетом всех возможностей и выпустить первую полнофункциональную версию NewLang. Ссылка на первую публикаци\n","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/ru/blog/newlang/","tags":"","title":"Новый язык программирования"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nПри разработке своего собственного языка программирования автор должен определиться, какими свойствами его язык должен обладать, ведь в конечном итоге именно это и будет определять назначение языка и особенности его использования. Причем некоторые свойства настолько сильно влияют на итоговую концепцию языка и его синтаксис, что впоследствии их изменение невозможно в принципе, либо новый синтаксис получается очень запутанным и непонятным. Наверно из-за этого многие свойства языков программирования рассматриваются и изучаются как взаимоисключающие.\nДо недавнего времени я считал, что императивная и декларативная парадигмы написания программ являются антагонистами и взаимоисключающими понятиями. Ведь выбор стиля написания кода, изначально определяется автором языка еще на стадии его проектирования и оказывает влияние на все последующие аспекты.\nНо сейчас я думаю, что это не верно. Императивный и декларативный стили программирования не являются взаимоисключающими, а писать программы только в одной из указанных парадигм подталкивают правила синтаксиса, реализованные в языке!\nДругими словами, использовать только императивную или только декларативную парадигмы разработчик вынужден не потому, что он не умеет или не хочет писать код по другому, а из-за того, что все более-менее мейнстримные языки программирования ориентированы на использование только одной парадигмы. И выбор только одной парадигмы написания кода, это ограничение, которое навязано программистам создателями языка. Ведь если они изначально ориентировались только на одну концепцию разработки кода, то и разрабатывали синтаксис языка в соответствии с этой парадигмой.\nДанная статья — размышление о совместимости декларативной и императивной парадигм программирования и возможности их одновременного использования в рамках одного языка программирования одновременно.\nЧто такое “Декларативное программирование”? Вначале мне захотелось разобраться, а существуют ли чисто декларативные языки программирования? Такие, которые могут полностью обходятся без императивных конструкций?\nНо чуть не споткнулся уже в самом начале, т.к. даже само определение «декларативное программировании», в вики описывается следующим образом:\nДекларати́вное программи́рование — парадигма программирования, в которой задаётся спецификация решения задачи, то есть описывается, что представляет собой проблема и ожидаемый результат. Противоположностью декларативного является императивное программирование, описывающее на том или ином уровне детализации, как решить задачу и представить результат.\nУже в изначальном определении закладывается противопоставление парадигм, а дальше идут рассуждения о «направлении» программирования. И хоть вики сама и не является авторитетным источником информации, но даже такая заготовка статьи смогла показать направление поиска ответов на первый поставленный вопрос.\nИ заставил задуматься один абзац в конце статьи следующего содержания:\n«Чисто декларативные» компьютерные языки зачастую неполны по Тьюрингу — так как теоретически не всегда возможно порождение исполняемого кода по декларативному описанию. Это иногда приводит к спорам о корректности термина «декларативное программирование» (менее спорным является «декларативное описание решения» или, что то же самое, «декларативное описание задачи»).\nСудя по наличию такой оговорки, ставится под сомнение наличие «чисто декларативных» языков. И как только пришлось задуматься над это мыслью, то сразу стало очевидным, что какой бы декларативный язык программирования не существовал, то в нем должна быть как минимум одна императивная конструкция, которая будет запускать поиск решения! Ведь любой синоним слова «выполнить» или «запустить» по определению будет императивом!\nНапример в языке Prolog, который обычно и приводят в качестве примера декларативного языка программирования, “замаскированным” императивным оператором является знак вопроса. Он кажется естественным и логичным, как же без него? Но по своей сути, это императивная конструкция!\nТоже самое касается и языка SQL. Он тоже как бы декларативный, но неожиданно все его команды являются императивными по сути. SELECT, CREATE, ALTER, DROP, INSERT, UPDATE, DELETE и т. д., а декларативными являются только описания условий их выполнения!\nВ результате, у меня так и не получилось найти чисто-декларативный язык программирования без императивных операторов (может быть, Вики права и такого языка программирования и вовсе не существует?).\nА что отличает декларативные языки программирования от императивных? Согласно определению, декларативными языками программирования их называют из-за возможности записать некие условия в декларативном стиле. Но кроме этого, в декларативных языках как правило присутствует и некий внутренний механизм поиска решений. Подобный “вычислитель” есть и в SQL и Prolog и во многих других декларативных языках.\nИнтересно, а является ли внутренняя система поиска решений обязательным признаком декларативного стиля программирования или это только особенность конкретного языка программирования, которая не зависит от декларативного стиля написания кода?\nЧтобы проверить данные предположения, можно было попробовать написать классическую декларативную программу на императивном языке, у которого отсутствует внутренний механизм поиска решений.\nА заодно, таким образом можно будет и изучить вопрос, получится ли написать программу в декларативном стиле используя обычный императивный язык программирования?\nДля примера, решил попробовать повторить уже классическую программу в декларативном стиле на Прологе.\nparent(\"Tom\",\"Jake\"). parent(\"Janna\",\"Jake\"). parent(\"Tom\",\"Tim\"). male(\"Tom\"). male(\"Tim\"). male(\"Jake\"). female(\"Janna\"). brother(X,Y):-parent(Z,X),parent(Z,Y),male(X),male(Y),X\\=Y. ? brother Получилась вот такая функционально - эквивалентная программа на С++, которая максимально приближена по стилю к декларативному прототипу:\nenum sex_ { male, female }; struct human; typedef std::vector\u003chuman *\u003e parent_; struct human { const char *name; sex_ sex; parent_ parent; }; human Tom{\"Tom\", male,{}}; human Janna{\"Janna\", female,{}}; human Jake{\"Jake\", male,{\u0026Tom, \u0026Janna}}; human Tim{\"Tim\", male,{\u0026Tom}}; std::vector\u003chuman *\u003e humans{\u0026Tom, \u0026Janna, \u0026Jake, \u0026Tim}; auto brothers = [](human * a, human * b) { auto intersec = [](parent_ \u0026a, parent_ \u0026 b) { for (auto elem_a : a) { for (auto elem_b : b) { if(elem_a \u0026\u0026 elem_b \u0026\u0026 elem_a == elem_b) { return true; } } } return false; }; return a \u0026\u0026 b \u0026\u0026 a != b \u0026\u0026 a-\u003esex == male \u0026\u0026 b-\u003esex == male \u0026\u0026 (intersec(a-\u003eparent, b-\u003eparent)); }; for (auto a : humans) { for (auto b : humans) { if(brothers(a, b)) { std::cout \u003c\u003c a-\u003ename \u003c\u003c \" and \" \u003c\u003c b-\u003ename \u003c\u003c \"\\n\"; } } } Конечно, текст на С++ получается значительно многословней, чем вариант на Прологе, но по сути, это почти дословное повторение декларативного стиля написания кода. Тем более, не стоит забывать про рассуждения в начале статьи об изначальном выборе концепции при создании языка и “принуждении” программистов пользоваться только одной, изначально выбранной парадигмой разработки.\nТаким образом, можно с высокой долей уверенности утверждать, что теоретически можно писать код одновременно в разных стилях.\nНо что тогда мешает в рамках одного языка программирования писать с использованием императивного и декларативного стиля? Неужели только убежденность создателей языков в том, что императивный и декларативный стили программирования являются взаимоисключающими? И только из-за этого получаются языки программирования, синтаксис которых подходит для использования одной единственной парадигмы?\nНо если это так, то что мешает попробовать разработать синтаксис языка программирования, в котором можно было бы использовать сразу императивный и декларативный стили программирования одновременно?\nЧто мешает совместить императивный и декларативный стили написания в рамках одной программы? В любой компьютерной программе всегда существует разделение кода на описание данных и на языковые конструкции для их обработки, т.е. фактически это разделение на данные и на функции. Мне кажется, что основная сложность, которая не дает использовать разные стили программирования в рамках одного языка, это необходимость разделять описываемые сущности на «данные» и «управляющие конструкции». Ведь это свойство (необходимость разделения сущностей на “данные” и “функции”), является неотъемлемой частью любого языка программирования.\nЭто не удивительно, ведь на заре становления ИТ индустрии, создатели первых языков программирования ориентировались исключительно на императивный стиль, потому что назначением любого компилятора было - преобразовать исходный текст программы в машинные инструкции. И на примерах модульного, структурного и объекто-ориентированного подходах показана и доказана необходимость оформления исполняемого кода в выделенные процедуры с последующей их группировкой в модули и классы.\nА декларативный стиль написания программ стал появляться только после создания высокоуровневых языков программирования. И основная цель создания данных языков сместилась на поиск решения конечного пользователя, а не на упрощение генерации бинарных файлов с машинными инструкциями. Если внимательно посмотреть на приведенные выше примеры кода, то можно заметить, что в них определения данных и операторы для их обработки идут вперемешку, (для примера на С++ это определение лямбд функции), что кардинально отличается от императивного подхода.\nТак может быть, основная особенность декларативного стиля как раз и заключается в том, что в нем не разделяются «данные» и «действия над данными»? Или как вариант, можно не указывать выполняемые действия над данными вовсе (как в некоторых SQL конструкциях)?\nМожет быть как раз именно эта особенность (возможность последовательной записи программного кода в соответствии с собственными логическими рассуждениями, в которых могут перемежаться «данные» и «функции», как это происходит при человеческом мыслительном процессе), не дает в полной мере реализовать возможность совмещения императивных и декларативных стилей программирования?\nИ если это так, тогда можно попробовать разработать такой синтаксис, который будет поддерживать определение как данных, так и декларацию функций в рамках единого потока языковых конструкций!\nПроверка гипотезы в новом языке программирования Для поверки данного предположения, я решил добавить в свой новый язык программирования (синтаксис которого допускает определение функций в одном потоке с описанием обрабатываемых данных), недостающие алгоритмические конструкции, которые позволяли бы реализовать императивный стиль программирования, несмотря на изначальную ориентацию только на декларативную парадигму.\nПравда с учетом изначальных ограничений синтаксиса нового языка (запрет на применение операторов в виде зарезервированных ключевых слов), в качестве оператора проверки условия была выбрана синтаксическая конструкция, соответствующая по смыслу термину «следует», т.е. тире и угловая скобка «-\u003e».\nВ результате, условный оператор получился практически математический, который легко объединяется в последовательности для реализации проверки множественных условий вида «else if». А для объединения сразу нескольких логического операторов между собой и для отделения их от последующего действия, операторы проверки условия можно заключать в круглые скобки.\nВ общем случае условный оператор в новом языке программирования имеет вид:\nусловие -\u003e действие; или (условие) -\u003e {действие}; или (условие1 || условие2) -\u003e {действие} -\u003e {действие иначе}; Или расширенный вариант, для наглядности записанный с отступами:\n(условие1) -\u003e {действие1} (условие2) -\u003e {действие2} (условие3) -\u003e {действие3} -\u003e {действие_иначе}; Тогда и операторы циклов можно будет записать практически аналогично, только выбрав в качестве оператора, не оператор следования, а следование с возвратом (раз уж нужно указывать циклическое действие).\nЦикл пока:\n(условие) \u003c-\u003e {тело цикла}; счетный цикл для работы с итератором:\n(счетчик_или_данные!)? \u003c-\u003e {тело цикла}; В этом случае, решение тестового примера декларативной программы на Прологе можно будет легко оформить, как в императивном, так и в декларативном стилях одновременно!\nм := \"муж.\"; ж := \"жен.\"; human @= term(пол=, parent=[,]); Tom @= human(пол=м); Janna @= human(пол=ж); Jake @= human(м, [\u0026Tom, \u0026Janna,]); Tim @= human(пол=м, parent=[\u0026Tom,]); brother(h1, h2) \u0026\u0026= $h1!=$h2, $h1.пол==м, $h2.пол==м, $h1.parent \u0026 $h2.parent; // Оператор «\u0026» побитовое «И» для чисел или операция пересечения для множеств // Запись алгоритма поиска решения в императивном стиле (h1=human!, h2=human!)? \u003c-\u003e { (brother(h1, h2)) -\u003e { @print($h1, $h2, «\\n»); } }; // Краткая запись алгоритма поиска решения в императивном стиле (h1=human!, h2=human!)? \u003c-\u003e brother($h1, $h2) -\u003e @print($h1, $h2, «\\n»); // Запись поиска решения в декларативном стиле brother(human!, human!)?; Примерно это и требовалось показать!\nЗ.Ы. Я почти закончил эксперименты с синтаксисом языка. И теперь, после добавления в него недостающих алгоритмический конструкций (ветвления и циклов), планирую, что следующая статья о новом языке программирования будет посвящена описанию его полного синтаксиса и публикации исходников прототипа компилятора для возможности поиграться на реальных примерах.\nЗ.З.Ы В комментариях @gbg привел очень простой ответ на один из поднятых вопросов. Причем в более элегантном виде и без написания кода!\nНу и пять копеечек про ООП. Как ни странно:\nВ нем таки есть декларативная часть, все эти pubic, private, virtual, etc Эта декларативная часть, внезапно, элегантно позволяет реализовывать декомпозицию и управление сложностью. При наличии перегрузок, можно поиграть в алгебраическое мышление, рассматривая взаимодействие двух объектов как бинарную операцию. Ух ты, ООП - это обкатанная практикой технология, которая совмещает декларатив с императивом и вроде позволяет освоившим ее вкусно кушать и мягко спать!\nСсылка на первую публикаци\n","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/blog/prog-styles-same-time/","tags":"","title":"Можно ли использовать декларативный и императивный стили написания программ одновременно?"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nПри разработке своего собственного языка программирования автор должен определиться, какими свойствами его язык должен обладать, ведь в конечном итоге именно это и будет определять назначение языка и особенности его использования. Причем некоторые свойства настолько сильно влияют на итоговую концепцию языка и его синтаксис, что впоследствии их изменение невозможно в принципе, либо новый синтаксис получается очень запутанным и непонятным. Наверно из-за этого многие свойства языков программирования рассматриваются и изучаются как взаимоисключающие.\nДо недавнего времени я считал, что императивная и декларативная парадигмы написания программ являются антагонистами и взаимоисключающими понятиями. Ведь выбор стиля написания кода, изначально определяется автором языка еще на стадии его проектирования и оказывает влияние на все последующие аспекты.\nНо сейчас я думаю, что это не верно. Императивный и декларативный стили программирования не являются взаимоисключающими, а писать программы только в одной из указанных парадигм подталкивают правила синтаксиса, реализованные в языке!\nДругими словами, использовать только императивную или только декларативную парадигмы разработчик вынужден не потому, что он не умеет или не хочет писать код по другому, а из-за того, что все более-менее мейнстримные языки программирования ориентированы на использование только одной парадигмы. И выбор только одной парадигмы написания кода, это ограничение, которое навязано программистам создателями языка. Ведь если они изначально ориентировались только на одну концепцию разработки кода, то и разрабатывали синтаксис языка в соответствии с этой парадигмой.\nДанная статья — размышление о совместимости декларативной и императивной парадигм программирования и возможности их одновременного использования в рамках одного языка программирования одновременно.\nЧто такое “Декларативное программирование”? Вначале мне захотелось разобраться, а существуют ли чисто декларативные языки программирования? Такие, которые могут полностью обходятся без императивных конструкций?\nНо чуть не споткнулся уже в самом начале, т.к. даже само определение «декларативное программировании», в вики описывается следующим образом:\nДекларати́вное программи́рование — парадигма программирования, в которой задаётся спецификация решения задачи, то есть описывается, что представляет собой проблема и ожидаемый результат. Противоположностью декларативного является императивное программирование, описывающее на том или ином уровне детализации, как решить задачу и представить результат.\nУже в изначальном определении закладывается противопоставление парадигм, а дальше идут рассуждения о «направлении» программирования. И хоть вики сама и не является авторитетным источником информации, но даже такая заготовка статьи смогла показать направление поиска ответов на первый поставленный вопрос.\nИ заставил задуматься один абзац в конце статьи следующего содержания:\n«Чисто декларативные» компьютерные языки зачастую неполны по Тьюрингу — так как теоретически не всегда возможно порождение исполняемого кода по декларативному описанию. Это иногда приводит к спорам о корректности термина «декларативное программирование» (менее спорным является «декларативное описание решения» или, что то же самое, «декларативное описание задачи»).\nСудя по наличию такой оговорки, ставится под сомнение наличие «чисто декларативных» языков. И как только пришлось задуматься над это мыслью, то сразу стало очевидным, что какой бы декларативный язык программирования не существовал, то в нем должна быть как минимум одна императивная конструкция, которая будет запускать поиск решения! Ведь любой синоним слова «выполнить» или «запустить» по определению будет императивом!\nНапример в языке Prolog, который обычно и приводят в качестве примера декларативного языка программирования, “замаскированным” императивным оператором является знак вопроса. Он кажется естественным и логичным, как же без него? Но по своей сути, это императивная конструкция!\nТоже самое касается и языка SQL. Он тоже как бы декларативный, но неожиданно все его команды являются императивными по сути. SELECT, CREATE, ALTER, DROP, INSERT, UPDATE, DELETE и т. д., а декларативными являются только описания условий их выполнения!\nВ результате, у меня так и не получилось найти чисто-декларативный язык программирования без императивных операторов (может быть, Вики права и такого языка программирования и вовсе не существует?).\nА что отличает декларативные языки программирования от императивных? Согласно определению, декларативными языками программирования их называют из-за возможности записать некие условия в декларативном стиле. Но кроме этого, в декларативных языках как правило присутствует и некий внутренний механизм поиска решений. Подобный “вычислитель” есть и в SQL и Prolog и во многих других декларативных языках.\nИнтересно, а является ли внутренняя система поиска решений обязательным признаком декларативного стиля программирования или это только особенность конкретного языка программирования, которая не зависит от декларативного стиля написания кода?\nЧтобы проверить данные предположения, можно было попробовать написать классическую декларативную программу на императивном языке, у которого отсутствует внутренний механизм поиска решений.\nА заодно, таким образом можно будет и изучить вопрос, получится ли написать программу в декларативном стиле используя обычный императивный язык программирования?\nДля примера, решил попробовать повторить уже классическую программу в декларативном стиле на Прологе.\nparent(\"Tom\",\"Jake\"). parent(\"Janna\",\"Jake\"). parent(\"Tom\",\"Tim\"). male(\"Tom\"). male(\"Tim\"). male(\"Jake\"). female(\"Janna\"). brother(X,Y):-parent(Z,X),parent(Z,Y),male(X),male(Y),X\\=Y. ? brother Получилась вот такая функционально - эквивалентная программа на С++, которая максимально приближена по стилю к декларативному прототипу:\nenum sex_ { male, female }; struct human; typedef std::vector\u003chuman *\u003e parent_; struct human { const char *name; sex_ sex; parent_ parent; }; human Tom{\"Tom\", male,{}}; human Janna{\"Janna\", female,{}}; human Jake{\"Jake\", male,{\u0026Tom, \u0026Janna}}; human Tim{\"Tim\", male,{\u0026Tom}}; std::vector\u003chuman *\u003e humans{\u0026Tom, \u0026Janna, \u0026Jake, \u0026Tim}; auto brothers = [](human * a, human * b) { auto intersec = [](parent_ \u0026a, parent_ \u0026 b) { for (auto elem_a : a) { for (auto elem_b : b) { if(elem_a \u0026\u0026 elem_b \u0026\u0026 elem_a == elem_b) { return true; } } } return false; }; return a \u0026\u0026 b \u0026\u0026 a != b \u0026\u0026 a-\u003esex == male \u0026\u0026 b-\u003esex == male \u0026\u0026 (intersec(a-\u003eparent, b-\u003eparent)); }; for (auto a : humans) { for (auto b : humans) { if(brothers(a, b)) { std::cout \u003c\u003c a-\u003ename \u003c\u003c \" and \" \u003c\u003c b-\u003ename \u003c\u003c \"\\n\"; } } } Конечно, текст на С++ получается значительно многословней, чем вариант на Прологе, но по сути, это почти дословное повторение декларативного стиля написания кода. Тем более, не стоит забывать про рассуждения в начале статьи об изначальном выборе концепции при создании языка и “принуждении” программистов пользоваться только одной, изначально выбранной парадигмой разработки.\nТаким образом, можно с высокой долей уверенности утверждать, что теоретически можно писать код одновременно в разных стилях.\nНо что тогда мешает в рамках одного языка программирования писать с использованием императивного и декларативного стиля? Неужели только убежденность создателей языков в том, что императивный и декларативный стили программирования являются взаимоисключающими? И только из-за этого получаются языки программирования, синтаксис которых подходит для использования одной единственной парадигмы?\nНо если это так, то что мешает попробовать разработать синтаксис языка программирования, в котором можно было бы использовать сразу императивный и декларативный стили программирования одновременно?\nЧто мешает совместить императивный и декларативный стили написания в рамках одной программы? В любой компьютерной программе всегда существует разделение кода на описание данных и на языковые конструкции для их обработки, т.е. фактически это разделение на данные и на функции. Мне кажется, что основная сложность, которая не дает использовать разные стили программирования в рамках одного языка, это необходимость разделять описываемые сущности на «данные» и «управляющие конструкции». Ведь это свойство (необходимость разделения сущностей на “данные” и “функции”), является неотъемлемой частью любого языка программирования.\nЭто не удивительно, ведь на заре становления ИТ индустрии, создатели первых языков программирования ориентировались исключительно на императивный стиль, потому что назначением любого компилятора было - преобразовать исходный текст программы в машинные инструкции. И на примерах модульного, структурного и объекто-ориентированного подходах показана и доказана необходимость оформления исполняемого кода в выделенные процедуры с последующей их группировкой в модули и классы.\nА декларативный стиль написания программ стал появляться только после создания высокоуровневых языков программирования. И основная цель создания данных языков сместилась на поиск решения конечного пользователя, а не на упрощение генерации бинарных файлов с машинными инструкциями. Если внимательно посмотреть на приведенные выше примеры кода, то можно заметить, что в них определения данных и операторы для их обработки идут вперемешку, (для примера на С++ это определение лямбд функции), что кардинально отличается от императивного подхода.\nТак может быть, основная особенность декларативного стиля как раз и заключается в том, что в нем не разделяются «данные» и «действия над данными»? Или как вариант, можно не указывать выполняемые действия над данными вовсе (как в некоторых SQL конструкциях)?\nМожет быть как раз именно эта особенность (возможность последовательной записи программного кода в соответствии с собственными логическими рассуждениями, в которых могут перемежаться «данные» и «функции», как это происходит при человеческом мыслительном процессе), не дает в полной мере реализовать возможность совмещения императивных и декларативных стилей программирования?\nИ если это так, тогда можно попробовать разработать такой синтаксис, который будет поддерживать определение как данных, так и декларацию функций в рамках единого потока языковых конструкций!\nПроверка гипотезы в новом языке программирования Для поверки данного предположения, я решил добавить в свой новый язык программирования (синтаксис которого допускает определение функций в одном потоке с описанием обрабатываемых данных), недостающие алгоритмические конструкции, которые позволяли бы реализовать императивный стиль программирования, несмотря на изначальную ориентацию только на декларативную парадигму.\nПравда с учетом изначальных ограничений синтаксиса нового языка (запрет на применение операторов в виде зарезервированных ключевых слов), в качестве оператора проверки условия была выбрана синтаксическая конструкция, соответствующая по смыслу термину «следует», т.е. тире и угловая скобка «-\u003e».\nВ результате, условный оператор получился практически математический, который легко объединяется в последовательности для реализации проверки множественных условий вида «else if». А для объединения сразу нескольких логического операторов между собой и для отделения их от последующего действия, операторы проверки условия можно заключать в круглые скобки.\nВ общем случае условный оператор в новом языке программирования имеет вид:\nусловие -\u003e действие; или (условие) -\u003e {действие}; или (условие1 || условие2) -\u003e {действие} -\u003e {действие иначе}; Или расширенный вариант, для наглядности записанный с отступами:\n(условие1) -\u003e {действие1} (условие2) -\u003e {действие2} (условие3) -\u003e {действие3} -\u003e {действие_иначе}; Тогда и операторы циклов можно будет записать практически аналогично, только выбрав в качестве оператора, не оператор следования, а следование с возвратом (раз уж нужно указывать циклическое действие).\nЦикл пока:\n(условие) \u003c-\u003e {тело цикла}; счетный цикл для работы с итератором:\n(счетчик_или_данные!)? \u003c-\u003e {тело цикла}; В этом случае, решение тестового примера декларативной программы на Прологе можно будет легко оформить, как в императивном, так и в декларативном стилях одновременно!\nм := \"муж.\"; ж := \"жен.\"; human @= term(пол=, parent=[,]); Tom @= human(пол=м); Janna @= human(пол=ж); Jake @= human(м, [\u0026Tom, \u0026Janna,]); Tim @= human(пол=м, parent=[\u0026Tom,]); brother(h1, h2) \u0026\u0026= $h1!=$h2, $h1.пол==м, $h2.пол==м, $h1.parent \u0026 $h2.parent; // Оператор «\u0026» побитовое «И» для чисел или операция пересечения для множеств // Запись алгоритма поиска решения в императивном стиле (h1=human!, h2=human!)? \u003c-\u003e { (brother(h1, h2)) -\u003e { @print($h1, $h2, «\\n»); } }; // Краткая запись алгоритма поиска решения в императивном стиле (h1=human!, h2=human!)? \u003c-\u003e brother($h1, $h2) -\u003e @print($h1, $h2, «\\n»); // Запись поиска решения в декларативном стиле brother(human!, human!)?; Примерно это и требовалось показать!\nЗ.Ы. Я почти закончил эксперименты с синтаксисом языка. И теперь, после добавления в него недостающих алгоритмический конструкций (ветвления и циклов), планирую, что следующая статья о новом языке программирования будет посвящена описанию его полного синтаксиса и публикации исходников прототипа компилятора для возможности поиграться на реальных примерах.\nЗ.З.Ы В комментариях @gbg привел очень простой ответ на один из поднятых вопросов. Причем в более элегантном виде и без написания кода!\nНу и пять копеечек про ООП. Как ни странно:\nВ нем таки есть декларативная часть, все эти pubic, private, virtual, etc Эта декларативная часть, внезапно, элегантно позволяет реализовывать декомпозицию и управление сложностью. При наличии перегрузок, можно поиграть в алгебраическое мышление, рассматривая взаимодействие двух объектов как бинарную операцию. Ух ты, ООП - это обкатанная практикой технология, которая совмещает декларатив с императивом и вроде позволяет освоившим ее вкусно кушать и мягко спать!\nСсылка на первую публикаци\n","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/ru/blog/prog-styles-same-time/","tags":"","title":"Можно ли использовать декларативный и императивный стили написания программ одновременно?"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nХочу представить на обсуждение читателей немного необычный концепт языка программирования, в котором отсутствует проблема, присущая практически всем промышленным языкам - постоянное увеличение сложности синтаксиса языка из-за его естественного развития по мере выхода новых версий и добавления новых фич. Эта проблема описана в статье “Простое сложное программирование” и Какая “идеальная” цель развития у языков программирования?\nПосле нескольких экспериментов с синтаксисом, хочется проверить выработанную идею на широкой аудитории Хабра, которая как нельзя лучше подходит для этих целей.\nОсобенности языка:\nНизкий порог входа и естественное ограничение уровня сложности в течение длительного времени даже при условии постоянного развития самого языка. Возможность писать код программы как в декларативной, так и в императивной парадигме с использованием процедурного, модульного и объектно-ориентированного подхода. Ну и в соответствии с собственным наблюдением Хабр — ума палата, буду рад любым комментариям и предложениям, которые помогут протестировать или улучшить предлагаемое решение.\nВведение Первой необычной особенностью языка является полное отсутствие зарезервированных ключевых слов. Точнее, планируется использовать только одно единственное ключевое слово (название языка), которое может быть как главной точкой входа в приложение, так и способом доступа к настройкам языка под конкретную предметную область, например при необходимости реализации DSL парадигмы.\nВ настоящий момент название языка не выбрано, поэтому для примеров используется просто слово lang, которое в будущем будет изменено.\nДанная особенность (отсутствие зарезервированных ключевых слов) реализуется за счет того, грамматика языка основана на использовании общеупотребительных символов и классических знаков препинания, а все остальные букво-символьные последовательности при парсинге программы рассматриваются как “токены”.\nКомпилятор языка реализуется как transpiler - преобразование исходного кода программы, написанной на одном языке программирования, в эквивалентный исходный код на другом языке. Первые эксперименты с синтаксисом я начинал на Python, но после осознания необходимости разработки не только интерпретатора, но и компилятора непосредственно в исполняемый код, решил остановиться на C++. Хотя в принципе, язык реализации может быть любым.\nИспользование транспиляции при реализации компилятора решает сразу множество очевидных и не очень задач. Сразу отпадает необходимость разрабатывать низкоуровневый компилятор в исполняемый процессорный код, а в моем случае основным бонусом такого подхода становится возможность использования императивной парадигмы программирования за счет вставок кода непосредственно в исходный код приложения на языке реализации.\nИ именно этот момент позволяет естественно разделить декларативный и императивный способ написания программы. В этом случае в декларативной парадигме реализуется только одна из трех базовых управляющих конструкций, необходимых и достаточных при реализации любого алгоритма — следование.\nДругими словами, в декларативном стиле описывается только последовательность операций, которые следуют одна за другой, но отсутствует возможность запрограммировать циклы или ветвление (переходы) по условию. Из-за этого в декларативном стиле можно записать только следующие типы языковых конструкций:\nкомментарий определение переменной и присвоение ей значения создание объекта и назначение его свойствам значений по умолчанию создание функции (метода для всего класса объектов) вызов функции или итератора непосредственная вставка кода на языке реализации Так как цель текущей публикации - протестировать общую концепцию, то начну сразу с примеров без длинного описания подробностей, а некоторые нюансы буду комментировать по ходу дела. Тем более, самая главная цель “низкий порог входа” само собой подразумевает возможность самостоятельно разобраться в синтаксисе. Тем не менее, совсем без знаний языка реализации не обойтись и начальные знания в программировании на С/С++ все равно необходимы.\n“Привет, мир!” в императивной парадигме Определение обычной функции выполняется с помощью оператора присвоения “:=”, а программный код на языке реализации (в данном случае на C++) заключается в фигурные скобки. Простой пример вывода строки на экран выглядит примерно так:\nprint(str=\"\") := { printf(\"%s\", static_cast\u003cchar *\u003e($str)); } Функция print с аргументом по умолчанию в виде пустой строки внутри себя вызывает обычный printf из стандартной библиотеки.\nСоответственно “Привет, мир!” в императивной парадигме программирования будет выглядеть тривиально:\n#!/bin/lang print(str=\"\") := { printf(\"%s\", static_cast\u003cchar *\u003e($str)); }; @print(\"Привет, мир!\\n\"); Из примера видно, что обращение к аргументам внутри С++ кода происходит с использованием символа $, который указывается вначале именованного аргумента. Кроме этого, для доступа к аргументам функции можно обращаться по их порядковым номерам начиная с первого ($1, $2, $3 и т. д.). Зарезервированный аргумент $0 содержит сам объект, метод которого вызывается или nullptr, если функция не принадлежит объекту.\nОбычные функции являются именно обычными функциями в понимании С/С++. Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д. Технически, код такой функции парсится на предмет замены использованных аргументов, специальным образом декорируется её имя и добавляются специальные маркеры для идентификации содержимого. После этого исходный текст готов для сборки обычным С++ компилятором для превращения в динамическую библиотеку и после её загрузки функцию можно будет вызвать в любой момент (для вызова функции перед её именем необходимо указать символ \"@\").\nНепосредственное выполнение файла в режиме интерпретатора происходит в два этапа. На первом этапе из текста программы генерируется временный С++ файл с исходным кодом всех функций, этот файл компилируется gcc и собирается динамическая библиотека.\nНа втором этапе, собранная динамическая библиотека загружается средой выполнения, а исходный текст программы начинает последовательно выполнятся интерпретатором (все строки, за исключением определений функций).\nЕсть еще вариант, когда вместо интерпретации кода программы, генерируется С++ файл не только для функций, но и для основной части приложения. Тогда на выходе компилятора будет уже обычный бинарный файл, хотя в том случае оперативно поправить текст программы уже не получится.\nЛогическое программирование в декларативной парадигме Так как самым известным языком логического программирования в декларативном стиле считается Prolog, поэтому приведу простой пример программы Brother (поиска братьев) на Прологе и эквивалентный ему код на новом языке.\nProlog:\nmale(\"Tom\"). male(\"Tim\"). male(\"Jake\"). female(\"Janna\"). parent(\"Tom\",\"Jake\"). parent(\"Janna\",\"Jake\"). parent(\"Tom\",\"Tim\"). brother(X,Y):- parent(Z,X),parent(Z,Y),male(X),male(Y),X\\=Y. Вывод: (Jake, Tim) (Tim, Jake)\nТот же самый пример:\n#!/bin/lang human:=@term(sex=,parent=); Tom:=@human(male); Janna:=@human(female); Jake:=@human(male, (Tom, Janna,)); Tim:=@human(sex=male, parent=(Tom,)); human::brother(test=human!) \u0026\u0026= $0!=$test, $0.sex==male, @intersec($0.parent, $test.parent); human.brother? Вывод: [Tim.brother(Jake), Jake.brother(Tim),]\nНадеюсь, что синтаксис интуитивно понятен, особенно при наличии эквивалентного кода на Прологе, но на всякий случай поясню отдельные моменты.\nhuman:=@term(sex=,parent=); В этой строке создается объект с именем “human” и двумя свойствами “sex” и “parent”, значения которых по умолчанию не определены, а родителем является системный объект “term”. Использование символа \"@\" в начале термина обозначает вызов существующей функции с параметрами, указанными в скобках. В данном случае вызывается конструктор системного объекта “term”, а возвращаемым результатом является новый термин “human”, который можно воспринимать как один экземпляр класса, так и как имя целого класса, если он будет выступать в качестве родителя для других объектов.\nTom:=@human(male); Janna:=@human(female); Jake:=@human(male, (Tom, Janna,)); Tim:=@human(parent=(Tom,), sex=male); Первые две строки создают объекты “Tom” и “Janna”, у которых свойство “sex” установлено в значения “male” и “female” соответственно. А в последней строке при создании объекта Tim значения свойств задается с указанием их имени.\nКонструкции (Tom, Janna,) и (Tom,), это определение константного литерала с типом словарь, которые присваиваются указанным свойствам.\nЧтобы определение словаря не путать с указанием аргументов при вызове функции, в нем содержится обязательная финальная запятая перед закрывающей скобкой. Это правило (финальная запятая перед закрывающей скобкой) действует и при определении литерала массива, только для записи которого используются скобки не круглые, а квадратные (например [,] - пустой массив). Основным отличием словаря от массива, заключаются в способах доступа к их элементам. Для доступа к элементу массива используется целочисленный индекс, а в словаре может быть использован как индекс, так и имя элемента при его наличии. Между словарем и массивом есть еще отличия, но сейчас они не принципиальны.\nИ предпоследняя строка в примере:\nhuman::brother(test=human !) \u0026\u0026= $0 != $test, $0.sex==male, @intersec($0.parent, $test.parent);\nэто определение простой чистой функции “brother” для всех объектов, производных от “human”. Данная функция принимает один именованный аргумент “test”, значением по умолчанию которого является итератор объектов класса “human”.\nОператор \u0026\u0026= означает определение простой чистой функции, т. е. функции без внешних зависимостей, которая не имеет доступа к глобальному контексту, а результат выполнения которой является логическое значение, которое вычисляется по схеме логическое И для всех условий, указанных в теле функции через запятую.\nВыполнение и вывод результата выполнения программы происходит в строке human.brother?\nВосклицательный и вопросительный знаки обозначают итератор. Итератор “!” возвращает один текущий элемент из коллекции и передвигает указатель на следующий, а итератор “?” возвращает сразу всю коллекцию объектов целиком.\nДругими словами при выполнении строки программы human.brother ? происходит последовательный перебор всей коллекции объектов типа “human”, где у каждого объекта выполняется функция “brother” с аргументами по умолчанию. А так как в качестве аргумента по умолчанию указан итератор human !, то в качестве аргумента последовательно предается каждый из элементов указанного класса. По сути, при выполнении этой строки происходит полный перебор всех возможных комбинаций объектов класса “human” каждый с каждым.\nБолее подробное описание работы итератора и причина выбора такого синтаксиса опубликовано в отдельной статье Лаконичный итератор для декларативного синтаксиса\nРезультат выполнения будет состоять из тех пар объектов, для которых функция “brother” вернет истину, т.е. результат выполнения будет массив из двух пар объектов [Tim.brother(Jake), Jake.brother(Tim),].\nФормулировка проверяемой концепции Тестируемая концепция заключается в следующем. Синтаксис языка программирования состоит как бы из двух частей, каждая из которых является относительно независимой и в тоже время они связаны между собой.\nПервая часть сложная — предназначена для описания алгоритмов в императивном стиле на обычном языке программирования, поэтому внутри функций разработчику доступны все возможности языка реализации.\nВторая часть простая (по сравнению с первой) — предназначена только для логического описания задачи в декларативном стиле. Именно эта часть используется для начального уровня использования, а естественное ограничение только на последовательное выполнение операторов (т.е. отсутствие циклов и ветвлений) не доставляет чрезмерных сложностей в понимании исходного текста программы даже в будущем по мере развития языка.\nСвязь между двумя вариантами синтаксиса прозрачна и реализуется за счет совместного использования переменных и функций, декларация и обращение к которым происходит в едином стиле в обоих случаях за счет унификации синтаксиса на уровне использования знаков препинания.\nСейчас я специально не привожу полного синтаксиса и подробного описания остальных возможностей языка, т.к. компилятор пока не готов для публичной презентации. Но буду крайне благодарен за любой отклик или дельные предложения в отношении предложенной концепции.\nОсобенно это касается возможных конфликтов по синтаксису в представленных примерах.\n","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/blog/unusual-prog/","tags":"","title":"Необычная концепция синтаксиса языка программирования"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nХочу представить на обсуждение читателей немного необычный концепт языка программирования, в котором отсутствует проблема, присущая практически всем промышленным языкам - постоянное увеличение сложности синтаксиса языка из-за его естественного развития по мере выхода новых версий и добавления новых фич. Эта проблема описана в статье “Простое сложное программирование” и Какая “идеальная” цель развития у языков программирования?\nПосле нескольких экспериментов с синтаксисом, хочется проверить выработанную идею на широкой аудитории Хабра, которая как нельзя лучше подходит для этих целей.\nОсобенности языка:\nНизкий порог входа и естественное ограничение уровня сложности в течение длительного времени даже при условии постоянного развития самого языка. Возможность писать код программы как в декларативной, так и в императивной парадигме с использованием процедурного, модульного и объектно-ориентированного подхода. Ну и в соответствии с собственным наблюдением Хабр — ума палата, буду рад любым комментариям и предложениям, которые помогут протестировать или улучшить предлагаемое решение.\nВведение Первой необычной особенностью языка является полное отсутствие зарезервированных ключевых слов. Точнее, планируется использовать только одно единственное ключевое слово (название языка), которое может быть как главной точкой входа в приложение, так и способом доступа к настройкам языка под конкретную предметную область, например при необходимости реализации DSL парадигмы.\nВ настоящий момент название языка не выбрано, поэтому для примеров используется просто слово lang, которое в будущем будет изменено.\nДанная особенность (отсутствие зарезервированных ключевых слов) реализуется за счет того, грамматика языка основана на использовании общеупотребительных символов и классических знаков препинания, а все остальные букво-символьные последовательности при парсинге программы рассматриваются как “токены”.\nКомпилятор языка реализуется как transpiler - преобразование исходного кода программы, написанной на одном языке программирования, в эквивалентный исходный код на другом языке. Первые эксперименты с синтаксисом я начинал на Python, но после осознания необходимости разработки не только интерпретатора, но и компилятора непосредственно в исполняемый код, решил остановиться на C++. Хотя в принципе, язык реализации может быть любым.\nИспользование транспиляции при реализации компилятора решает сразу множество очевидных и не очень задач. Сразу отпадает необходимость разрабатывать низкоуровневый компилятор в исполняемый процессорный код, а в моем случае основным бонусом такого подхода становится возможность использования императивной парадигмы программирования за счет вставок кода непосредственно в исходный код приложения на языке реализации.\nИ именно этот момент позволяет естественно разделить декларативный и императивный способ написания программы. В этом случае в декларативной парадигме реализуется только одна из трех базовых управляющих конструкций, необходимых и достаточных при реализации любого алгоритма — следование.\nДругими словами, в декларативном стиле описывается только последовательность операций, которые следуют одна за другой, но отсутствует возможность запрограммировать циклы или ветвление (переходы) по условию. Из-за этого в декларативном стиле можно записать только следующие типы языковых конструкций:\nкомментарий определение переменной и присвоение ей значения создание объекта и назначение его свойствам значений по умолчанию создание функции (метода для всего класса объектов) вызов функции или итератора непосредственная вставка кода на языке реализации Так как цель текущей публикации - протестировать общую концепцию, то начну сразу с примеров без длинного описания подробностей, а некоторые нюансы буду комментировать по ходу дела. Тем более, самая главная цель “низкий порог входа” само собой подразумевает возможность самостоятельно разобраться в синтаксисе. Тем не менее, совсем без знаний языка реализации не обойтись и начальные знания в программировании на С/С++ все равно необходимы.\n“Привет, мир!” в императивной парадигме Определение обычной функции выполняется с помощью оператора присвоения “:=”, а программный код на языке реализации (в данном случае на C++) заключается в фигурные скобки. Простой пример вывода строки на экран выглядит примерно так:\nprint(str=\"\") := { printf(\"%s\", static_cast\u003cchar *\u003e($str)); } Функция print с аргументом по умолчанию в виде пустой строки внутри себя вызывает обычный printf из стандартной библиотеки.\nСоответственно “Привет, мир!” в императивной парадигме программирования будет выглядеть тривиально:\n#!/bin/lang print(str=\"\") := { printf(\"%s\", static_cast\u003cchar *\u003e($str)); }; @print(\"Привет, мир!\\n\"); Из примера видно, что обращение к аргументам внутри С++ кода происходит с использованием символа $, который указывается вначале именованного аргумента. Кроме этого, для доступа к аргументам функции можно обращаться по их порядковым номерам начиная с первого ($1, $2, $3 и т. д.). Зарезервированный аргумент $0 содержит сам объект, метод которого вызывается или nullptr, если функция не принадлежит объекту.\nОбычные функции являются именно обычными функциями в понимании С/С++. Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д. Технически, код такой функции парсится на предмет замены использованных аргументов, специальным образом декорируется её имя и добавляются специальные маркеры для идентификации содержимого. После этого исходный текст готов для сборки обычным С++ компилятором для превращения в динамическую библиотеку и после её загрузки функцию можно будет вызвать в любой момент (для вызова функции перед её именем необходимо указать символ \"@\").\nНепосредственное выполнение файла в режиме интерпретатора происходит в два этапа. На первом этапе из текста программы генерируется временный С++ файл с исходным кодом всех функций, этот файл компилируется gcc и собирается динамическая библиотека.\nНа втором этапе, собранная динамическая библиотека загружается средой выполнения, а исходный текст программы начинает последовательно выполнятся интерпретатором (все строки, за исключением определений функций).\nЕсть еще вариант, когда вместо интерпретации кода программы, генерируется С++ файл не только для функций, но и для основной части приложения. Тогда на выходе компилятора будет уже обычный бинарный файл, хотя в том случае оперативно поправить текст программы уже не получится.\nЛогическое программирование в декларативной парадигме Так как самым известным языком логического программирования в декларативном стиле считается Prolog, поэтому приведу простой пример программы Brother (поиска братьев) на Прологе и эквивалентный ему код на новом языке.\nProlog:\nmale(\"Tom\"). male(\"Tim\"). male(\"Jake\"). female(\"Janna\"). parent(\"Tom\",\"Jake\"). parent(\"Janna\",\"Jake\"). parent(\"Tom\",\"Tim\"). brother(X,Y):- parent(Z,X),parent(Z,Y),male(X),male(Y),X\\=Y. Вывод: (Jake, Tim) (Tim, Jake)\nТот же самый пример:\n#!/bin/lang human:=@term(sex=,parent=); Tom:=@human(male); Janna:=@human(female); Jake:=@human(male, (Tom, Janna,)); Tim:=@human(sex=male, parent=(Tom,)); human::brother(test=human!) \u0026\u0026= $0!=$test, $0.sex==male, @intersec($0.parent, $test.parent); human.brother? Вывод: [Tim.brother(Jake), Jake.brother(Tim),]\nНадеюсь, что синтаксис интуитивно понятен, особенно при наличии эквивалентного кода на Прологе, но на всякий случай поясню отдельные моменты.\nhuman:=@term(sex=,parent=); В этой строке создается объект с именем “human” и двумя свойствами “sex” и “parent”, значения которых по умолчанию не определены, а родителем является системный объект “term”. Использование символа \"@\" в начале термина обозначает вызов существующей функции с параметрами, указанными в скобках. В данном случае вызывается конструктор системного объекта “term”, а возвращаемым результатом является новый термин “human”, который можно воспринимать как один экземпляр класса, так и как имя целого класса, если он будет выступать в качестве родителя для других объектов.\nTom:=@human(male); Janna:=@human(female); Jake:=@human(male, (Tom, Janna,)); Tim:=@human(parent=(Tom,), sex=male); Первые две строки создают объекты “Tom” и “Janna”, у которых свойство “sex” установлено в значения “male” и “female” соответственно. А в последней строке при создании объекта Tim значения свойств задается с указанием их имени.\nКонструкции (Tom, Janna,) и (Tom,), это определение константного литерала с типом словарь, которые присваиваются указанным свойствам.\nЧтобы определение словаря не путать с указанием аргументов при вызове функции, в нем содержится обязательная финальная запятая перед закрывающей скобкой. Это правило (финальная запятая перед закрывающей скобкой) действует и при определении литерала массива, только для записи которого используются скобки не круглые, а квадратные (например [,] - пустой массив). Основным отличием словаря от массива, заключаются в способах доступа к их элементам. Для доступа к элементу массива используется целочисленный индекс, а в словаре может быть использован как индекс, так и имя элемента при его наличии. Между словарем и массивом есть еще отличия, но сейчас они не принципиальны.\nИ предпоследняя строка в примере:\nhuman::brother(test=human !) \u0026\u0026= $0 != $test, $0.sex==male, @intersec($0.parent, $test.parent);\nэто определение простой чистой функции “brother” для всех объектов, производных от “human”. Данная функция принимает один именованный аргумент “test”, значением по умолчанию которого является итератор объектов класса “human”.\nОператор \u0026\u0026= означает определение простой чистой функции, т. е. функции без внешних зависимостей, которая не имеет доступа к глобальному контексту, а результат выполнения которой является логическое значение, которое вычисляется по схеме логическое И для всех условий, указанных в теле функции через запятую.\nВыполнение и вывод результата выполнения программы происходит в строке human.brother?\nВосклицательный и вопросительный знаки обозначают итератор. Итератор “!” возвращает один текущий элемент из коллекции и передвигает указатель на следующий, а итератор “?” возвращает сразу всю коллекцию объектов целиком.\nДругими словами при выполнении строки программы human.brother ? происходит последовательный перебор всей коллекции объектов типа “human”, где у каждого объекта выполняется функция “brother” с аргументами по умолчанию. А так как в качестве аргумента по умолчанию указан итератор human !, то в качестве аргумента последовательно предается каждый из элементов указанного класса. По сути, при выполнении этой строки происходит полный перебор всех возможных комбинаций объектов класса “human” каждый с каждым.\nБолее подробное описание работы итератора и причина выбора такого синтаксиса опубликовано в отдельной статье Лаконичный итератор для декларативного синтаксиса\nРезультат выполнения будет состоять из тех пар объектов, для которых функция “brother” вернет истину, т.е. результат выполнения будет массив из двух пар объектов [Tim.brother(Jake), Jake.brother(Tim),].\nФормулировка проверяемой концепции Тестируемая концепция заключается в следующем. Синтаксис языка программирования состоит как бы из двух частей, каждая из которых является относительно независимой и в тоже время они связаны между собой.\nПервая часть сложная — предназначена для описания алгоритмов в императивном стиле на обычном языке программирования, поэтому внутри функций разработчику доступны все возможности языка реализации.\nВторая часть простая (по сравнению с первой) — предназначена только для логического описания задачи в декларативном стиле. Именно эта часть используется для начального уровня использования, а естественное ограничение только на последовательное выполнение операторов (т.е. отсутствие циклов и ветвлений) не доставляет чрезмерных сложностей в понимании исходного текста программы даже в будущем по мере развития языка.\nСвязь между двумя вариантами синтаксиса прозрачна и реализуется за счет совместного использования переменных и функций, декларация и обращение к которым происходит в едином стиле в обоих случаях за счет унификации синтаксиса на уровне использования знаков препинания.\nСейчас я специально не привожу полного синтаксиса и подробного описания остальных возможностей языка, т.к. компилятор пока не готов для публичной презентации. Но буду крайне благодарен за любой отклик или дельные предложения в отношении предложенной концепции.\nОсобенно это касается возможных конфликтов по синтаксису в представленных примерах.\n","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/ru/blog/unusual-prog/","tags":"","title":"Необычная концепция синтаксиса языка программирования"},{"body":"\nВ очередной раз увидел на Хабре статью про сложное дело под названием «программирование». И то, что программирование действительно является делом не простым воспринимается как факт и обычно не требует какого либо подтверждения.\nНо понятие «сложность» сродни термину «куча». Для кого-то и пять кокосов это не куча, а кого-то съел один и «больше не хочется» - значит для него и единственного кокоса будет много.\nТак и со сложностью ПО. Вроде бы увеличение сложности является для всех очевидным и наблюдается во всех сферах применения IT технологий, да и сами языки программирования по мере своего развития становятся все сложнее, а вот оценивать «сложность» с помощью численных метрик — дело заведомо неблагодарное, но и «нельзя управлять тем, что невозможно измерить …».\nОбычно разговоры о «сложности» включают в себя только оценочные суждения без какой либо численной оценки. А так как лично меня интересует вопрос сложности языков программирования, то я решил посчитать сложность реализации компилятора gcc в каких нибудь условных попугаях. Вдруг можно будет увидеть какие нибудь закономерности?\nВыбор «попугаев» для измерения Я не стал придумывать свои или вычислять эмпирические метрики программного кода, и в качестве «попугая» решил взять самую простую метрику SLOC (англ. Source Lines of Code) — количество строк исходного текста компилятора, которая очень легко вычисляется.\nПравда, с её помощью можно будет оценивать сложность языка только при следующем допущении — сложность языка должна находиться в прямой зависимости от сложности его реализации, если для простых синтаксических конструкций будет требовать меньше кода, чем для более сложных.\nКонечно, использование метрики «количество строк исходного кода» имеет и свои недостатки, т.к. она сильно зависит от используемого языка программирования, стиля оформления исходного кода и в общем случае не позволяет сравнивать несколько разных проектов между собой.\nНо для численной оценки сложности кода в рамках одного проекта, метрика SLOC подходит хорошо.\nМетодика подсчета SLOC Изначально попробовал использовать простой bash скрипт с поиском по маске и подсчетом числа строк в файлах исходника через wc -l. Но через некоторое время стало понятно, что приходится изобретать очередной велосипед.\nПоэтому решил взять уже готовый. После быстрого поиска остановился на утилите SLOCCount, которая умеет анализировать почти три десятка типов исходников.\nСписок типов файлов для автоматического анализа 1. Ada (.ada, .ads, .adb) 2. Assembly (.s, .S, .asm) 3. awk (.awk) 4. Bourne shell and variants (.sh) 5. C (.c) 6. C++ (.C, .cpp, .cxx, .cc) 7. C shell (.csh) 8. COBOL (.cob, .cbl) as of version 2.10 9. C# (.cs) as of version 2.11 10. Expect (.exp) 11. Fortran (.f) 12. Haskell (.hs) as of version 2.11 13. Java (.java) 14. lex/flex (.l) 15. LISP/Scheme (.el, .scm, .lsp, .jl) 16. Makefile (makefile) — not normally shown. 17. Modula-3 (.m3, .i3) as of version 2.07 18. Objective-C (.m) 19. Pascal (.p, .pas) 20. Perl (.pl, .pm, .perl) 21. PHP (.php, .php[3456], .inc) as of version 2.05 22. Python (.py) 23. Ruby (.rb) as of version 2.09 24. sed (.sed) 25. SQL (.sql) — not normally shown. 26. TCL (.tcl, .tk, .itk) 27. Yacc/Bison (.y) \u003c/code\u003e Причем, считает не просто количество строк исходного текста, но и умеет игнорировать комментарии, исключает из подсчета дубли файлов (сравнивает их хеш суммы), а также выводит расчетную трудоемкость, примерную оценку стоимости разработки анализируемого проекта и другие характеристики.\nМеня изначально интересовал объем исходников на С/С++ и может быть еще на Ассемблере, если таких файлов окажется достаточно много. Но после начала работы очень обрадовался, что не стал изобретать велосипед, а взял готовую тулзу, т.к. она отдельно считала статистику исходных файлов синтаксического анализатора Yacc/Bison (.y), который и определяет фактическую сложность парсера (читай сложность синтаксиса языка программирования).\nСтарые исходники gcc брал с https://gcc.gnu.org/mirrors.html, но перед запуском анализатора удалил каталоги других компиляторов (ada, fortran, java и т.д.), чтобы они не попадали в итоговую статистику.\nРезультаты в попугаях Итоговая статистика\nОбъем кода синтаксического анализатора Yacc/Bison\nОбъем общей которой базы GCC (только для языков C и C++)\nВыводы К сожалению, синтаксический анализатор Yacc/Bison использовался только до 3 версии, а после его использование свелось на нет. Поэтому оценить сложность синтаксиса С/С++ с помощью объема кода парсера можно лишь примерно до 1996-98 года, после чего его стали постепенно выпиливать, т.е. чуть менее, чем за десять лет. Но даже за этот период объем кодовой базы синтаксического анализатора вырос двукратно, что примерно соответствует по времени реализации стандарта C99.\nНо даже если не учитывать код синтаксического анализатора, то объем общей кодовой базы так же коррелирует с внедрением новых стандартов C++: C99, С11 и C14.\nНа графике не видно выраженного пика для С+17 и следующих версий, но предполагаю, что при текущем объеме кодой базы (более 4 миллионов строк только С и С++ кода), несколько тысяч строк, необходимых для поддержки синтаксических конструкций новых стандартов просто незаметно.\nВывод первый - очевидный. Рост сложности инструментов разработки Фактически на примере проекта GCC можно видеть постоянный и неотвратимый рост сложности рабочих инструментов программистов.\nИ как бы не говорили о деградации разработки в статье “Хорошие времена рождают слабаков”, о системном кризисе программного обеспечения, который носит поколенческом характер, но мне кажется тут дело немного в другом.\nОбновление персонала и как следствие — необходимость обучения новых сотрудников старым наработкам, тут дело не сколько в передаче знаний, сколько в возможности эти знания усваивать.\nПричем возможность усвоения знаний для разных поколений будет разная, но не из-за того, что предыдущее поколение было умнее, а у нового поколения не хватает толку в этом разобрать. Просто изменяется окружение и усложняются рабочие инструменты, по сравнению с теми, которые были в ходу у предыдущего поколения.\nВывод второй — порог входа Представьте, что нужно «сделать свой сайт». Естественно нужно определить, какую CMS для него использовать и какой брать хостинг. И если с хостингом вопрос решается очень просто, конечно же в TimeWeb, да еще и с бонусом по ссылке, то при выборе CMS приходится подумать.\nИ если для простых сайтов существуют и простые решения, то для тех, кто не ищет легких путей существует CMS Drupal, который примечателен тем, что имеет фантастически высокий порог входа для начала использования.\nЭто я к чему? При использовании любого инструмента, как и языка программирования, существует некий минимальный уровень комфортного использования. Причем этот уровень прямо пропорционально связан с размером той целевой аудитории, для которой он предназначен. Точнее, размер возможной аудитории определяется в том числе и требованиями к уровню начальных знаний и квалификации потенциального пользователя.\nИтоговый вывод — не утешительный Если рассматривать увеличение сложности только самого ПО, то это одно дело. Вот к примеру:\nСтатистика ядра Linux с вики\n17 сентября 1991: Linux версии 0.01 (10 239 строк кода). 14 марта 1994: Linux версии 1.0.0 (176 250 строк кода). Март 1995: Linux версии 1.2.0 (310 950 строк кода). 9 июня 1996: Linux версии 2.0.0 (777 956 строк кода). 25 января 1999: Linux версии 2.2.0, изначально довольно недоработанный (1 800 847 строк кода). 4 января 2001: Linux версии 2.4.0 (3 377 902 строки кода). 18 декабря 2003: Linux версии 2.6.0 (5 929 913 строк кода). 23 марта 2009: Linux версии 2.6.29, временный символ Linux — тасманский дьявол Tuz (11 010 647 строк кода). 22 июля 2011: релиз Linux 3.0 (14,6 млн строк кода). 24 октября 2011: релиз Linux 3.1. 15 января 2012: релиз Linux 3.3 преодолел отметку в 15 млн строк кода. 23 февраля 2015: первый релиз-кандидат Linux 4.0 (более 19 млн строк кода). 7 января 2019: первый релиз-кандидат Linux 5.0 (более 26 млн строк кода). А что делать, если сложность программного обеспечения накладывается на тенденцию постоянного усложнения самих рабочих инструментов? Ведь постоянное развитие языков программирования неизбежно повышает порог входа для всех начинающих и только усугубляет проблему сложности разработки ПО.\nДругими словами, не зависимо от того, как хорошо документирован код и как полно он покрыт тестами, через некоторое время устаревают используемые инструменты, завершаются жизненные циклы внешних зависимостей, и самое главное, приходят новые люди взамен тех, кто разработал или сумел разобраться в системе.\nИ у новых людей возникает необходимость разбираться в системе с самого начала, но в других начальных условиях. И из-за этого, сложность изучения системы для всех новых людей будет выше просто по факту того, что изменились внешние условия и усложнились рабочие инструменты, которыми приходится использовать новым сотрудникам.\nПонятно, что чем дальше, тем проще уже не будет. Ведь область IT , это среда с самой высокой конкуренцией. И как уж тут не вспомнить Льюиса Кэррола, что его крылатое выражение\nНужно бежать со всех ног, чтобы только оставаться на месте, а чтобы куда-то попасть, надо бежать как минимум вдвое быстрее!\nВедь это относится не только к Алисе в стране чудес, но и ко всем информационным технологиям в целом!\nПервоначальная публикация\n","categories":"","description":"","excerpt":"\nВ очередной раз увидел на Хабре статью про сложное дело под названием …","ref":"/blog/complex-prog/","tags":"","title":"Простое сложное программирование"},{"body":"\nВ очередной раз увидел на Хабре статью про сложное дело под названием «программирование». И то, что программирование действительно является делом не простым воспринимается как факт и обычно не требует какого либо подтверждения.\nНо понятие «сложность» сродни термину «куча». Для кого-то и пять кокосов это не куча, а кого-то съел один и «больше не хочется» - значит для него и единственного кокоса будет много.\nТак и со сложностью ПО. Вроде бы увеличение сложности является для всех очевидным и наблюдается во всех сферах применения IT технологий, да и сами языки программирования по мере своего развития становятся все сложнее, а вот оценивать «сложность» с помощью численных метрик — дело заведомо неблагодарное, но и «нельзя управлять тем, что невозможно измерить …».\nОбычно разговоры о «сложности» включают в себя только оценочные суждения без какой либо численной оценки. А так как лично меня интересует вопрос сложности языков программирования, то я решил посчитать сложность реализации компилятора gcc в каких нибудь условных попугаях. Вдруг можно будет увидеть какие нибудь закономерности?\nВыбор «попугаев» для измерения Я не стал придумывать свои или вычислять эмпирические метрики программного кода, и в качестве «попугая» решил взять самую простую метрику SLOC (англ. Source Lines of Code) — количество строк исходного текста компилятора, которая очень легко вычисляется.\nПравда, с её помощью можно будет оценивать сложность языка только при следующем допущении — сложность языка должна находиться в прямой зависимости от сложности его реализации, если для простых синтаксических конструкций будет требовать меньше кода, чем для более сложных.\nКонечно, использование метрики «количество строк исходного кода» имеет и свои недостатки, т.к. она сильно зависит от используемого языка программирования, стиля оформления исходного кода и в общем случае не позволяет сравнивать несколько разных проектов между собой.\nНо для численной оценки сложности кода в рамках одного проекта, метрика SLOC подходит хорошо.\nМетодика подсчета SLOC Изначально попробовал использовать простой bash скрипт с поиском по маске и подсчетом числа строк в файлах исходника через wc -l. Но через некоторое время стало понятно, что приходится изобретать очередной велосипед.\nПоэтому решил взять уже готовый. После быстрого поиска остановился на утилите SLOCCount, которая умеет анализировать почти три десятка типов исходников.\nСписок типов файлов для автоматического анализа 1. Ada (.ada, .ads, .adb) 2. Assembly (.s, .S, .asm) 3. awk (.awk) 4. Bourne shell and variants (.sh) 5. C (.c) 6. C++ (.C, .cpp, .cxx, .cc) 7. C shell (.csh) 8. COBOL (.cob, .cbl) as of version 2.10 9. C# (.cs) as of version 2.11 10. Expect (.exp) 11. Fortran (.f) 12. Haskell (.hs) as of version 2.11 13. Java (.java) 14. lex/flex (.l) 15. LISP/Scheme (.el, .scm, .lsp, .jl) 16. Makefile (makefile) — not normally shown. 17. Modula-3 (.m3, .i3) as of version 2.07 18. Objective-C (.m) 19. Pascal (.p, .pas) 20. Perl (.pl, .pm, .perl) 21. PHP (.php, .php[3456], .inc) as of version 2.05 22. Python (.py) 23. Ruby (.rb) as of version 2.09 24. sed (.sed) 25. SQL (.sql) — not normally shown. 26. TCL (.tcl, .tk, .itk) 27. Yacc/Bison (.y) \u003c/code\u003e Причем, считает не просто количество строк исходного текста, но и умеет игнорировать комментарии, исключает из подсчета дубли файлов (сравнивает их хеш суммы), а также выводит расчетную трудоемкость, примерную оценку стоимости разработки анализируемого проекта и другие характеристики.\nМеня изначально интересовал объем исходников на С/С++ и может быть еще на Ассемблере, если таких файлов окажется достаточно много. Но после начала работы очень обрадовался, что не стал изобретать велосипед, а взял готовую тулзу, т.к. она отдельно считала статистику исходных файлов синтаксического анализатора Yacc/Bison (.y), который и определяет фактическую сложность парсера (читай сложность синтаксиса языка программирования).\nСтарые исходники gcc брал с https://gcc.gnu.org/mirrors.html, но перед запуском анализатора удалил каталоги других компиляторов (ada, fortran, java и т.д.), чтобы они не попадали в итоговую статистику.\nРезультаты в попугаях Итоговая статистика\nОбъем кода синтаксического анализатора Yacc/Bison\nОбъем общей которой базы GCC (только для языков C и C++)\nВыводы К сожалению, синтаксический анализатор Yacc/Bison использовался только до 3 версии, а после его использование свелось на нет. Поэтому оценить сложность синтаксиса С/С++ с помощью объема кода парсера можно лишь примерно до 1996-98 года, после чего его стали постепенно выпиливать, т.е. чуть менее, чем за десять лет. Но даже за этот период объем кодовой базы синтаксического анализатора вырос двукратно, что примерно соответствует по времени реализации стандарта C99.\nНо даже если не учитывать код синтаксического анализатора, то объем общей кодовой базы так же коррелирует с внедрением новых стандартов C++: C99, С11 и C14.\nНа графике не видно выраженного пика для С+17 и следующих версий, но предполагаю, что при текущем объеме кодой базы (более 4 миллионов строк только С и С++ кода), несколько тысяч строк, необходимых для поддержки синтаксических конструкций новых стандартов просто незаметно.\nВывод первый - очевидный. Рост сложности инструментов разработки Фактически на примере проекта GCC можно видеть постоянный и неотвратимый рост сложности рабочих инструментов программистов.\nИ как бы не говорили о деградации разработки в статье “Хорошие времена рождают слабаков”, о системном кризисе программного обеспечения, который носит поколенческом характер, но мне кажется тут дело немного в другом.\nОбновление персонала и как следствие — необходимость обучения новых сотрудников старым наработкам, тут дело не сколько в передаче знаний, сколько в возможности эти знания усваивать.\nПричем возможность усвоения знаний для разных поколений будет разная, но не из-за того, что предыдущее поколение было умнее, а у нового поколения не хватает толку в этом разобрать. Просто изменяется окружение и усложняются рабочие инструменты, по сравнению с теми, которые были в ходу у предыдущего поколения.\nВывод второй — порог входа Представьте, что нужно «сделать свой сайт». Естественно нужно определить, какую CMS для него использовать и какой брать хостинг. И если с хостингом вопрос решается очень просто, конечно же в TimeWeb, да еще и с бонусом по ссылке, то при выборе CMS приходится подумать.\nИ если для простых сайтов существуют и простые решения, то для тех, кто не ищет легких путей существует CMS Drupal, который примечателен тем, что имеет фантастически высокий порог входа для начала использования.\nЭто я к чему? При использовании любого инструмента, как и языка программирования, существует некий минимальный уровень комфортного использования. Причем этот уровень прямо пропорционально связан с размером той целевой аудитории, для которой он предназначен. Точнее, размер возможной аудитории определяется в том числе и требованиями к уровню начальных знаний и квалификации потенциального пользователя.\nИтоговый вывод — не утешительный Если рассматривать увеличение сложности только самого ПО, то это одно дело. Вот к примеру:\nСтатистика ядра Linux с вики\n17 сентября 1991: Linux версии 0.01 (10 239 строк кода). 14 марта 1994: Linux версии 1.0.0 (176 250 строк кода). Март 1995: Linux версии 1.2.0 (310 950 строк кода). 9 июня 1996: Linux версии 2.0.0 (777 956 строк кода). 25 января 1999: Linux версии 2.2.0, изначально довольно недоработанный (1 800 847 строк кода). 4 января 2001: Linux версии 2.4.0 (3 377 902 строки кода). 18 декабря 2003: Linux версии 2.6.0 (5 929 913 строк кода). 23 марта 2009: Linux версии 2.6.29, временный символ Linux — тасманский дьявол Tuz (11 010 647 строк кода). 22 июля 2011: релиз Linux 3.0 (14,6 млн строк кода). 24 октября 2011: релиз Linux 3.1. 15 января 2012: релиз Linux 3.3 преодолел отметку в 15 млн строк кода. 23 февраля 2015: первый релиз-кандидат Linux 4.0 (более 19 млн строк кода). 7 января 2019: первый релиз-кандидат Linux 5.0 (более 26 млн строк кода). А что делать, если сложность программного обеспечения накладывается на тенденцию постоянного усложнения самих рабочих инструментов? Ведь постоянное развитие языков программирования неизбежно повышает порог входа для всех начинающих и только усугубляет проблему сложности разработки ПО.\nДругими словами, не зависимо от того, как хорошо документирован код и как полно он покрыт тестами, через некоторое время устаревают используемые инструменты, завершаются жизненные циклы внешних зависимостей, и самое главное, приходят новые люди взамен тех, кто разработал или сумел разобраться в системе.\nИ у новых людей возникает необходимость разбираться в системе с самого начала, но в других начальных условиях. И из-за этого, сложность изучения системы для всех новых людей будет выше просто по факту того, что изменились внешние условия и усложнились рабочие инструменты, которыми приходится использовать новым сотрудникам.\nПонятно, что чем дальше, тем проще уже не будет. Ведь область IT , это среда с самой высокой конкуренцией. И как уж тут не вспомнить Льюиса Кэррола, что его крылатое выражение\nНужно бежать со всех ног, чтобы только оставаться на месте, а чтобы куда-то попасть, надо бежать как минимум вдвое быстрее!\nВедь это относится не только к Алисе в стране чудес, но и ко всем информационным технологиям в целом!\nПервоначальная публикация\n","categories":"","description":"","excerpt":"\nВ очередной раз увидел на Хабре статью про сложное дело под названием …","ref":"/ru/blog/complex-prog/","tags":"","title":"Простое сложное программирование"},{"body":"\nС постоянной периодичностью появляется информация о выходе новой версии того или иного языка программирования. И с каждой новой версией расширяются его возможности, добавляются новые синтаксические конструкции или иные улучшения.\nИ это очень сильно напоминает развитие технологий, как и в любой другой области техники. Когда с очередным этапом совершенствуются создаваемые творения. Быстрее, выше, сильнее … и одновременно значительно сложнее.\nОб этой проблеме меня заставила задуматься первоапрельская статья «Доказательное программирование».\nПонятно, что дата публикации статьи говорит сама за себя. Тем не менее, новые стандарты С++, постоянно выходящие спецификации Java или новый синтаксис у PHP 8, невольно заставляют задуматься, а в нужную ли сторону идет развитие языков программирования? Ведь большинство нововведений добавляют сложность в основной рабочий инструмент и решая одни проблемы, неявно добавляя множество других.\nА что должно быть в конце прогресса у развития такой дисциплины как программирование? Или хотя бы у одного конкретного языка? Ради достижения какой конечной «идеальной» цели разрабатываются новые стандарты языков программирования?\nЕсли фантазировать об идеальной конечной цели развития, например транспорта, то это будет мгновенное перемещение на любое расстояние с произвольной полезной нагрузкой и нулевым потреблением энергии.\nИли, например, какая может быть идеальная цель у медицины? Бедные не болели, а богатые не выздоравливали, вероятно, лечение любых болезней и биологическое бессмертие.\nКонечно, «идеальная» цель это очень упрощенное понятие. Фактически, «идеальная» это синоним «недостижимая», т.к. она всегда будет упираться необходимость соблюдать компромисс между различными взаимно-исключающими граничными условиями.\nНо сравнивать разработку средств программирования с процессом развития в других технических дисциплинах напрямую нельзя. Ведь при создание конечного продукта в любой технической области, все сложные производственные операции, которые требуют непосредственного участия человека, практически всегда можно разделить на отдельные, более простые части или этапы.\nЭто делается, в том числе и для того, чтобы сложность одной выполняемой операции не была запредельной для исполнителя. Но как это можно сделать при разработке программного обеспечения?\nВ данном случае, я имею ввиду конечную ограниченность возможностей одного конкретного человека в противовес возможностям разделения технологических процессов на отдельные этапы, каждый из которых может выполняться совершенно разными людьми (как пример, это обычный конвеер с его разделением труда на элементарные операции или узкая специализация врачей-специалистов в одной конкретной области).\nВедь даже сложно себе представить фантастическую организацию труда программистов в виде конвеера:\nПервый разработчик пишет только интерфейсы функций и их вызовы, после чего передает код второму сотруднику. Второй пишет в тексте программы только условия проверки и безусловные переходы и передает текст третьему. Третий отвечает за написание циклов и общее форматирование кода и т.д. и результате ожидаемо получится полный бред. Из-за этого индустрия разработки ПО вынуждена идти по экстенсивному пути развития (т.е. за счет увеличения используемых в производстве ресурсов). Современные промышленные языки программирования имеют очень богатые возможности по разделению кода приложения на отдельные функции/модули/компоненты, что позволяет вести разработку сложного программного продукта сразу множеству сотрудников одновременно.\nНо и такое развитие имеет естественное ограничение. И этим ограничением является сам человек, так как каждый разработчик должен знать и уметь пользоваться своим рабочим инструментом, т.е. языком программирования.\nЕсли взять приведенную выше аналогию с конвеером, то в ней каждый рабочий должен был бы досконально знать большую часть используемых станков и инструментов на всем заводе, независимо от того, какую одну конкретную операцию он выполняет на своем рабочем месте.\nВедь парадокс развития языков программирования заключается в том, что добавляя новые возможности и синтаксические конструкции, мы усложняем рабочий инструмент, предназначенный как для совместного, так и для индивидуального использования!\nИ получается, что одновременно с процессом постоянного наращивания возможностей средств разработки идет и обратный процесс — увеличение сложности разработки кода отдельно взятым разработчиком. Фактически, это и есть то самое взаимоисключающее непреодолимое противоречие.\nМожет быть именно поэтому невозможно найти «серебряную пулю», которая бы повышала производительность труда одного программиста? Ведь внимание и возможности человека не безграничны. И любые новшества и улучшения рабочего инструмента программиста вынужденно толкают всю IT индустрию на экстенсивный путь развития.\nВозможно следует разрабатывать принципиально новые подходы, а не гнаться за синтаксическим сахаром в языках программирования из прошлого века? Или и вовсе не париться, продолжать пользоваться тем, что есть, а теория дедушки Дарвина все сама расставит по своим местам?\nПервоначальная публикация\n","categories":"","description":"","excerpt":"\nС постоянной периодичностью появляется информация о выходе новой …","ref":"/blog/lang-final/","tags":"","title":"Какая «идеальная» цель развития у языков программирования?"},{"body":"\nС постоянной периодичностью появляется информация о выходе новой версии того или иного языка программирования. И с каждой новой версией расширяются его возможности, добавляются новые синтаксические конструкции или иные улучшения.\nИ это очень сильно напоминает развитие технологий, как и в любой другой области техники. Когда с очередным этапом совершенствуются создаваемые творения. Быстрее, выше, сильнее … и одновременно значительно сложнее.\nОб этой проблеме меня заставила задуматься первоапрельская статья «Доказательное программирование».\nПонятно, что дата публикации статьи говорит сама за себя. Тем не менее, новые стандарты С++, постоянно выходящие спецификации Java или новый синтаксис у PHP 8, невольно заставляют задуматься, а в нужную ли сторону идет развитие языков программирования? Ведь большинство нововведений добавляют сложность в основной рабочий инструмент и решая одни проблемы, неявно добавляя множество других.\nА что должно быть в конце прогресса у развития такой дисциплины как программирование? Или хотя бы у одного конкретного языка? Ради достижения какой конечной «идеальной» цели разрабатываются новые стандарты языков программирования?\nЕсли фантазировать об идеальной конечной цели развития, например транспорта, то это будет мгновенное перемещение на любое расстояние с произвольной полезной нагрузкой и нулевым потреблением энергии.\nИли, например, какая может быть идеальная цель у медицины? Бедные не болели, а богатые не выздоравливали, вероятно, лечение любых болезней и биологическое бессмертие.\nКонечно, «идеальная» цель это очень упрощенное понятие. Фактически, «идеальная» это синоним «недостижимая», т.к. она всегда будет упираться необходимость соблюдать компромисс между различными взаимно-исключающими граничными условиями.\nНо сравнивать разработку средств программирования с процессом развития в других технических дисциплинах напрямую нельзя. Ведь при создание конечного продукта в любой технической области, все сложные производственные операции, которые требуют непосредственного участия человека, практически всегда можно разделить на отдельные, более простые части или этапы.\nЭто делается, в том числе и для того, чтобы сложность одной выполняемой операции не была запредельной для исполнителя. Но как это можно сделать при разработке программного обеспечения?\nВ данном случае, я имею ввиду конечную ограниченность возможностей одного конкретного человека в противовес возможностям разделения технологических процессов на отдельные этапы, каждый из которых может выполняться совершенно разными людьми (как пример, это обычный конвеер с его разделением труда на элементарные операции или узкая специализация врачей-специалистов в одной конкретной области).\nВедь даже сложно себе представить фантастическую организацию труда программистов в виде конвеера:\nПервый разработчик пишет только интерфейсы функций и их вызовы, после чего передает код второму сотруднику. Второй пишет в тексте программы только условия проверки и безусловные переходы и передает текст третьему. Третий отвечает за написание циклов и общее форматирование кода и т.д. и результате ожидаемо получится полный бред. Из-за этого индустрия разработки ПО вынуждена идти по экстенсивному пути развития (т.е. за счет увеличения используемых в производстве ресурсов). Современные промышленные языки программирования имеют очень богатые возможности по разделению кода приложения на отдельные функции/модули/компоненты, что позволяет вести разработку сложного программного продукта сразу множеству сотрудников одновременно.\nНо и такое развитие имеет естественное ограничение. И этим ограничением является сам человек, так как каждый разработчик должен знать и уметь пользоваться своим рабочим инструментом, т.е. языком программирования.\nЕсли взять приведенную выше аналогию с конвеером, то в ней каждый рабочий должен был бы досконально знать большую часть используемых станков и инструментов на всем заводе, независимо от того, какую одну конкретную операцию он выполняет на своем рабочем месте.\nВедь парадокс развития языков программирования заключается в том, что добавляя новые возможности и синтаксические конструкции, мы усложняем рабочий инструмент, предназначенный как для совместного, так и для индивидуального использования!\nИ получается, что одновременно с процессом постоянного наращивания возможностей средств разработки идет и обратный процесс — увеличение сложности разработки кода отдельно взятым разработчиком. Фактически, это и есть то самое взаимоисключающее непреодолимое противоречие.\nМожет быть именно поэтому невозможно найти «серебряную пулю», которая бы повышала производительность труда одного программиста? Ведь внимание и возможности человека не безграничны. И любые новшества и улучшения рабочего инструмента программиста вынужденно толкают всю IT индустрию на экстенсивный путь развития.\nВозможно следует разрабатывать принципиально новые подходы, а не гнаться за синтаксическим сахаром в языках программирования из прошлого века? Или и вовсе не париться, продолжать пользоваться тем, что есть, а теория дедушки Дарвина все сама расставит по своим местам?\nПервоначальная публикация\n","categories":"","description":"","excerpt":"\nС постоянной периодичностью появляется информация о выходе новой …","ref":"/ru/blog/lang-final/","tags":"","title":"Какая «идеальная» цель развития у языков программирования?"},{"body":"\nНекоторое время назад я писал про «Интернациональное программирование на естественных языках», в которой попытался представить достойную цель для абстрактного языка программирования, попробовав примерить на него роль связующего звена между миром программистов с компьютерами и не программистов.\nНо в результате оказалось, что это не нужно в принципе, т.к. «не программистам» просто не требуется учиться писать программы. А если иногда такое желание и возникает, то вполне хватает обычных формализованных языков программирования, которых уже сейчас насчитывается наверно более десяти тысяч.\nА пользователи, как программисты, так и не программисты, просто хотят решать возникающие перед ними задачи. И хотя задачи бывают совершенно разные, но если способ (алгоритм) её решения известен, то выбрать язык для её решения не составит никакого труда.\nЗа исключением одного класса задач. Задач, решение которых нельзя описать в виде алгоритма. Но можно указать некие критерии, которым должно удовлетворять искомое решение.\nЯ имею ввиду логические языки программирования и Пролог, как самый яркий представитель этого класса.\nЕще помню воспоминание из юности, когда удалось достать дискету с этим языком. Ух, с каким задором горели мои глаза, когда мне казалось, ну вот, еще чуть-чуть и будет создана система с базой знаний, у которой и можно будет получить заветный ответ 42 на любой вопрос.\nТак почему этого так и не случилось? В чем проблема Пролога, да и любой системы / языка программирования, назначение которых анализировать факты и искать ответы на вопросы?\nЭта проблема называется «Комбинаторный взрыв» - экспоненциальная (или более) зависимость времени работы алгоритма от количества входных данных. И есть как минимум два решения этой проблемы.\nПодходы к написанию программ Прежде чем переходить к частностям, следует сказать пару слов про парадигмы программирования. Обычно противопоставляют между собой два разных стиля в написании программ: императивный и декларативный.\nИмперативный — это классический вариант написания программы, при котором программист сам задает шаги алгоритма для получения конечного результата. А сам текст программы состоит из последовательности команд, которые читают, сохраняют и обрабатывают данные или вызывают другие команды.\nДекларативный — в этом стиле программист описывает условия задачи и правила для получения требуемого результата, но не требуется детально описывать все шаги работы алгоритма, оставляя их на усмотрения компьютера.\nИменно к декларативному стилю относится язык Пролог, да и все остальные логические языки программирования. К декларативному стилю написания программ следует относить и язык структурированных запросов (SQL).\nИ проблема под называнием «комбинаторный взрыв» сильнее всего оказывает негативное влияние как раз на подобные языки. Ведь в императивном подходе программист сам отвечает за последовательность выполняемых команд, и если он запрограммировал алгоритм полного перебора всех возможных вариантов решений, то он сам себе злобный Буратино.\nДругое дело, программирование в декларативном стиле. Разработчик хоть и может указать ограничения, которые следует применять при поиске решения, но это возможно только в том случае, когда известен алгоритм решения задачи. Но если алгоритм решения известен, то проще использовать императивный стиль, как раз и реализуя этот алгоритм!\nПоэтому основное применения языков программирования в декларативном стиле — отказаться от необходимости описания четкого алгоритма поиска решения, отдав это компьютеру на откуп. Для которого самое простое решение «в лоб» - полный перебор возможных вариантов.\nИменно в этом случае и начинается экспоненциальный рост времени выполнения алгоритма. И начиная с определенного порога, время ожидания ответа становится неприемлемым для реального использования. Это и означает «Комбинаторный взрыв», резкий («взрывной») рост времени выполнения алгоритма при увеличении размера входных данных.\nПроблема поиска решений В языке Пролог эта проблема решалась за счет использования механизма отката и отсечений. Иногда еще уточняли про «красное» и «зеленое» отсечение решений. Но в любом случае, это были алгоритмические механизмы для ограничения количества размера дерева возможных решений, а необходимость их применения все равно остается на программисте.\nНо чтобы их правильно реализовывать, нужно знать алгоритм решения, что опять возвращает нас к утверждению о том, что если известен алгоритм, то и программировать его удобнее в императивном стиле.\nА если полный алгоритм решения задачи не известен (или не подходит, например из-за большого времени для его работы), то в результате остается либо увеличивать производительность системы, чтобы сократить время выполнения алгоритма, либо искать другое решение, в том числе, сокращая вычислительную сложность поиска решений, например, исключая заведомо не подходящие данные, чтобы уменьшить возможные комбинации их перебора.\nМасштабирование производительности Увеличение производительности тоже бывает разным и работает не во всех случаях. Вертикальное масштабирование производительности одного узла вычислительной среды имеет свой естественный предел. И даже многократное увеличение скорости работы компьютера может лишь отдалить порог терпения пользователя при ожидании получения результата, но не в состоянии принципиально решить саму проблему.\nДругое дело горизонтальное масштабирование, при котором выполнение алгоритма запускается на отдельных узлах, которые параллельно решают одну и ту же задачу. Такой способ масштабирования позволяет уже значительно сократить время получения итогового результата для сложных вычислительных задач. И хотя это способ является решением «в лоб», но успехи в области data science доказывают успешность такого подхода.\nКонечно, у горизонтального масштабирования тоже есть подводные камни. В первую очередь, сам алгоритм должен допускать возможность параллельного выполнения независимо от других узлов. Также требуется автоматизация управления заданиями, самими вычислительными узлами, да и всей системой в целом.\nТут частично может помочь парадигма функционального программирования, которая ограничивает результат вычисления функций только входными параметрами и результатом выполнения других функций, но сам результат не зависит от состояния системы или иных внешних данных.\nПоиск обобщенного решения Вторым способом решения решения проблемы комбинаторного взрыва является уменьшение вычислительной сложности решения. Тут имеется ввиду не выбор другого алгоритма или решение задачи в символьном виде. Если такое возможно, то все опять сразу сведется к императивному стилю программированию.\nЯ имею ввиду возможность поиска самого алгоритма решения. Точнее не совсем алгоритма, а возможность применения к входным данным различные методы отбора, чтобы исключить необходимость их полного перебора. По сути, это сводится к применению различных методов и механизмов обработки входных данных с учетом различных закономерностей.\nЭто возможно как алгоритмическими методами (откат и отсечение в Прологе), так и с применением машинного обучения, которое очень хорошо справляется с поиском различных закономерностей.\nЕстественно, такой способ подходит не для всех классов задач. Он не подходит для выявления ВСЕХ возможных решений. Но там где это не требуется, подобные способы уменьшения вычислительной сложности имеют право на существование.\nНапример, не требуется искать все возможные лекарства от конкретной болезни, достаточно одного, с учетом определенных ограничений, которое гарантированно подействует.\nК тому же, даже при нахождении частных решений, всегда существует шанс, что с их помощью получится увидеть не очевидные на первый взгляд закономерности, которые помогут показать новые пути алгоритмического уменьшения вычислительной сложности основной задачи.\nОбласть не решаемых задач Как вы считает, а реально ли создать язык логического программирования, который бы сам умел автоматизировать поиск решений для задач подобных классов? Или хотя бы имел в своем арсенале встроенные механизмы для автоматизации подобной деятельности?\nРезультаты опроса из оригинальной публикации - 57.47% Ха-ха! То, что хочет автор и называется искусственным интеллектом (50 голосов) - 27.59% Поиск решений нельзя автоматизировать (24 голоса) - 19.54% Это уже есть и все давно придумано (17 голосов) - 9.2% Такой язык не нужен, т.к. нейросети могут всё (8 голосов) - 3.45% Свой вариант написал в комменатрии (3 голоса) Проголосовали 87 пользователей. Воздержались 62 пользователя.\n","categories":"","description":"","excerpt":"\nНекоторое время назад я писал про «Интернациональное программирование …","ref":"/blog/logic-prog/","tags":"","title":"Проблема логических языков программирования"},{"body":"\nНекоторое время назад я писал про «Интернациональное программирование на естественных языках», в которой попытался представить достойную цель для абстрактного языка программирования, попробовав примерить на него роль связующего звена между миром программистов с компьютерами и не программистов.\nНо в результате оказалось, что это не нужно в принципе, т.к. «не программистам» просто не требуется учиться писать программы. А если иногда такое желание и возникает, то вполне хватает обычных формализованных языков программирования, которых уже сейчас насчитывается наверно более десяти тысяч.\nА пользователи, как программисты, так и не программисты, просто хотят решать возникающие перед ними задачи. И хотя задачи бывают совершенно разные, но если способ (алгоритм) её решения известен, то выбрать язык для её решения не составит никакого труда.\nЗа исключением одного класса задач. Задач, решение которых нельзя описать в виде алгоритма. Но можно указать некие критерии, которым должно удовлетворять искомое решение.\nЯ имею ввиду логические языки программирования и Пролог, как самый яркий представитель этого класса.\nЕще помню воспоминание из юности, когда удалось достать дискету с этим языком. Ух, с каким задором горели мои глаза, когда мне казалось, ну вот, еще чуть-чуть и будет создана система с базой знаний, у которой и можно будет получить заветный ответ 42 на любой вопрос.\nТак почему этого так и не случилось? В чем проблема Пролога, да и любой системы / языка программирования, назначение которых анализировать факты и искать ответы на вопросы?\nЭта проблема называется «Комбинаторный взрыв» - экспоненциальная (или более) зависимость времени работы алгоритма от количества входных данных. И есть как минимум два решения этой проблемы.\nПодходы к написанию программ Прежде чем переходить к частностям, следует сказать пару слов про парадигмы программирования. Обычно противопоставляют между собой два разных стиля в написании программ: императивный и декларативный.\nИмперативный — это классический вариант написания программы, при котором программист сам задает шаги алгоритма для получения конечного результата. А сам текст программы состоит из последовательности команд, которые читают, сохраняют и обрабатывают данные или вызывают другие команды.\nДекларативный — в этом стиле программист описывает условия задачи и правила для получения требуемого результата, но не требуется детально описывать все шаги работы алгоритма, оставляя их на усмотрения компьютера.\nИменно к декларативному стилю относится язык Пролог, да и все остальные логические языки программирования. К декларативному стилю написания программ следует относить и язык структурированных запросов (SQL).\nИ проблема под называнием «комбинаторный взрыв» сильнее всего оказывает негативное влияние как раз на подобные языки. Ведь в императивном подходе программист сам отвечает за последовательность выполняемых команд, и если он запрограммировал алгоритм полного перебора всех возможных вариантов решений, то он сам себе злобный Буратино.\nДругое дело, программирование в декларативном стиле. Разработчик хоть и может указать ограничения, которые следует применять при поиске решения, но это возможно только в том случае, когда известен алгоритм решения задачи. Но если алгоритм решения известен, то проще использовать императивный стиль, как раз и реализуя этот алгоритм!\nПоэтому основное применения языков программирования в декларативном стиле — отказаться от необходимости описания четкого алгоритма поиска решения, отдав это компьютеру на откуп. Для которого самое простое решение «в лоб» - полный перебор возможных вариантов.\nИменно в этом случае и начинается экспоненциальный рост времени выполнения алгоритма. И начиная с определенного порога, время ожидания ответа становится неприемлемым для реального использования. Это и означает «Комбинаторный взрыв», резкий («взрывной») рост времени выполнения алгоритма при увеличении размера входных данных.\nПроблема поиска решений В языке Пролог эта проблема решалась за счет использования механизма отката и отсечений. Иногда еще уточняли про «красное» и «зеленое» отсечение решений. Но в любом случае, это были алгоритмические механизмы для ограничения количества размера дерева возможных решений, а необходимость их применения все равно остается на программисте.\nНо чтобы их правильно реализовывать, нужно знать алгоритм решения, что опять возвращает нас к утверждению о том, что если известен алгоритм, то и программировать его удобнее в императивном стиле.\nА если полный алгоритм решения задачи не известен (или не подходит, например из-за большого времени для его работы), то в результате остается либо увеличивать производительность системы, чтобы сократить время выполнения алгоритма, либо искать другое решение, в том числе, сокращая вычислительную сложность поиска решений, например, исключая заведомо не подходящие данные, чтобы уменьшить возможные комбинации их перебора.\nМасштабирование производительности Увеличение производительности тоже бывает разным и работает не во всех случаях. Вертикальное масштабирование производительности одного узла вычислительной среды имеет свой естественный предел. И даже многократное увеличение скорости работы компьютера может лишь отдалить порог терпения пользователя при ожидании получения результата, но не в состоянии принципиально решить саму проблему.\nДругое дело горизонтальное масштабирование, при котором выполнение алгоритма запускается на отдельных узлах, которые параллельно решают одну и ту же задачу. Такой способ масштабирования позволяет уже значительно сократить время получения итогового результата для сложных вычислительных задач. И хотя это способ является решением «в лоб», но успехи в области data science доказывают успешность такого подхода.\nКонечно, у горизонтального масштабирования тоже есть подводные камни. В первую очередь, сам алгоритм должен допускать возможность параллельного выполнения независимо от других узлов. Также требуется автоматизация управления заданиями, самими вычислительными узлами, да и всей системой в целом.\nТут частично может помочь парадигма функционального программирования, которая ограничивает результат вычисления функций только входными параметрами и результатом выполнения других функций, но сам результат не зависит от состояния системы или иных внешних данных.\nПоиск обобщенного решения Вторым способом решения решения проблемы комбинаторного взрыва является уменьшение вычислительной сложности решения. Тут имеется ввиду не выбор другого алгоритма или решение задачи в символьном виде. Если такое возможно, то все опять сразу сведется к императивному стилю программированию.\nЯ имею ввиду возможность поиска самого алгоритма решения. Точнее не совсем алгоритма, а возможность применения к входным данным различные методы отбора, чтобы исключить необходимость их полного перебора. По сути, это сводится к применению различных методов и механизмов обработки входных данных с учетом различных закономерностей.\nЭто возможно как алгоритмическими методами (откат и отсечение в Прологе), так и с применением машинного обучения, которое очень хорошо справляется с поиском различных закономерностей.\nЕстественно, такой способ подходит не для всех классов задач. Он не подходит для выявления ВСЕХ возможных решений. Но там где это не требуется, подобные способы уменьшения вычислительной сложности имеют право на существование.\nНапример, не требуется искать все возможные лекарства от конкретной болезни, достаточно одного, с учетом определенных ограничений, которое гарантированно подействует.\nК тому же, даже при нахождении частных решений, всегда существует шанс, что с их помощью получится увидеть не очевидные на первый взгляд закономерности, которые помогут показать новые пути алгоритмического уменьшения вычислительной сложности основной задачи.\nОбласть не решаемых задач Как вы считает, а реально ли создать язык логического программирования, который бы сам умел автоматизировать поиск решений для задач подобных классов? Или хотя бы имел в своем арсенале встроенные механизмы для автоматизации подобной деятельности?\nРезультаты опроса из оригинальной публикации - 57.47% Ха-ха! То, что хочет автор и называется искусственным интеллектом (50 голосов) - 27.59% Поиск решений нельзя автоматизировать (24 голоса) - 19.54% Это уже есть и все давно придумано (17 голосов) - 9.2% Такой язык не нужен, т.к. нейросети могут всё (8 голосов) - 3.45% Свой вариант написал в комменатрии (3 голоса) Проголосовали 87 пользователей. Воздержались 62 пользователя.\n","categories":"","description":"","excerpt":"\nНекоторое время назад я писал про «Интернациональное программирование …","ref":"/ru/blog/logic-prog/","tags":"","title":"Проблема логических языков программирования"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nВ последнее время часто попадаются на глаза статьи о новых языках программирования, а так же различные рейтинги и прогнозы, связанные с популярностью компьютерных языков.\nЗаявляют о себе и новые инструментальные средства, которые в своей работе используют собственные форматы описания конфигурационных файлов или последовательности выполняемых команд, которые так же очень сильно приближает их к понятию «язык программирования».\nЦель написания данной статьи — формулировка ожиданий и возможной реализации абстрактного языка программирования, который может стать универсальным инструментом для общения между компьютером и человеком.\nО программистах Если начинать с самого начала, то когда-то давно я слышал перефразированное высказывание, «каждый программист должен написать свою базу данных, текстовый редактор и язык программирования». И если первые две вещи я уже давным давно написал, то с языком программирования пока не сложилось.\nВедь как обычно создаются языки программирования?\nУ каждого программиста всегда есть какой-то своей предыдущий опыт:\nзнания одного или нескольких языков программирования (как же без этого) негативный опыт от их использования (в противном случае, если все устраивает, то зачем придумывать что-то новое?) желания получить новые возможности (когда в существующих языках чего-то не хватает) А перед тем, как описывать синтаксис, выбирать ключевые слова и начинать основную работу: лексер, парсер, базовые библиотеки, нужно дать ответ на основные вопросы:\nКомпилятор/интерпретатор/транспилятор(transpiler)? Статическая или динамическая типизация? Ручное управление памятью или автоматическое со сборщиком мусора? Модель программирования: ООП, функциональное, структурное или что-то новое? Разрешены ли вставки из других языков программирования и т. д.? У меня, наверно, как и у большинства читателей, присутствует опыт использования нескольких языков программирования. Поэтому давно сложилось практика, что для решения задачи лучше взять известный язык или даже выучить новый, вместо того, чтобы начинать писать собственный.\nТем более, что не хочется придумывать еще один язык просто ради галочки или ради самого языка. Я считаю, что цель его создания должна быть за пределами потребностей самого разработчика.\nИ мне кажется, что удалось определить область, для которой разработка языка программирования может быть востребованной, а потраченные на него усилия могут принести реальную пользу.\nО не программистах Эта область — программирование для «не программистов» на «естественном» языке. Я специально взял слова «не программистов» и «естественном» в кавычки, т.к. эти термины являются очень условными.\nВедь если не программист начинает программировать, то сам того не осознавая, он автоматически становится программистом ;-). А «естественным» язык программирования быть не может по определению. Точнее для компьютеров скорее всего «естественным» будет язык Assembler или набор машинных команд.\nПоэтому, цель максимум — приблизить язык программирования к естественному человеческому языку.\nЭто не только сделает чтение текста программы более понятным для не профессионалов, но и позволит начинать составлять программы просто освоив письменную речь, используя самый минимум основных правил.\nНо в подобной формулировке кроется очень большая проблема!\nЛюбой язык программирования является интернациональным, т.к. его синтаксис не зависит от естественного языка, на котором общается программист.\nА если текст программы будет на “естественном” языке, то она станет понятной только для знающих этот язык, одновременно становясь непонятной для всех остальных.\nВ качестве иллюстрации: раз или два. Если пофантазировать насчет хотелок к такому языку, то видятся следующие требования и ограничения:\nТак как каждый пользователь является носителем своего родного естественного языка (или даже нескольких), то жестко задавать ключевые слова невозможно, из чего следует, что основой такого языка должны стать только правила пунктуации, но никак не лексика или грамматика. Компилятор/транслятор должен уметь преобразовывать исходный текст программы не только в машинный код для компьютера, но в другой вариант “естественного” языка, чтобы пользователь мог работать с исходным текстом на известном ему “естественном” языке. Очень хочется видеть в новом языке толерантность терпимость к очепяткам. Подобная «фича» присутствует в письме на естественном языке, и несмотря на наличие опечаток, практически всегда сохраняется смысл. Естественно, в данном случае не стоит доходить до фанатизма. Компилятор не читает мысли и не может в действительности «понять», что имел ввиду пользователь, и все же довольно часто можно игнорировать опечатки в тексте программы исходя из контекста (пусть и с выводом предупреждающих сообщений). Тем не менее, такой язык должен оставаться именно языком программирования со всеми возможностями создания программ любого уровня сложности, включая функциональное и объектно-ориентированное программирование и однозначное понимание написанного.\nО гипотетическом языке Если взять за основу правила письменной речи, то основные соглашения и пунктуация для нового языка могут выглядеть примерно так:\nЛюбой текст состоит из предложений и комментариев. Предложения обрабатываются, а комментарии игнорируются. Предложение состоит из последовательности терминов, литералов и символов, разделенных пробелами и знаками препинания и завершается символом конца предложения. Термин — слитно написанная последовательность букв, цифр и символов “:” и “_”. Литерал — константы, включаемые непосредственно в текст программы, тип которой определяется однозначно. Это символьные строки в кавычках, целые и вещественные числа, и некоторые специальные форматы (время, дата). Символы — все остальное символы, которые не относятся к знакам препинания, пробельным символам, цифрам и буквам. Знаки препинания — символы пунктуации, имеющие специальное значение при разборе текста программы: «.»,«;»,«!»,«?»,«…» — конец предложения. «=» — присвоение значения. \"\" (кавычки) — определение символьной строки. «()» - передача параметров/аргументов или группировка операторов для определения приоритета выполнения операций. «[]» - массив или обращение к элементу массива. «{}» - включение в текст исходного кода программы на обычном языке программирования. «$» — системная переменная. «@» — системная функция. «,» (запятая) — перечисление. «:» (двоеточие) — список или логическая связь. Если с символом присвоения, кавычками, круглыми и квадратными скобками все должно быть более-менее понятно, т.к. их назначение соответствует аналогичному в подавляющем большинстве языков программирования, то про назначение остальных символов (фигурных скобок, двоеточия, запятой и системных функций/переменной), следует немного пояснить.\nРаз цель гипотетического языка программирования все же написание программ, то необходимо предусмотреть возможность делать вставки обычного программного кода без учета всех возможностей и неоднозначностей, которые присущи любому естественному языку.\nТак же эта возможность требуется для реализации низкоуровневых функций и для взаимодействия с внешними библиотеками.\nПри создании подобных вставок и могут использоваться фигурные скобки, весь текст между которыми будет вставляться в итоговый файл практически без обработки.\nДля похожих целей служат и символы «$» — системная переменная и «@» — системная функция. Если такой символ поставить в начале слова, тогда он станет обозначать объект с соответствующим назначением. Например «@exit» — будет означать функцию, а «$var» — переменную с соответствующими именами, а сами объекты станут доступны как в обычном коде, так и в программных вставках внутри фигурных скобок.\nАналогичным образом организуется и доступ к отдельным полям/методам объектов: «объект@метод» или «объект$поле».\nСимвол запятая «,» применяется для указание последовательности равноправных логических блоков в одном предложении или для создания списков.\nСимвол двоеточия «:» используется для создания списков и для обозначения логической связи между двумя частями слова/текста, в том числе для указания полного пути модуля.\nНапример, создание списка:\nВ_строку: элемент 1, элемент 2, последний элемент.\nФорматированный_список: - элемент 1; - элемент 2; - последний элемент. Логическое следствие/указание связи:\nmodule:calc //термин «calc», который находится в модуле «module» super:module:example$var //переменная «$var» которая находится в указанной иерархии. Как можно заметить, использование знаков препинания взято из их прямого назначения, принятого в письменной речи, что должно обеспечить определенный компромисс между синтаксисом в стандартных языках программирования и письмом на естественном языке.\nО компьютерах Так как речь идет все же о языке программирования, то не обойтись без стандартных алгоритмических конструкций: следования, ветвления и циклов.\nСледование легко описывается обычными правилам письма на естественном языке. В случае последовательного выполнения в одном предложении, операции и вызовы функций записываются последовательно через запятую. Если они располагаются в разных предложениях, то они записываются так же друг за другом. Причем форматирование по абзацам служит только для лучшего восприятия текста и логического разделения отдельных фрагментов.\nПри создании условных и циклических управляющих конструкций уже потребуются ключевые слова. Но так как согласно исходным пожеланиям к языку, резервировать обычные термины для записи алгоритмических конструкций нельзя, то перед ключевыми словами достаточно указывать символ системной функции, что позволит отличить обычный термин от ключевого (управляющего) слова.\nЕстественно, при программировании, данными терминами хоть и можно будет пользоваться, но делать это совсем не обязательно. Так как при настройке под конкретный естественный язык, системным функциям и ключевым словам нужно обязательно присвоить конкретные термины и пользоваться уже ими, например:\nперейти = @goto, метка = @label, продолжить = @continue, прервать=@break и т.д. И последняя по очереди, но наверно самая важная по сути конструкция: передача параметров при вызовах функций. Если стремиться к полностью естественному синтаксису, тогда мы получим тот самый естественный язык, который очень сложно анализировать.\nТем не менее, мне кажется, что можно скомбинировать оба два подхода, если отказаться от обязательного использования круглых скобок, там, где это допустимо по синтаксису.\nКомпьютерный: функция(параметр1, функция2(), параметр3=значение). Естественный: функция параметр1 функция2 параметр3=значение. Но:\nКомпьютерный: функция( функция2(параметр) ). Естественный: функция функция2(параметр). Или так: функция (функция2 параметр). Другими словами, для естественного порядка указания аргументов, скобки для функций и запятые между параметрами могут быть опущены. Хотя их использование должно определяться в первую очередь целевым естественным языком, а не синтаксисом.\nО возражениях Предвижу обоснованные возражения против использования подобного языка со стороны программистов. Программа на нем по любому получится значительно многословнее, чем с использованием строгого формального синтаксиса обычных компьютерных языков.\nПоэтому напомню про его обязательное свойство - умение преобразовывать текст программы с одного языка на другой. Это позволяет писать программы как с использованием строго формального синтаксиса без использования переопеределенных терминов на естественном языке, так и преобразовывать исходный текст в “естественный” язык для “не программиста”.\nСсылка на первую публикаци\n","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/blog/inter-prog/","tags":"","title":"Интернациональное программирование на естественных языках"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nВ последнее время часто попадаются на глаза статьи о новых языках программирования, а так же различные рейтинги и прогнозы, связанные с популярностью компьютерных языков.\nЗаявляют о себе и новые инструментальные средства, которые в своей работе используют собственные форматы описания конфигурационных файлов или последовательности выполняемых команд, которые так же очень сильно приближает их к понятию «язык программирования».\nЦель написания данной статьи — формулировка ожиданий и возможной реализации абстрактного языка программирования, который может стать универсальным инструментом для общения между компьютером и человеком.\nО программистах Если начинать с самого начала, то когда-то давно я слышал перефразированное высказывание, «каждый программист должен написать свою базу данных, текстовый редактор и язык программирования». И если первые две вещи я уже давным давно написал, то с языком программирования пока не сложилось.\nВедь как обычно создаются языки программирования?\nУ каждого программиста всегда есть какой-то своей предыдущий опыт:\nзнания одного или нескольких языков программирования (как же без этого) негативный опыт от их использования (в противном случае, если все устраивает, то зачем придумывать что-то новое?) желания получить новые возможности (когда в существующих языках чего-то не хватает) А перед тем, как описывать синтаксис, выбирать ключевые слова и начинать основную работу: лексер, парсер, базовые библиотеки, нужно дать ответ на основные вопросы:\nКомпилятор/интерпретатор/транспилятор(transpiler)? Статическая или динамическая типизация? Ручное управление памятью или автоматическое со сборщиком мусора? Модель программирования: ООП, функциональное, структурное или что-то новое? Разрешены ли вставки из других языков программирования и т. д.? У меня, наверно, как и у большинства читателей, присутствует опыт использования нескольких языков программирования. Поэтому давно сложилось практика, что для решения задачи лучше взять известный язык или даже выучить новый, вместо того, чтобы начинать писать собственный.\nТем более, что не хочется придумывать еще один язык просто ради галочки или ради самого языка. Я считаю, что цель его создания должна быть за пределами потребностей самого разработчика.\nИ мне кажется, что удалось определить область, для которой разработка языка программирования может быть востребованной, а потраченные на него усилия могут принести реальную пользу.\nО не программистах Эта область — программирование для «не программистов» на «естественном» языке. Я специально взял слова «не программистов» и «естественном» в кавычки, т.к. эти термины являются очень условными.\nВедь если не программист начинает программировать, то сам того не осознавая, он автоматически становится программистом ;-). А «естественным» язык программирования быть не может по определению. Точнее для компьютеров скорее всего «естественным» будет язык Assembler или набор машинных команд.\nПоэтому, цель максимум — приблизить язык программирования к естественному человеческому языку.\nЭто не только сделает чтение текста программы более понятным для не профессионалов, но и позволит начинать составлять программы просто освоив письменную речь, используя самый минимум основных правил.\nНо в подобной формулировке кроется очень большая проблема!\nЛюбой язык программирования является интернациональным, т.к. его синтаксис не зависит от естественного языка, на котором общается программист.\nА если текст программы будет на “естественном” языке, то она станет понятной только для знающих этот язык, одновременно становясь непонятной для всех остальных.\nВ качестве иллюстрации: раз или два. Если пофантазировать насчет хотелок к такому языку, то видятся следующие требования и ограничения:\nТак как каждый пользователь является носителем своего родного естественного языка (или даже нескольких), то жестко задавать ключевые слова невозможно, из чего следует, что основой такого языка должны стать только правила пунктуации, но никак не лексика или грамматика. Компилятор/транслятор должен уметь преобразовывать исходный текст программы не только в машинный код для компьютера, но в другой вариант “естественного” языка, чтобы пользователь мог работать с исходным текстом на известном ему “естественном” языке. Очень хочется видеть в новом языке толерантность терпимость к очепяткам. Подобная «фича» присутствует в письме на естественном языке, и несмотря на наличие опечаток, практически всегда сохраняется смысл. Естественно, в данном случае не стоит доходить до фанатизма. Компилятор не читает мысли и не может в действительности «понять», что имел ввиду пользователь, и все же довольно часто можно игнорировать опечатки в тексте программы исходя из контекста (пусть и с выводом предупреждающих сообщений). Тем не менее, такой язык должен оставаться именно языком программирования со всеми возможностями создания программ любого уровня сложности, включая функциональное и объектно-ориентированное программирование и однозначное понимание написанного.\nО гипотетическом языке Если взять за основу правила письменной речи, то основные соглашения и пунктуация для нового языка могут выглядеть примерно так:\nЛюбой текст состоит из предложений и комментариев. Предложения обрабатываются, а комментарии игнорируются. Предложение состоит из последовательности терминов, литералов и символов, разделенных пробелами и знаками препинания и завершается символом конца предложения. Термин — слитно написанная последовательность букв, цифр и символов “:” и “_”. Литерал — константы, включаемые непосредственно в текст программы, тип которой определяется однозначно. Это символьные строки в кавычках, целые и вещественные числа, и некоторые специальные форматы (время, дата). Символы — все остальное символы, которые не относятся к знакам препинания, пробельным символам, цифрам и буквам. Знаки препинания — символы пунктуации, имеющие специальное значение при разборе текста программы: «.»,«;»,«!»,«?»,«…» — конец предложения. «=» — присвоение значения. \"\" (кавычки) — определение символьной строки. «()» - передача параметров/аргументов или группировка операторов для определения приоритета выполнения операций. «[]» - массив или обращение к элементу массива. «{}» - включение в текст исходного кода программы на обычном языке программирования. «$» — системная переменная. «@» — системная функция. «,» (запятая) — перечисление. «:» (двоеточие) — список или логическая связь. Если с символом присвоения, кавычками, круглыми и квадратными скобками все должно быть более-менее понятно, т.к. их назначение соответствует аналогичному в подавляющем большинстве языков программирования, то про назначение остальных символов (фигурных скобок, двоеточия, запятой и системных функций/переменной), следует немного пояснить.\nРаз цель гипотетического языка программирования все же написание программ, то необходимо предусмотреть возможность делать вставки обычного программного кода без учета всех возможностей и неоднозначностей, которые присущи любому естественному языку.\nТак же эта возможность требуется для реализации низкоуровневых функций и для взаимодействия с внешними библиотеками.\nПри создании подобных вставок и могут использоваться фигурные скобки, весь текст между которыми будет вставляться в итоговый файл практически без обработки.\nДля похожих целей служат и символы «$» — системная переменная и «@» — системная функция. Если такой символ поставить в начале слова, тогда он станет обозначать объект с соответствующим назначением. Например «@exit» — будет означать функцию, а «$var» — переменную с соответствующими именами, а сами объекты станут доступны как в обычном коде, так и в программных вставках внутри фигурных скобок.\nАналогичным образом организуется и доступ к отдельным полям/методам объектов: «объект@метод» или «объект$поле».\nСимвол запятая «,» применяется для указание последовательности равноправных логических блоков в одном предложении или для создания списков.\nСимвол двоеточия «:» используется для создания списков и для обозначения логической связи между двумя частями слова/текста, в том числе для указания полного пути модуля.\nНапример, создание списка:\nВ_строку: элемент 1, элемент 2, последний элемент.\nФорматированный_список: - элемент 1; - элемент 2; - последний элемент. Логическое следствие/указание связи:\nmodule:calc //термин «calc», который находится в модуле «module» super:module:example$var //переменная «$var» которая находится в указанной иерархии. Как можно заметить, использование знаков препинания взято из их прямого назначения, принятого в письменной речи, что должно обеспечить определенный компромисс между синтаксисом в стандартных языках программирования и письмом на естественном языке.\nО компьютерах Так как речь идет все же о языке программирования, то не обойтись без стандартных алгоритмических конструкций: следования, ветвления и циклов.\nСледование легко описывается обычными правилам письма на естественном языке. В случае последовательного выполнения в одном предложении, операции и вызовы функций записываются последовательно через запятую. Если они располагаются в разных предложениях, то они записываются так же друг за другом. Причем форматирование по абзацам служит только для лучшего восприятия текста и логического разделения отдельных фрагментов.\nПри создании условных и циклических управляющих конструкций уже потребуются ключевые слова. Но так как согласно исходным пожеланиям к языку, резервировать обычные термины для записи алгоритмических конструкций нельзя, то перед ключевыми словами достаточно указывать символ системной функции, что позволит отличить обычный термин от ключевого (управляющего) слова.\nЕстественно, при программировании, данными терминами хоть и можно будет пользоваться, но делать это совсем не обязательно. Так как при настройке под конкретный естественный язык, системным функциям и ключевым словам нужно обязательно присвоить конкретные термины и пользоваться уже ими, например:\nперейти = @goto, метка = @label, продолжить = @continue, прервать=@break и т.д. И последняя по очереди, но наверно самая важная по сути конструкция: передача параметров при вызовах функций. Если стремиться к полностью естественному синтаксису, тогда мы получим тот самый естественный язык, который очень сложно анализировать.\nТем не менее, мне кажется, что можно скомбинировать оба два подхода, если отказаться от обязательного использования круглых скобок, там, где это допустимо по синтаксису.\nКомпьютерный: функция(параметр1, функция2(), параметр3=значение). Естественный: функция параметр1 функция2 параметр3=значение. Но:\nКомпьютерный: функция( функция2(параметр) ). Естественный: функция функция2(параметр). Или так: функция (функция2 параметр). Другими словами, для естественного порядка указания аргументов, скобки для функций и запятые между параметрами могут быть опущены. Хотя их использование должно определяться в первую очередь целевым естественным языком, а не синтаксисом.\nО возражениях Предвижу обоснованные возражения против использования подобного языка со стороны программистов. Программа на нем по любому получится значительно многословнее, чем с использованием строгого формального синтаксиса обычных компьютерных языков.\nПоэтому напомню про его обязательное свойство - умение преобразовывать текст программы с одного языка на другой. Это позволяет писать программы как с использованием строго формального синтаксиса без использования переопеределенных терминов на естественном языке, так и преобразовывать исходный текст в “естественный” язык для “не программиста”.\nСсылка на первую публикаци\n","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/ru/blog/inter-prog/","tags":"","title":"Интернациональное программирование на естественных языках"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/categories/","tags":"","title":"Categories"},{"body":"","categories":"","description":"","excerpt":"","ref":"/categories/","tags":"","title":"Categories"},{"body":" Добро пожаловать на сайт проекта NewLang! Documentation Articles Playground GitHub NewLang — это язык программирования высокого уровня общего назначения c базовым синтаксисом на основе грамматических правил. С помощью макросов препроцесора, базовый синтаксис легко преобразуется в DSL на основе ключевых слов.\nТензорные вычисления и рациональные числа не ограниченной точности поддерживаются на уровне синтаксиса языка и базовых типов данных без использования дополнительных библиотек.\nМодель управления памятью на основе владения не трубет использования сборщика мусора и исключет основные ошибки еще на этапе компиляции исходного текста программы.\nОсновные свойства и особенности языка: возможность работы как в режиме интерпретатора, так и компилятора* динамическая и статическая типизация с возможностью указания типов в явном виде статическая типизация является условно-строгой (автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных. Например, целое число может быть автоматически преобразовано в вещественное или рациональное, но не наоборот) автоматическое управление памятью без сборщика мусора на основе владения* ООП* в виде явного наследования классов и «утиная типизация» на уровне синтаксиса поддерживается несколько типов функций (обычные и чистые функции без побочных эффектов) необязательные и именованные параметры функций простая интеграция с уже существующими программными библиотеками (в том числе импорт нативных переменных, функций и классов* из С/С++.) имеется REPL (read-eval-print loop — «цикл: чтение — вычисление — вывод») символьные вычисления** *) Данные возможности запланированы к реализации **) Символьные вычисления поддерживаются на уровне синтаксиса, но не реализованы Зачем нужен NewLang? У всех современных языков программирования происходит постоянное развитие (усложнение) синтаксиса по мере выхода новых версий.\nЭто является своего рода платой за появление новых возможностей языка и воспринимается пользователями как естественное явление. Но одновременно является и серьезной проблемой, так как с выходом новых версий языка в него добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для всех новых пользователей. Еще одним следствием этого процесса становится постоянное увеличение сложности разработки и поддержки уже созданных программных продуктов, когда старый программный код дорабатывается с применением уже новых стандартов и постоянным увеличением старого легаси кода. У NewLang сложность языковых конструкций ограничена естественным образом за счет разделения синтаксиса языка на несколько частей, что упрощает его изучение и использование. Основной (базовый) синтаксис — на системе строгих грамматических правил. Синтаксис DSL (domain-specific language) — хотя базовый синтаксис самодостаточен и полснотью покрывает все возможные сценарии использования, но его применение разработчиками напрямую не всегда эффекстивно с точки зрения последующего чтения исходноиков. Поэтому более правильным вариантом написания исходного кода программы будет применение предметно-ориентированного языка, который реализуется с помощью макросов препроцессора и превращает базовый синтаксис на основе грамматических правил в синтаксис на основе ключевых слов. Расширенный синтаксис — программные вставки на языке реализации (С/С++), когда основного или DSL синтаксиса становится недостаточно. Еще одно неудобство современных языков в том, что большинство из них были созданы еще до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек. Это же касается и вычислений с неограниченной точностью, которые также требуют использования дополнительных библиотечных функций. У NewLang тензорные вычисления и рациональные числа неограниченной точности доступны «из коробки». Они поддерживаются на уровне синтаксиса для удобной записи литералов, а простые арифметические типы данных являются скалярами (тензорами нулевой размерности). Реализация тензорных вычислений сделана на базе библиотеки libtorch, а рациональные числа с использованием OpenSSL. Пример скрипта Hello world! на NewLang #!../output/nlc --eval hello(str) := { # Импорт и вызов функции printf стандартной библиотеки printf(format:FmtChar, ...):Int32 := %printf...; printf('call: %s', $str); $str; }; hello('Привет, мир!'); Вывод: call: Привет, мир! Привет, мир! Пример вычисления факториала 40 на NewLang (базовый синтаксис) #!../output/nlc --eval fact := 1\\1; # Рациональное число 1 (без ограничения точности) mult := 40..1..-1?; # Итератор из диапазона для множителей от 40 до 2 [mult ?!] \u003c-\u003e { # Цикл, пока не закончатся данные итератора fact *= mult !; # Получить текущий множитель и перейти на следующий элемент итератора }; fact # Вывести итоговый результат Вывод: 815915283247897734345611269596115894272000000000\\1 Тот же код с использованием DSL синтаксиса #!../output/nlc --eval fact := 1\\1; mult := iter( 40..1..-1 ); while( curr(mult) ) { fact *= next(mult); }; fact; Вывод: 815915283247897734345611269596115894272000000000\\1 Еще примеры кода Описание синтаксиса Вся документация Articles ","categories":"","description":"","excerpt":" Добро пожаловать на сайт проекта NewLang! Documentation Articles …","ref":"/","tags":"","title":"NewLang"},{"body":" Добро пожаловать на сайт проекта NewLang! Документация Статьи Playground GitHub NewLang — это язык программирования высокого уровня общего назначения c базовым синтаксисом на основе грамматических правил. С помощью макросов препроцесора, базовый синтаксис легко преобразуется в DSL на основе ключевых слов.\nТензорные вычисления и рациональные числа не ограниченной точности поддерживаются на уровне синтаксиса языка и базовых типов данных без использования дополнительных библиотек.\nМодель управления памятью на основе владения не трубет использования сборщика мусора и исключет основные ошибки еще на этапе компиляции исходного текста программы.\nОсновные свойства и особенности языка: возможность работы как в режиме интерпретатора, так и компилятора* динамическая и статическая типизация с возможностью указания типов в явном виде статическая типизация является условно-строгой (автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных. Например, целое число может быть автоматически преобразовано в вещественное или рациональное, но не наоборот) автоматическое управление памятью без сборщика мусора на основе владения* ООП* в виде явного наследования классов и «утиная типизация» на уровне синтаксиса поддерживается несколько типов функций (обычные и чистые функции без побочных эффектов) необязательные и именованные параметры функций простая интеграция с уже существующими программными библиотеками (в том числе импорт нативных переменных, функций и классов* из С/С++.) имеется REPL (read-eval-print loop — «цикл: чтение — вычисление — вывод») символьные вычисления** *) Данные возможности запланированы к реализации **) Символьные вычисления поддерживаются на уровне синтаксиса, но не реализованы Зачем нужен NewLang? У всех современных языков программирования происходит постоянное развитие (усложнение) синтаксиса по мере выхода новых версий.\nЭто является своего рода платой за появление новых возможностей языка и воспринимается пользователями как естественное явление. Но одновременно является и серьезной проблемой, так как с выходом новых версий языка в него добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для всех новых пользователей. Еще одним следствием этого процесса становится постоянное увеличение сложности разработки и поддержки уже созданных программных продуктов, когда старый программный код дорабатывается с применением уже новых стандартов и постоянным увеличением старого легаси кода. У NewLang сложность языковых конструкций ограничена естественным образом за счет разделения синтаксиса языка на несколько частей, что упрощает его изучение и использование. Основной (базовый) синтаксис — на системе строгих грамматических правил. Синтаксис DSL (domain-specific language) — хотя базовый синтаксис самодостаточен и полснотью покрывает все возможные сценарии использования, но его применение разработчиками напрямую не всегда эффекстивно с точки зрения последующего чтения исходноиков. Поэтому более правильным вариантом написания исходного кода программы будет применение предметно-ориентированного языка, который реализуется с помощью макросов препроцессора и превращает базовый синтаксис на основе грамматических правил в синтаксис на основе ключевых слов. Расширенный синтаксис — программные вставки на языке реализации (С/С++), когда основного или DSL синтаксиса становится недостаточно. Еще одно неудобство современных языков в том, что большинство из них были созданы еще до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек. Это же касается и вычислений с неограниченной точностью, которые также требуют использования дополнительных библиотечных функций. У NewLang тензорные вычисления и рациональные числа неограниченной точности доступны «из коробки». Они поддерживаются на уровне синтаксиса для удобной записи литералов, а простые арифметические типы данных являются скалярами (тензорами нулевой размерности). Реализация тензорных вычислений сделана на базе библиотеки libtorch, а рациональные числа с использованием OpenSSL. Пример скрипта Hello world! на NewLang #!../output/nlc --eval hello(str) := { # Импорт и вызов функции printf стандартной библиотеки printf(format:FmtChar, ...):Int32 := %printf...; printf('call: %s', $str); $str; }; hello('Привет, мир!'); Вывод: call: Привет, мир! Привет, мир! Пример вычисления факториала 40 на NewLang (базовый синтаксис) #!../output/nlc --eval fact := 1\\1; # Рациональное число 1 (без ограничения точности) mult := 40..1..-1?; # Итератор из диапазона для множителей от 40 до 2 [mult ?!] \u003c-\u003e { # Цикл, пока не закончатся данные итератора fact *= mult !; # Получить текущий множитель и перейти на следующий элемент итератора }; fact # Вывести итоговый результат Вывод: 815915283247897734345611269596115894272000000000\\1 Тот же код с использованием DSL синтаксиса #!../output/nlc --eval fact := 1\\1; mult := iter( 40..1..-1 ); while( curr(mult) ) { fact *= next(mult); }; fact; Вывод: 815915283247897734345611269596115894272000000000\\1 Еще примеры кода Описание синтаксиса Вся документация Статьи ","categories":"","description":"","excerpt":" Добро пожаловать на сайт проекта NewLang! Документация Статьи …","ref":"/ru/","tags":"","title":"NewLang"},{"body":"","categories":"","description":"","excerpt":"","ref":"/search/","tags":"","title":"Search Results"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/search/","tags":"","title":"Search Results"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/tags/","tags":"","title":"Tags"},{"body":"","categories":"","description":"","excerpt":"","ref":"/tags/","tags":"","title":"Tags"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/tags/%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B/","tags":"","title":"Итераторы"},{"body":"","categories":"","description":"","excerpt":"","ref":"/tags/%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B/","tags":"","title":"Итераторы"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/tags/%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8/","tags":"","title":"Коллекции"},{"body":"","categories":"","description":"","excerpt":"","ref":"/tags/%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8/","tags":"","title":"Коллекции"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/tags/%D0%BE%D0%BE%D0%BF/","tags":"","title":"ООП"},{"body":"","categories":"","description":"","excerpt":"","ref":"/tags/%D0%BE%D0%BE%D0%BF/","tags":"","title":"ООП"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/tags/%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B/","tags":"","title":"Системые Типы"},{"body":"","categories":"","description":"","excerpt":"","ref":"/tags/%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B/","tags":"","title":"Системые Типы"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/tags/%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B8/","tags":"","title":"Строки"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/tags/%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85/","tags":"","title":"Типы Данных"},{"body":"","categories":"","description":"","excerpt":"","ref":"/tags/%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85/","tags":"","title":"Типы Данных"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/tags/%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8/","tags":"","title":"Функции"},{"body":"","categories":"","description":"","excerpt":"","ref":"/tags/%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8/","tags":"","title":"Функции"}] \ No newline at end of file +[{"body":" Operators are separated by a semicolon “;”. Indentations and line breaks are ignored. Single-line comments start with the symbol “#” until the end of the line, following the style of Python and Bash comments. Multi-line comments follow the C/C++ style and should be enclosed between “/*” and “*/”. Multi-line comments can be nested. Command sequences (code block) are enclosed in curly braces “{” and “}”. Most operators are expressions and return the result of the last operation. ","categories":"","description":"Правила синтаксиса и основные понятия языка программирования NewLang \n","excerpt":"Правила синтаксиса и основные понятия языка программирования NewLang \n","ref":"/docs/syntax/","tags":"","title":"Синтаксис"},{"body":" Операторы разделяются точкой с запятой «;». Отступы и переводы строк игнорируются. Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash. Многострочные комментарии соответствуют стилю С/С++ и должны располагаться между символами /* и */. Многосточные комментарии могут быть вложенными. Последовательность команд (блок кода) заключаются в фигурные скобки “{” и “}”. Большинство операторов являются выражениями и возвращают результат выполнения последней операции. ","categories":"","description":"Правила синтаксиса и основные понятия языка программирования NewLang \n","excerpt":"Правила синтаксиса и основные понятия языка программирования NewLang \n","ref":"/ru/docs/syntax/","tags":"","title":"Синтаксис"},{"body":"NewLang является языком с динамической типизацией и явное указание типа переменной не обязательно и на прямую не влияет на размер памяти, котрую она занимает. Тип переменных используется при проверке их совместимости, когда существующему объекту присваивается другое значение.\nПрисвоение нового значения переменной возможно только тогда, когда типы данных между собой совместимы или допускают автоматическое приведение. Это справедливо как во время компиляции исходного теста, так и во время выполнения.\nNewLang имеет закрытую иерархическую систему типов, т.е. любой новый тип данных, которые создает пользователь, обязательно должен быть наследником от уже существующего. Это напоминает реализуцию ООП в яызке Java, где каждый класс имеет в своем составе наследников Object.\nЗа счет закрытой иерархии типов реализуется и парадигма обобщённого программирования (generics).\nКаждый тип данных имеет краткое имя и функцию - конструктор.\nКраткое имя типа всегда начинается с символа двоеточия “:” и определяется в глобальной области видимости.\nФункция - конструктора типа, имеет тоже самое краткое имя типа, но без символа двоеточия “:”, и как и любая функция может располагаться в пользовательском пространстве имен.\nСоздать новый экземпляр типа нужно вызвать функцию - конструтор типа.\nСоздать новый экземпляр типа данных можно записав краткое имя типа как вызов функции, либо вызвать непосредственно функцию - конструтор типа, с указанием её полного пространства имен.\nТипы данных могут быть синонимами, т.е. два типа данных могут иметь одинаковое краткое имя, (соответствено, и одитнаковые функции конструкторы), но сами функции должны располагаться в разных областях пространства имен.\nВ этом случае, создание объекта - синонима типа, требует вызова функции конструктора с указанием её полного пространства имен, в противном случае будет вызвана функция согласно алгоритму разрешения имен (name lookup). .\nВозможно явное приведение одного типа данных к дргуому. Для этого применяется краткое имя (которое начинается с символа двоеточия “:”), как вызов функции, в параметрах которой передается один или несколько объектов, тип которых нужно привести к требуемому.\nТипы данных разделяются на простые и сложные (составные).\nПростые типы данных не могут Поля у простых типов данных не могут быть расширены\nСоздание типов происходит согласно правилам синтаксиса. Имя типа всегда начинается с символа двоеточия “:” и определяется в глобальной области видимости. Создание сложных типов (классов), может располагаться в пользовательском пространстве имен.\n, в том числе и конструктор классов, ","categories":"","description":"","excerpt":"NewLang является языком с динамической типизацией и явное указание …","ref":"/docs/types/","tags":"","title":"Типы данных"},{"body":"NewLang является языком с динамической типизацией и явное указание типа переменной не обязательно и на прямую не влияет на размер памяти, котрую она занимает. Тип переменных используется при проверке их совместимости, когда существующему объекту присваивается другое значение.\nПрисвоение нового значения переменной возможно только тогда, когда типы данных между собой совместимы или допускают автоматическое приведение. Это справедливо как во время компиляции исходного теста, так и во время выполнения.\nNewLang имеет закрытую иерархическую систему типов, т.е. любой новый тип данных, которые создает пользователь, обязательно должен быть наследником от уже существующего. Это напоминает реализуцию ООП в яызке Java, где каждый класс имеет в своем составе наследников Object.\nЗа счет закрытой иерархии типов реализуется и парадигма обобщённого программирования (generics).\nКаждый тип данных имеет краткое имя и функцию - конструктор.\nКраткое имя типа всегда начинается с символа двоеточия “:” и определяется в глобальной области видимости.\nФункция - конструктора типа, имеет тоже самое краткое имя типа, но без символа двоеточия “:”, и как и любая функция может располагаться в пользовательском пространстве имен.\nСоздать новый экземпляр типа нужно вызвать функцию - конструтор типа.\nСоздать новый экземпляр типа данных можно записав краткое имя типа как вызов функции, либо вызвать непосредственно функцию - конструтор типа, с указанием её полного пространства имен.\nТипы данных могут быть синонимами, т.е. два типа данных могут иметь одинаковое краткое имя, (соответствено, и одитнаковые функции конструкторы), но сами функции должны располагаться в разных областях пространства имен.\nВ этом случае, создание объекта - синонима типа, требует вызова функции конструктора с указанием её полного пространства имен, в противном случае будет вызвана функция согласно алгоритму разрешения имен (name lookup). .\nВозможно явное приведение одного типа данных к дргуому. Для этого применяется краткое имя (которое начинается с символа двоеточия “:”), как вызов функции, в параметрах которой передается один или несколько объектов, тип которых нужно привести к требуемому.\nТипы данных разделяются на простые и сложные (составные).\nПростые типы данных не могут Поля у простых типов данных не могут быть расширены\nСоздание типов происходит согласно правилам синтаксиса. Имя типа всегда начинается с символа двоеточия “:” и определяется в глобальной области видимости. Создание сложных типов (классов), может располагаться в пользовательском пространстве имен.\n, в том числе и конструктор классов, ","categories":"","description":"","excerpt":"NewLang является языком с динамической типизацией и явное указание …","ref":"/ru/docs/types/","tags":"","title":"Типы данных"},{"body":"Один из самых недооценных операторов, которй отсутствует в большинстве высокоуровневых языков программирования, это переменная с результатом выполнения предыдущей операции. В NewLang это системная переменная $^ (или DSL макрос @result), в которой всегда хранится результат выполнения последней операции (оператора).\nЭто чем-то похоже на глобальное значние error(), но не только для кода ошибки, а для значения любого оператора.\nПри её использовании многие синтаксические конструкции языка значительно упрощаются, так как не требуется предусматривать определение локальных переменных для сохранения промежуточных данных, например при возникновении ошибки.\n","categories":"","description":"","excerpt":"Один из самых недооценных операторов, которй отсутствует в большинстве …","ref":"/docs/ops/","tags":"","title":"Операторы и управляющие конструкции"},{"body":"Один из самых недооценных операторов, которй отсутствует в большинстве высокоуровневых языков программирования, это переменная с результатом выполнения предыдущей операции. В NewLang это системная переменная $^ (или DSL макрос @result), в которой всегда хранится результат выполнения последней операции (оператора).\nЭто чем-то похоже на глобальное значние error(), но не только для кода ошибки, а для значения любого оператора.\nПри её использовании многие синтаксические конструкции языка значительно упрощаются, так как не требуется предусматривать определение локальных переменных для сохранения промежуточных данных, например при возникновении ошибки.\n","categories":"","description":"","excerpt":"Один из самых недооценных операторов, которй отсутствует в большинстве …","ref":"/ru/docs/ops/","tags":"","title":"Операторы и управляющие конструкции"},{"body":"Ключем поиска объектов явялется строка с полным именем в иерархии имен относительно корня\nСистема классов реализации RunTime - единственный класс для приложения (процесса) - интерфейс для взаимодействия с операционной системой\nЗагружат и выгружает модули и является их владельцем (shared_ptr) Хранит глобальные объекты (ObjPtr) для глобальных объектов (встроенных типов и функций). Ключем явялется строка с полным именем объекта в иерархии имен относительно корня Хранит список глобальных объектов (типы данных и прототипы функций в TermPtr, которые создаются на этапе компиляции). Используется парсером и компилятором для разбора исходного текста и создания исполняемого файла. Module - класс для модуля\nХранение объектов модуля (shared_ptr) и добавляет weak_ptr в глобальный список объектов в RunTime Context - класс для хранения временных данных при выполнении программы\nОдин класс создается сразу при создании RunTime В дальнейшем создается по одному объекту для каждого нового потока (:Thread) Хранение списка объектов (weak_ptr) Хранение локальных объектов (ObjPtr), которые создаются на этапе выполнения Исходный текст -\u003e Парсинг -\u003e AST (TermPtr) -+-\u003e Компиляция в модуль (LLVM) -\u003e Выполнение модуля | +-\u003e Интерпретация (Выполнение AST)\nРеализация загрузки модулей и пакетов Загрузка модулей происодит следующим образом. Когда во время парсинга исходного текста встречается команда загруки модуля, создается отдельный экземпляр парсера, которому на вход подается исходный текст загружаемого модуля.\nЗагружаемый модуль парсится как обучный файл (включая обработку вложенных модулей), после чего парсер завершает работу. В результате получается отдельное AST загружаемого модуля и общая база макросов. После этого в AST модуля раскрываются области имен, производится проверка имен объетов и создание единой базы глобальных объектов.\nПосле проверки отдельного AST модуля, обработка текущего файла моедт быть прожолжена. После завершения обарботки файла раскрываются области имен, производится проверка имен объетов и создание единой базы глобальных объектов как и в случае с обработко отдельного AST модуля.\nПри такой схеме работы, компиляция отдельных AST у каждого модуля может производиться параллельно с остальными моделями, а создание общего исоплняемого файла после компиляции всех используемых модулей.\nЗагрузка пакета обработывается точто таким же образом, как и загрузка моделя.\nШаги сборки компилятора Сборка nlc Генерация с помощью nlc --no-runtime --no-dsl -emit-cpp модуля dsl Сборка модуля dsl Генерация с помощью nlc --no-runtime -emit-cpp пакета runtime Сборка пакета runtime В результате имеем готовый nlc с модулями runtime.nlm и dsl.nlm, а заодно и проверяем:\nгенерацию С++ кода без макросов сборку модуля загрузку модуля генерацию С++ кода с макросами сборку пакета загрузку пакета Выполнение тестов с модулями runtime.nlm и dsl.nlm\nОпции компилятора -no-dsl - не использовать автоматически загружаемый модуль dsl -no-runtime - не использовать автоматически загружаемый модуль runtime -emit-cpp - генерировать выходной *.cpp файл 5.5. alignas(N) Этот спецификатор появился в C++11. Применяется к простым переменным, массивам и классам. N — это выражение, вычисляемое при компиляции, его значение должно быть степенью двойки. Переменная при этом будет размещена по адресу, кратному значению N. Например:\nalignas(64) char cacheline[64]; cacheline:Int8[64](__alignas__=64) := _; constexpr Этот спецификатор появился в C++11. Применяется к простым переменным, массивам, функциям и функциям-членам. Для простой переменной или массива это означает, что ее значение вычисляется на этапе компиляции и не может быть изменено. Для функции это означает, что ее возвращаемое значение вычисляется на этапе компиляции, если значения аргументов известно на стадии компиляции. (Но такую функцию можно использовать и с обычными аргументами.) Вот пример:\nconstexpr double PI = 3.1415926535897932; constexpr int Square(int x) { return x * x; } PI^:Double = 3.1415926535897932; Square^(x:Int64):Int64 ::= { return x * x; } 5.7. consteval Этот спецификатор появился в C++20. Применяется к функциям и функциям-членам. Это более строгий вариант constexpr, при вызове такой функции значения аргументов должны быть всегда известны на стадии компиляции.\n????????????????????????????????????? Square^(x^:Int64):Int64 ::= { return x * x; } 5.8. noexcept Этот спецификатор появился в C++11. Применяется к функциям и функциям-членам и располагается в конце инструкции, после списка параметров. Этот спецификатор гарантирует отсутствие исключений в процессе выполнения тела функции.\nfunc() ::= {* *}; 5.9. mutable Применяются к нестатическим членам класса, такие члены можно изменять в константных функциях-членах (см. раздел 5.10.1).\nВ C++20 для агрегатных типов появилась еще назначенная инициализация (designated initialization): struct Point { int X; int Y; };\nPoint pt = { .X = 1, .Y = 2 };\nЭта инициализация позаимствована из C. Инициализируемые члены могут быть опущены и не только в конце, для них гарантируется инициализация по умолчанию. В отличие от C, порядок членов изменять нельзя, он должен быть таким же, как и при объявлении.\n","categories":"","description":"Описание реализация архитектуры для лучшего понимания отдельных важных моментов\n","excerpt":"Описание реализация архитектуры для лучшего понимания отдельных важных …","ref":"/docs/arch/","tags":"","title":"Архитектура"},{"body":"На память clang-17 не поддерживает:\nFeature Proposal Available Coroutines P0912R5 Partial Fully supported on all targets except Windows, which still has some stability and ABI issues. Extended floating-point types and standard names P1467R9 No Concepts P0848R3 Clang 16 (Partial) Modules No Начиная с C++ should adopt the same characters for C++26. Add @, $, and ` to the basic character set P2558R2 Yes Система классов реализации RunTime - единственный класс для приложения (процесса) - интерфейс для взаимодействия с операционной системой\nЗагружат и выгружает модули и является их владельцем (shared_ptr) Хранит сслыки на глобальные объекты (WeakPtr) и непосредственно глобальные объекты (встроенные типы и функции). Ключем явялется строка с внутренним именем объекта Хранит список глобальных объектов (типы данных и прототипы функций, которые создаются на этапе компиляции). Используется парсером и компилятором для разбора исходного текста и создания исполняемого файла. Module - класс для модуля\nХранение объектов модуля (shared_ptr) и добавляет weak_ptr в глобальный список объектов в RunTime Context - класс для хранения временных данных при выполнении программы\nОдин класс создается сразу при создании RunTime В дальнейшем создается по одному объекту для каждого нового потока (:Thread) Хранение списка объектов (weak_ptr) Хранение локальных объектов (ObjPtr), которые создаются на этапе выполнения Исходный текст -\u003e Парсинг -\u003e AST (TermPtr) -+-\u003e Компиляция в модуль (LLVM) -\u003e Выполнение модуля | +-\u003e Интерпретация (Выполнение AST)\nРеализация загрузки модулей и пакетов Загрузка модулей происодит следующим образом. Когда во время парсинга исходного текста встречается команда загруки модуля, создается отдельный экземпляр парсера, которому на вход подается исходный текст загружаемого модуля.\nЗагружаемый модуль парсится как обучный файл (включая обработку вложенных модулей), после чего парсер завершает работу. В результате получается отдельное AST загружаемого модуля и общая база макросов. После этого в AST модуля раскрываются области имен, производится проверка имен объетов и создание единой базы глобальных объектов.\nПосле проверки отдельного AST модуля, обработка текущего файла моедт быть прожолжена. После завершения обарботки файла раскрываются области имен, производится проверка имен объетов и создание единой базы глобальных объектов как и в случае с обработко отдельного AST модуля.\nПри такой схеме работы, компиляция отдельных AST у каждого модуля может производиться параллельно с остальными моделями, а создание общего исоплняемого файла после компиляции всех используемых модулей.\nЗагрузка пакета обработывается точто таким же образом, как и загрузка моделя.\nШаги сборки компилятора Сборка nlc Генерация с помощью nlc --no-runtime --no-dsl -emit-cpp модуля dsl Сборка модуля dsl Генерация с помощью nlc --no-runtime -emit-cpp пакета runtime Сборка пакета runtime В результате имеем готовый nlc с модулями runtime.nlm и dsl.nlm, а заодно и проверяем:\nгенерацию С++ кода без макросов сборку модуля загрузку модуля генерацию С++ кода с макросами сборку пакета загрузку пакета Выполнение тестов с модулями runtime.nlm и dsl.nlm\nОпции компилятора -no-dsl - не использовать автоматически загружаемый модуль dsl -no-runtime - не использовать автоматически загружаемый модуль runtime -emit-cpp - генерировать выходной *.cpp файл 5.5. alignas(N) Этот спецификатор появился в C++11. Применяется к простым переменным, массивам и классам. N — это выражение, вычисляемое при компиляции, его значение должно быть степенью двойки. Переменная при этом будет размещена по адресу, кратному значению N. Например:\nalignas(64) char cacheline[64]; cacheline:Int8[64](__alignas__=64) := _; constexpr Этот спецификатор появился в C++11. Применяется к простым переменным, массивам, функциям и функциям-членам. Для простой переменной или массива это означает, что ее значение вычисляется на этапе компиляции и не может быть изменено. Для функции это означает, что ее возвращаемое значение вычисляется на этапе компиляции, если значения аргументов известно на стадии компиляции. (Но такую функцию можно использовать и с обычными аргументами.) Вот пример:\nconstexpr double PI = 3.1415926535897932; constexpr int Square(int x) { return x * x; } PI^:Double = 3.1415926535897932; Square^(x:Int64):Int64 ::= { return x * x; } 5.7. consteval Этот спецификатор появился в C++20. Применяется к функциям и функциям-членам. Это более строгий вариант constexpr, при вызове такой функции значения аргументов должны быть всегда известны на стадии компиляции.\n????????????????????????????????????? Square^(x^:Int64):Int64 ::= { return x * x; } 5.8. noexcept Этот спецификатор появился в C++11. Применяется к функциям и функциям-членам и располагается в конце инструкции, после списка параметров. Этот спецификатор гарантирует отсутствие исключений в процессе выполнения тела функции.\nfunc() ::= {* *}; 5.9. mutable Применяются к нестатическим членам класса, такие члены можно изменять в константных функциях-членах (см. раздел 5.10.1).\nВ C++20 для агрегатных типов появилась еще назначенная инициализация (designated initialization): struct Point { int X; int Y; };\nPoint pt = { .X = 1, .Y = 2 };\nЭта инициализация позаимствована из C. Инициализируемые члены могут быть опущены и не только в конце, для них гарантируется инициализация по умолчанию. В отличие от C, порядок членов изменять нельзя, он должен быть таким же, как и при объявлении.\n","categories":"","description":"Описание архитектуры компилятора для и конкретных технических решений\n","excerpt":"Описание архитектуры компилятора для и конкретных технических решений\n","ref":"/ru/docs/arch/","tags":"","title":"Архитектура"},{"body":"NewLang имеет закрытую систему типов. т.е. любой новый тип данных, которые создает пользователь, обязательно должен быть наследником одного из уже существующих, т.е. расширять один из них. Такой поход напоминает создание классов в языке Java, в котором каждый новый класс имеет в своих родителях класс Object.\nС помощью обобщений (generics) можно писать код, который может работать с любым совместимым типом данных.\nФрагмент иерархии типов данных (строки и числа, а в скобках указаны синонимы типов):\n:Any -+-\u003e :Arithmetic -+-\u003e :Tensor -+-\u003e :Integer --\u003e :Int64 ... --\u003e :Int8 --\u003e :Bool | | | (:DWord64) (:Char) | | | (:Byte) | | | | | +-\u003e :Number --\u003e :Float64 --\u003e :Float32 --\u003e :Float16 --\u003e ... | | | (:Double) (:Single) | | | | | +-\u003e :Complex ... | | | +-\u003e :Rational | +-\u003e :String -+-\u003e :StrChar | | (:FmtChar) | | | +-\u003e :StrWide | (:FmtWide) | | ... Обобщенные типы :Any - обобщенный тип для всех остальных типов данных :Arithmetic - обобщенный тип для всех числовых типов :Tensor - обобщенный тип для чисел, которые можно представить в машинном формате :Integer - обощенный тип для всех целочисленных типов данных :Number - обощенный тип для всех чисел с плавающей точкой :Complex - обощенный тип для всех комплексных чисел :String - обощенный тип для текстовых строк Примеры определения функций с обобщенными типами only_int8(arg:Int8):Int8 := ... ; # Функиця принимает и возвращает только :Int8 any_int(arg:Integer):Integer := ... ; # Функиця принимает и возвращает только целые числа any_tensor(arg:Tensor):Tensor := ... ;# Функиця принимает и возвращает любые машинные типы чисел any_any1(arg:Any):None := ... ; # Функиця принимает любой тип аргумента и ничего не возвращает any_any2(arg) := ... ; # Тип не указан - функиця можен принимать и возвращать любой тип ","categories":"","description":"","excerpt":"NewLang имеет закрытую систему типов. т.е. любой новый тип данных, …","ref":"/docs/types/generics/","tags":["типы данных","ООП","коллекции"],"title":"Иерархия типов и обобщения"},{"body":"NewLang имеет закрытую систему типов. т.е. любой новый тип данных, которые создает пользователь, обязательно должен быть наследником одного из уже существующих, т.е. расширять один из них. Такой поход напоминает создание классов в языке Java, в котором каждый новый класс имеет в своих родителях класс Object.\nС помощью обобщений (generics) можно писать код, который может работать с любым совместимым типом данных.\nФрагмент иерархии типов данных (строки и числа, а в скобках указаны синонимы типов):\n:Any -+-\u003e :Arithmetic -+-\u003e :Tensor -+-\u003e :Integer --\u003e :Int64 ... --\u003e :Int8 --\u003e :Bool | | | (:DWord64) (:Char) | | | (:Byte) | | | | | +-\u003e :Number --\u003e :Float64 --\u003e :Float32 --\u003e :Float16 --\u003e ... | | | (:Double) (:Single) | | | | | +-\u003e :Complex ... | | | +-\u003e :Rational | +-\u003e :String -+-\u003e :StrChar | | (:FmtChar) | | | +-\u003e :StrWide | (:FmtWide) | | ... Обобщенные типы :Any - обобщенный тип для всех остальных типов данных :Arithmetic - обобщенный тип для всех числовых типов :Tensor - обобщенный тип для чисел, которые можно представить в машинном формате :Integer - обощенный тип для всех целочисленных типов данных :Number - обощенный тип для всех чисел с плавающей точкой :Complex - обощенный тип для всех комплексных чисел :String - обощенный тип для текстовых строк Примеры определения функций с обобщенными типами only_int8(arg:Int8):Int8 := ... ; # Функиця принимает и возвращает только :Int8 any_int(arg:Integer):Integer := ... ; # Функиця принимает и возвращает только целые числа any_tensor(arg:Tensor):Tensor := ... ;# Функиця принимает и возвращает любые машинные типы чисел any_any1(arg:Any):None := ... ; # Функиця принимает любой тип аргумента и ничего не возвращает any_any2(arg) := ... ; # Тип не указан - функиця можен принимать и возвращать любой тип ","categories":"","description":"","excerpt":"NewLang имеет закрытую систему типов. т.е. любой новый тип данных, …","ref":"/ru/docs/types/generics/","tags":["типы данных","ООП","коллекции"],"title":"Иерархия типов и обобщения"},{"body":"Objects and data types can be named using letters, numbers, and underscores in any combination, provided that the first character of the name is not a digit.\nAll identifiers must be unique, and to avoid collisions, you can use namespaces and a modular code structure supported simultaneously by NewLang.\nOverloading functions based on argument types is absent in NewLang, so defining multiple functions with the same name but different arguments is not possible, but you can override a function, including extending the types of accepted arguments or increasing their number.\nAn object identifier can contain one or more special characters - qualifiers (or sigils), which represent specific values. An object identifier that does not contain a qualifier is called simple:\nName Qualifiers: ‘@’ - the at sign prefix is used to specify the name of a macro, which is processed by the preprocessor before the start of the program’s syntactic analysis. ‘@’ - the at prefix is used to specify the name of a macro that is processed by the preprocessor before the start of the syntactic analysis of the source code of the program. ‘$’ - the dollar sign at the beginning of an object’s name denotes an automatic name for a temporary variable, the memory space for which is dynamically allocated during the application’s execution, and the lifetime is limited by the language semantics. ‘::’ - the double colon serves as a separator for namespaces and indicates a static object, the memory space for which is allocated during the compilation of the application or module. If the name starts with ‘::’, the object’s scope will be global and it will be accessible throughout the application. Otherwise, the object’s visibility will be limited to the current program module. ‘.’ - the dot prefix is used when accessing a module or class field (limits the scope to the current object). The dot prefix can be used when defining (calling) a function to explicitly identify a named argument, preventing it from being overridden by a preprocessor macro. ‘\\’ - the backslash at the beginning of a term denotes the name of a program module, and also separates directory names in the hierarchy of program module placement. ‘:’ — colon at the beginning of the term denotes the name of a data type or a class constructor ‘%’ — the percent sign prefix is used for imported symbols (native variables and functions) ‘^’ — the caret symbol after the name is used to give immutability (constancy, non-modifiability) to the object. Name Lookup If the object name does not contain a qualifier, it is called simple. Creating an object with a simple name is equivalent to creating a local object.\nIn other cases, when NewLang encounters a simple object name without a qualifier (sigil), a special algorithm comes into play that associates the simple name found in the source code of the program with its declaration or a specific object by its internal name.\nResolution of simple names without a qualifier (name lookup for function/variable names) always occurs in a strictly defined order:\nFirst, the search for the name is among macros Next, the search is among local objects up to objects of the current module Lastly, the search is among global objects with a gradual expansion of the namespace search scope from current to global Such a sequence of name resolution always provides the opportunity to redefine global/local objects or argument names in functions for existing code without serious changes.\nFor example, for the name name in the namespace ns, the search occurs in the following sequence: @name -\u003e $name -\u003e ns::name -\u003e ::ns::name -\u003e ::name, and for the name arg, only @arg is checked:\nns:: { name(arg=\"value\"); }; And at the same time, there will always be the possibility to specify a specific object regardless of the algorithm for resolving simple names. It is sufficient to explicitly specify the qualifier in the object name.\nFor example, to access the global object name from the namespace ns in the above example, you need to use the full object name ::ns::name, and the named argument ’. arg’ will not be replaced by the @arg macro if it is defined:\n::ns::name(.arg=\"value\"); Forward Declaration In the program text, you can only refer to actually existing (created) objects. But in cases where it is necessary to refer to an object that is created in another module or will be created later, you can make a preliminary declaration, in which the compiler registers the name and type of the object without its actual creation.\nBy means of a forward declaration, one can refer only to static objects (data types), or local class fields that the compiler does not yet know about but which will be defined during the compilation process later.\nFor a forward declaration, only the fully qualified name can be used, which must exactly match the object’s name when it is subsequently created.\nThe same syntax is used for a forward declaration as for the actual creation of an object, only an ellipsis should be specified to the right of the creation operator.\nThe scope of a forward declaration corresponds to the scope of its placement, not the actual scope of the object (even for global objects).\n# Preliminary definition of a module variable # Applies to the entire module var_module:Int32 := ...; func() ::= { # Preliminary announcement using DSL # (only works inside a function body) @declare( func2(arg:Int32):Int32 ); var_module = func2(var_module); @return var_module; }; func2(arg:Int32):Int32 ::= { @return $arg*$arg; } var_module:Int32 := 1; Argument Names, Special, System Names The notation of argument names in functions is very similar to referencing arguments in bash scripts, where “$1” or “$name” represents the ordinal number or name of the corresponding argument.\nThe reserved name “$0” denotes the current object, and the name “$$” denotes the parent object.\nAll function arguments are collected in a single dictionary with the special name $*\nThe immutable variable “$^” contains the result of the last operator or code block execution.\nThe full name of the current module is contained in the variable @\\\\, and the current namespace in the variable @::, i.e.:\n# File name filename.src in directory dir ns:: { # Use namespace ns name:: { # Preprocessor command \"@#\" - convert to a string ns_str := @# @::; # String with namespase \"::ns::name::\" mod_str := @# @\\\\; # String with module name \"\\\\dir\\filename\" }; }; Scope The underscore symbol, as well as an underscore at the beginning of a name or double underscores at the beginning and end of a name, have special meanings.\nA single underscore corresponds to a protected, and two underscores to a private scope of an object within a module or class, in accordance with the conventions in the Python language.\nHowever, just like in Python, scopes are more of a “gentleman’s agreement,” and with explicit naming, access to protected objects can be obtained by simply specifying the full object name.\nIn addition, there are also system fields and objects that start and end with two underscores.\n‘$’ - The dollar sign at the beginning of a name denotes a system (local) name of a temporary variable, the memory space for which is allocated during execution, and the lifetime is limited by the language semantics. ‘::’ - Double colons serve as a separator when specifying namespaces. Explicit namespace specification is a sign of a static object, the memory space for which is allocated during the compilation of the application or module. ","categories":"","description":"Rules for naming variables, functions, and data types","excerpt":"Rules for naming variables, functions, and data types","ref":"/docs/syntax/naming/","tags":"","title":"Naming Objects"},{"body":"NewLang is a language with dynamic typing, and explicit type declaration does not affect the memory size occupied by a variable. Type information is used when checking their compatibility, when assigning a value of a different type to an existing object. This operation is possible only when the types are compatible and allow for automatic conversion. This is true both during parsing/compilation of the source text and during execution in interpreter and/or compiled file modes.\nArithmetic types All numbers (except rational) in NewLang are tensors, i.e. arrays of one type with an arbitrary number of dimensions and the same column size in each. A unit number is also a tensor of zero size.\nOnly signed integers are supported, as there is no special need for unsigned numbers, and there are many problems with them that can be found very easily.\nIssues with unsigned numbers (from the internet): First, subtracting two unsigned numbers, for example 3 and 5. 3 minus 5 equals 4294967294 because -2 cannot be represented as an unsigned number. Second, unexpected behavior may occur when mixing signed and unsigned integer values. C++ can freely convert signed and unsigned numbers, but does not check the range to ensure that you are not overflowing your data type.\nThe names of the built-in arithmetic types: :Int8, :Int16, :Int32, :Int64, :Float16, :Float32, :Float64, :Complex16, :Complex32, :Complex64 speak for themselves. And although among them there are names that are inherent to unsigned numbers (:Byte, :Word, :DWord, etc.), they are synonyms and are used for interaction with native C++ code.\nLogical type A separate type is the logical type: Bool, which can only take values 0 or 1 (false/true respectively), and depending on the operation being performed, it can also be classified as integer types, or not included in their composition (this approach to interpreting the logical data type was taken from the Torch library).\n// Treat bool as a distinct \"category,\" to be consistent with type promotion // rules (e.g. `bool_tensor + 5 -\u003e int64_tensor`). If `5` was in the same // category as `bool_tensor`, we would not promote. Differing categories // implies `bool_tensor += 5` is disallowed. // // NB: numpy distinguishes \"unsigned\" as a category to get the desired // `bool_tensor + 5 -\u003e int64_tensor` behavior. We don't, because: // * We don't want the performance hit of checking the runtime sign of Scalars. // * `uint8_tensor + 5 -\u003e int64_tensor` would be undesirable. Tensor Indexing Access to tensor elements is done by an integer index starting from 0. For a multidimensional tensor, element indices are listed in square brackets separated by commas. Access to elements through a negative index is supported, which is handled in the same way as in Python (-1 is the last element, -2 is the second to last, and so on).\nRanges can be used as tensor indices, which are handled the same way as in Python, as well as the value :None and ellipsis .... The value :None, meaning absence of an index, signifies an arbitrary size of the tensor in one specific dimension, while the ellipsis ... denotes an arbitrary dimension in any number of dimensions (hence, it can appear in the tensor index only once).\nThe tensor literal in the program text is written in square brackets with a mandatory closing comma, i.e. [1, 2,] - this is a literal one-dimensional tensor of two numbers. After the closing bracket, the tensor type can be explicitly specified. If the type is not specified, it is automatically output based on the specified data and the minimum possible byte size that allows all values to be saved without loss of accuracy is selected.\nExamples of creating tensors and transforming their dimensions can be found here.\nRational Numbers For calculations with unlimited precision in NewLang, a separate type is used - rational numbers. They are written in the form of a common fraction, in which the numerator must be an integer, and the denominator natural (an integer without zero).\nA backslash is used as the fraction separator, i.e. 1\\1 - rational number 1, -5\\1 - rational number -5, etc.\n","categories":"","description":"","excerpt":"NewLang is a language with dynamic typing, and explicit type …","ref":"/docs/types/numbers/","tags":"","title":"Numbers"},{"body":"В качестве имен объектов и типов данных можно использовать буквы, цифры и знаки подчеркивания в любых комбинациях, при условии, что первый символ имени не является цифрой.\nВсе идентификаторы должны быть уникальны, а для избежания коллизий можно использовать пространство имен и модульную структуру кода, которые NewLang поддерживает одновременно.\nПерегрузка функций по типам аргументов NewLang отсуствует, поэтому несколько функций с однинаковым именем но разными аругментами определить нельзя, но можно переопределить функцию, в том числе и расширив типы принимаемых аргументов или увеличив их количество.\nИдентификатор объекта может содержать один или несколько специальных символов - квалификаторов (или сигилов), за которыми закрепелено определенное значение. Идентификатор объекта который не содержит квалификатора, называется простым:\nКвалификаторы имен: ‘@’ — префикс собачка используется для указания имени макроса, который обрабатыватся препроцессором до начала синтаксического анализа исходного текста программы. ‘$’ — знак доллара в начале имени объекта обозначает автоматичекое имя временной переменной, область памяти для которой выделяется динамически во время выполнения приложения, а время жизни ограничено семантикой яызка ‘::’ — двойное двоеточие является разделителем пространства имен, и является признаком статического объекта, область памяти для которого выделяется во время компиляции приложения или модуля. Если имя начинается на ‘::’, то область видимости объекта будет глобальной и он будет доступен в рамках всего приложения. В противном случае, видимость объекта будет ограничена только текущим программным модулем. ‘.’ — префикс точка используется при обращении к полю модуля или класса (ограничивает область видимости текущим объектом). Префикс точка может использоваться при определении (вызове) функции для явной идентификации именованного аргумента, чтобы его нельзя было перекрыть макросом препроцессора. ‘\\’ — обратный слеш в начале термина обозначает имя программного модуля, а так же разделяет имена каталогов в иерархии размещения программных модулей. ‘:’ — двоеточие в начале термина обозначает имя типа данных или конструктор класса ‘%’ — префикс знак процента указывается для импортируемых символов (нативных переменных и функций) ‘^’ — символ карет (крышечка/домик) после имени используется для придания объекту иммутабельности (константности, не изменяемости). Разрешение имен (name lookup) Если имя объекта не содержит квалификатора, оно называется простым. Создание объекта с указанием простого имени равнозначно созданию локального объекта.\nВ других случаях, когда NewLang встречает простое имя объекта без квалификатора (сигила), то в дело вструпает специальный алгоритм, который связывает простое имя, встретившееся в исходном тексте программы, с его декларацией или конкретным объектом по его внутреннему имени.\nРазрешение простых имен без квалификатора (name lookup, или поиск имени функции/переменной) происходит всегда в строго определенном порядке:\nв первую очередь происходит поиск имени среди макросов далее выполняется поиск имени среди локальных объектов до объектов текущего модуля в последнюю очередь выполняется поиск среди глобальных объетов с постепенным расширением пространства имен области поиска от текущей до глобальной Такая последовательность разрешение имен всегда предоставляет возможность переопределить глобальные/локальные объекты или имена аргументов у функций для уже существующего кода без его серъезных изменений.\nНапример, для имени name в области имен ns поиск происходит в следующей последовательности: @name -\u003e $name -\u003e ns::name -\u003e ::ns::name -\u003e ::name, а для имени arg проверяется только @arg:\nns:: { name(arg=\"value\"); }; И в тоже время, всегда остатся возможность указать конкретный объект не зависимо от работы алгоритма разрешение простых имен. Достаточно указать квалификатор в имени объекта в явном виде.\nНапример, обратиться к глобальному объекту name из пространства имен ns из примера выше, нужно по полному имени объекта ::ns::name, а именованнй аргумент ’. arg’ не будет заменен макросом @arg, если такой будет определен:\n::ns::name(.arg=\"value\"); Предварительное объявление В тексте программы можно ссылаться только на реально существующие (созданные) объекты. Но для тех случаев, когда требуется сослаться на объект, который создан в другом модуле или будет создан позже, можно сделать предварительное объявление, при котором компилятор регистриурет имя и тип объекта без его реального создания.\nЗа счет предварительного объявления можно ссылаться только на статические объекты (типы данных), или локальные поля класса о которых компилятор ещё не знает, но которые будут определены в процессе компиляции позже.\nДля предварительного объявления можно использовать только полное квалифцированное имя, которое должно будет в точности совпадать с именем обекта при его последующем создании.\nДля предварительного объявления используется точто такой же синтаксис, как и при реальном создании объекта, только с права от операторо создания должно быть указано многоточие.\nОбласть видимости предварительное объявения соответствует области видимости его размещенея, а не реальвой области видимости объекта (это касается даже глобальных объектов).\n# Предварительное определение переменной модуля # Действует для всего модуля var_module:Int32 := ...; func() ::= { # Предварительное объявление с помощью DSL # (действует только внутри тела функции) @declare( func2(arg:Int32):Int32 ); var_module = func2(var_module); @return var_module; }; func2(arg:Int32):Int32 ::= { @return $arg*$arg; } var_module:Int32 := 1; Имена аргументов, специальные, системные имена Обозначение имен аргументов у функций очень похоже на обращение к аргументы в bash скриптах, где “$1” или “$name” — порядковый номер или имя соответствующего аргумента.\nЗарезервированное имя “$0” обозначает текущий объект, а именем “$$” обозначается родительский объект.\nВсе аргументы функции собранны в одном словаре со специальным имеенм $*\nНеизменяемая переменная “$^” содержит результат выполнения последнего оператора или блока кода.\nПолное имя текущего модуля содержится в переменной @\\\\, а текущая область имен в переменной @::, т.е.:\n# Имя файла filename.src в каталоге dir ns:: { # Использовать пространство имен ns name:: { # Команда препроцессора \"@#\" - преобразовать в символьную строку ns_str := @# @::; # Строка с областью имен \"::ns::name::\" mod_str := @# @\\\\; # Строка с именем модуля \"\\\\dir\\filename\" }; }; Области видимости Символ подчерка, а так же подчерк в начале имени или двойные подчерки в начале и в конце имени имеют специальное значение.\nОдин подчерк соответствует защищенной, а два подчерка - приватной области видимости объекта в модуле или классе, что соответствует принятым соглашениям в языке Python.\nНо так же, как и в языке Python, области видимости больше соответствуют “джентльменской” договоренности и при явном указании имени, доступ к защищенным объектам можно получить, просто указав полное имя объекта.\nВ дополнении к этому, существуют еще системные поля и объекты, которые начинаются и заканчиваются на два подчерка.\n‘$’ — знак доллара в начале имени обозначает системное (локальное) имя временной переменной, область памяти для которой выделяется во время выполнения, а время жизни ограничено семантикой яызка ‘::’ — двойное двоеточие являются разделителем при указании пространства имен. Явное указание пространства имен является признаком статического объекта, область памяти для которого выделяется во время компиляции приложения или модуля. ","categories":"","description":"Правила именования переменных, функций и типов данных","excerpt":"Правила именования переменных, функций и типов данных","ref":"/ru/docs/syntax/naming/","tags":"","title":"Именование объектов"},{"body":" Область видимости объекта =/= время жизни объекта Область видимости объекта определяется его расположением в программном коде (блоки кода, пространство имен, модели и т.д.) Объект может существовать, но может быть не доступен из текущей области видимости.\nИмя объекта, создание объекта и его расположение Имя объекта - его уникальный идентификатор, который однозначно определяется местом его расположения (нахождение сильной ссылки на объект). Имя у объекта может быть всегда, даже тогда, когда сам объект физически еще не создан (например при предварительном объявлении).\nСоздания объектов и присвоения новых значений Для создания объектов и присвоения им новых значений в NewLang используется несколько операторов:\n“::=” или “::-” - используется для создания только новых объектов. Если объект с таким именем был определен ранее, то произойдет ошибка компиляции. “:=” или “:-” - используется для создания новых объектов с возможностью перекрытия имен. Если локальный объект с таким именем был определен ранее, то новый объект будет его перекрывать. “=” - применяется только для присвоения значения уже существующим объектам. Если объект с указанным именем отсутствует, то возникает ошибка компиляции. “:=:” - Оператор не создает нового объекта, а обменивает значения уже существуюих (переменные должны иметь одинаковые/совместимые типы данных). ?????????????????????????????????????\n“[]=” - добавлеят новый элемент к словарю или переопределяет созданное ранее имя функции или метод класса. Похож на оператор присвоения значения “=”, но в отличии от него не удаляет старое значение, а сохраняет его в стек переопределнных имен, и к старому значению можно обратиться по системному имени “$$” ????????????????? *). Не может применяться к макросам. Использование трех разных видов операторов для создания/изменения объектов позволяет более гибко контролировать подобные операции и выявлять логические ошибки в коде на более раннем этапе.\nНапример, при определении класса :NewClass2:\n:NewClass := :Class() { # Базовый класс filed ::= 2; # Однократная инициализация (статическоого) члена класса method() ::= {}; # Регистрация метода }; :NewClass2 := :NewClass() { filed ::= 2; # Будет ошибка, т.к. field уже есть в базовом классе method() = {}; # Аналог override, т.к. method должен существовать в базовом классе }; Если же контролировать момент создание объектов и присвоения им значений не требуется, то можно пользоваться единственным оператором :=.\nvar := 1.0; # Создать новую переменную var без явного указания типа var := 100; # Присвоить новое значение уже существующей переменной printf(format:FmtChar, ...):Int32 ::= %printf...; # Создать новый или переопределить printf ??????????????????????????????????????????? Присваивание значения сразу нескольким переменным и оператор распаковки словаря NewLang поддерживает операцию присваивания значения сразу нескольким переменным, которые должны быть перечислены через запятую слева от оператора присвоения. С правой стороны от оператора присвоения может находится только одно значение. А для обмена занчениями двух переменных, вместо традиционной записи:\na,b = b,a; Нужно использовать отдельный оператор обмена:\na :=: b; В качестве правого операнда в операторе присвоения допускается использовать оператор распаковки словаря … (многоточие), который можно использовать и при передаче аргументов в функцию.\nargs := (arg1=1, arg2=2, 3,4,); call(arg=0, ... args); # Что равносильно вызову call(arg=0, arg1=1, arg2=2, 3, 4); Словарь может быть указан и с левой стороны от оператора присвоения. Таким образом можно записать самый простой способ перебора всех его элементов: item, dictionary := ... dictionary;, т.е. когда первый элемент словаря сохраняется в переменную item, а из самого словаря удаляется, и так в цикле пока словарь не станет пустым.\nПример реализации цикла foreach для суммирования всех элементов словаря (или одномерного тензора) с использованием оператора раскрытия словаря (списка):\nsumma := 0; dictionary := (1,2,3,4,5,); @while( dictionary ) { # Первый элемент словаря перемещается в item item, dictionary := ... dictionary; summa += item; }; Заполнение данными При заполнении данными размерных тензоров существует краткий способ указания их начальных значений. Для этого используется многоточие в следующих вариантах:\n:Tensor[10](2,3, ...) - повторение всех предыдущих данных до полного заполнения тензора, что равносильно записи :Tensor[10](2,3, 2,3, 2,3, 2,3, 2,3).\n:Tensor[10](2, 3, ... 42 ...) - заполнение значением 42 до конца тензора, что равносильно записи :Tensor[10](2,3, 42,42,42,42,42,42,42,42).\n:Tensor[10](2, 3, ... rand() ...) - заполнение до конца тензора значением, которое будет возвращать функция. Указанная функция будет вызываться для каждого элемента до полного заполнения тензора (8 раз).\n:Tensor[10]( rand(), rand(), ...) - заполнение тензора двумя произвольными заначениями, то есть функция rand() будет вызвана дважды для двух первых элементов, после чего эти значения будут использоваться до полного заполнения тензора (как в первом примере).\n:Tensor[10]( ... 0..0.99..0.1 ) - заполнение тензора элементами диапазона, что равносильно записи\n:Tensor[10](0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9). Раскрытие диапазона создает фиксированное количество значений. Поэтому в данном примере размерность тензора можно не указывать, так как она будет создана автоматически.\n:Tensor[15]( ... 0..5 , ... ) - заполнение тензора элементами диапазона с их повторением до заданного размера тензора: :Tensor(0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4)\nЗаполнение данными в словарях и аргументах функций Предыдущие способы заполнения данными возможны только для тензоров фиксированного размера, так как позволяют получить произвольное количество значений, но их можно применять только в конце списка значения для инициализации.\nОператоры раскрытия словаря или диапазона создают ограниченное количество значений, но за счет этого их можно использовать не только для инициализации тензоров, но и в качестве начальных значений у словарей или создания аргументов при вызове функций, причем в произвольном месте, а не только в конце списка инициализации:\n:Tensor( ... 0..0.99..0.1 ) - заполнение тензора без указания его размера элементами диапазона, что равносильно записи :Tensor(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9)\nfuntcion( 0, ... dict, 42 ) - раскрытие словаря как индивидуальных не именованных аргументов функции, к примеру funtcion( 0, 1, 2, 3, 42), если словарь dict содержал три элемента 1, 2 и 3.\nfuntcion( ... ... dict, end=4) - раскрытие словаря как индивидуальных именованных аргументов функции. Если словарь dict будет содержать элементы (1, two=2, three=3,), то это будет равносильно вызову функции funtcion( 1, two=2, three=3, end=4).\n","categories":"","description":"","excerpt":" Область видимости объекта =/= время жизни объекта Область видимости …","ref":"/docs/ops/create/","tags":"","title":"Создание объектов"},{"body":" Область видимости объекта =/= время жизни объекта Область видимости объекта определяется его расположением в программном коде (блоки кода, пространство имен, модели и т.д.) Объект может существовать, но может быть не доступен из текущей области видимости.\nИмя объекта, создание объекта и его расположение Имя объекта - его уникальный идентификатор, который однозначно определяется местом его расположения (нахождение сильной ссылки на объект). Имя у объекта может быть всегда, даже тогда, когда сам объект физически еще не создан (например при предварительном объявлении).\nСоздания объектов и присвоения новых значений Для создания объектов и присвоения им новых значений в NewLang используется несколько операторов:\n“::=” или “::-” - используется для создания только новых объектов. Если объект с таким именем был определен ранее, то произойдет ошибка компиляции. “:=” или “:-” - используется для создания новых объектов с возможностью перекрытия имен. Если локальный объект с таким именем был определен ранее, то новый объект будет его перекрывать. “=” - применяется только для присвоения значения уже существующим объектам. Если объект с указанным именем отсутствует, то возникает ошибка компиляции. “:=:” - Оператор не создает нового объекта, а обменивает значения уже существуюих (переменные должны иметь одинаковые/совместимые типы данных). ?????????????????????????????????????\n“[]=” - добавлеят новый элемент к словарю или переопределяет созданное ранее имя функции или метод класса. Похож на оператор присвоения значения “=”, но в отличии от него не удаляет старое значение, а сохраняет его в стек переопределнных имен, и к старому значению можно обратиться по системному имени “$$” ????????????????? *). Не может применяться к макросам. Использование трех разных видов операторов для создания/изменения объектов позволяет более гибко контролировать подобные операции и выявлять логические ошибки в коде на более раннем этапе.\nНапример, при определении класса :NewClass2:\n:NewClass := :Class() { # Базовый класс filed ::= 2; # Однократная инициализация (статическоого) члена класса method() ::= {}; # Регистрация метода }; :NewClass2 := :NewClass() { filed ::= 2; # Будет ошибка, т.к. field уже есть в базовом классе method() = {}; # Аналог override, т.к. method должен существовать в базовом классе }; Если же контролировать момент создание объектов и присвоения им значений не требуется, то можно пользоваться единственным оператором :=.\nvar := 1.0; # Создать новую переменную var без явного указания типа var := 100; # Присвоить новое значение уже существующей переменной printf(format:FmtChar, ...):Int32 ::= %printf...; # Создать новый или переопределить printf ??????????????????????????????????????????? Присваивание значения сразу нескольким переменным и оператор распаковки словаря NewLang поддерживает операцию присваивания значения сразу нескольким переменным, которые должны быть перечислены через запятую слева от оператора присвоения. С правой стороны от оператора присвоения может находится только одно значение. А для обмена занчениями двух переменных, вместо традиционной записи:\na,b = b,a; Нужно использовать отдельный оператор обмена:\na :=: b; В качестве правого операнда в операторе присвоения допускается использовать оператор распаковки словаря … (многоточие), который можно использовать и при передаче аргументов в функцию.\nargs := (arg1=1, arg2=2, 3,4,); call(arg=0, ... args); # Что равносильно вызову call(arg=0, arg1=1, arg2=2, 3, 4); Словарь может быть указан и с левой стороны от оператора присвоения. Таким образом можно записать самый простой способ перебора всех его элементов: item, dictionary := ... dictionary;, т.е. когда первый элемент словаря сохраняется в переменную item, а из самого словаря удаляется, и так в цикле пока словарь не станет пустым.\nПример реализации цикла foreach для суммирования всех элементов словаря (или одномерного тензора) с использованием оператора раскрытия словаря (списка):\nsumma := 0; dictionary := (1,2,3,4,5,); @while( dictionary ) { # Первый элемент словаря перемещается в item item, dictionary := ... dictionary; summa += item; }; Заполнение данными При заполнении данными размерных тензоров существует краткий способ указания их начальных значений. Для этого используется многоточие в следующих вариантах:\n:Tensor[10](2,3, ...) - повторение всех предыдущих данных до полного заполнения тензора, что равносильно записи :Tensor[10](2,3, 2,3, 2,3, 2,3, 2,3).\n:Tensor[10](2, 3, ... 42 ...) - заполнение значением 42 до конца тензора, что равносильно записи :Tensor[10](2,3, 42,42,42,42,42,42,42,42).\n:Tensor[10](2, 3, ... rand() ...) - заполнение до конца тензора значением, которое будет возвращать функция. Указанная функция будет вызываться для каждого элемента до полного заполнения тензора (8 раз).\n:Tensor[10]( rand(), rand(), ...) - заполнение тензора двумя произвольными заначениями, то есть функция rand() будет вызвана дважды для двух первых элементов, после чего эти значения будут использоваться до полного заполнения тензора (как в первом примере).\n:Tensor[10]( ... 0..0.99..0.1 ) - заполнение тензора элементами диапазона, что равносильно записи\n:Tensor[10](0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9). Раскрытие диапазона создает фиксированное количество значений. Поэтому в данном примере размерность тензора можно не указывать, так как она будет создана автоматически.\n:Tensor[15]( ... 0..5 , ... ) - заполнение тензора элементами диапазона с их повторением до заданного размера тензора: :Tensor(0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4)\nЗаполнение данными в словарях и аргументах функций Предыдущие способы заполнения данными возможны только для тензоров фиксированного размера, так как позволяют получить произвольное количество значений, но их можно применять только в конце списка значения для инициализации.\nОператоры раскрытия словаря или диапазона создают ограниченное количество значений, но за счет этого их можно использовать не только для инициализации тензоров, но и в качестве начальных значений у словарей или создания аргументов при вызове функций, причем в произвольном месте, а не только в конце списка инициализации:\n:Tensor( ... 0..0.99..0.1 ) - заполнение тензора без указания его размера элементами диапазона, что равносильно записи :Tensor(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9)\nfuntcion( 0, ... dict, 42 ) - раскрытие словаря как индивидуальных не именованных аргументов функции, к примеру funtcion( 0, 1, 2, 3, 42), если словарь dict содержал три элемента 1, 2 и 3.\nfuntcion( ... ... dict, end=4) - раскрытие словаря как индивидуальных именованных аргументов функции. Если словарь dict будет содержать элементы (1, two=2, three=3,), то это будет равносильно вызову функции funtcion( 1, two=2, three=3, end=4).\n","categories":"","description":"","excerpt":" Область видимости объекта =/= время жизни объекта Область видимости …","ref":"/ru/docs/ops/create/","tags":"","title":"Создание объектов"},{"body":"NewLang является языком с динамической типизацией и явное указание типа не влияет на размер памяти, занимаемой переменной. Информация о типах используется при проверке их совместимости, когда существующему объекту присваивается значение другого типа. Такая операция возможна только тогда, когда типы совместимы между собой и допускают автоматическое приведение. Это справедливо как во время парсинга/компиляции исходного теста, так и во время выполнения в режимах интерпретатора и/или скомпилированного файла.\nАрифметические типы Все числа (кроме рациональных) в NewLang являются тензорами, т.е. массивами одного типа с произвольным количеством измерений и одинаковым размером столбцов в каждом. Единичное число, это тоже тензор нулевого размера.\nПоддерживаются только знаковые целые числа, т.к. в без знаковых числах особая нужда отсутствует, а проблем с ними можно найти очень много на ровном месте.\nПроблемы без знаковых чисел (из интернета):\nВо-первых, вычитание двух без знаковых чисел, например 3 и 5. 3 минус 5 равно 4294967294, т.к. -2 не может быть представлено как без знаковое число. Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных значений со знаком и без знака. С++ может свободно преобразовывать числа со знаком и без знака, но не проверяет диапазон, чтобы убедиться, что вы не переполняете свой тип данных.\nИмена встроенных арифметических типов: :Int8, :Int16, :Int32, :Int64, :Float16, :Float32, :Float64, :Complex16, :Complex32, :Complex64 говорят сами за себя. И хотя среди них присуствуют названия, присущие беззнаковым числам (:Byte, :Word, :DWord и т.д.), они являются синонимами и применяются для взаимодействия с нативным C++ кодом.\nЛогический тип Отдельным типом идет логический тип :Bool, который может принимать значения только 0 или 1 (false/true соответственно), и в зависимости от выполняемой операции тоже может быть отнесен к целочисленным типам, так и не входить в их состав (данный подход интерпретации логического типа данных был взят из библиотеки Torch).\n// Treat bool as a distinct \"category,\" to be consistent with type promotion // rules (e.g. `bool_tensor + 5 -\u003e int64_tensor`). If `5` was in the same // category as `bool_tensor`, we would not promote. Differing categories // implies `bool_tensor += 5` is disallowed. // // NB: numpy distinguishes \"unsigned\" as a category to get the desired // `bool_tensor + 5 -\u003e int64_tensor` behavior. We don't, because: // * We don't want the performance hit of checking the runtime sign of Scalars. // * `uint8_tensor + 5 -\u003e int64_tensor` would be undesirable. Индексация тензоров Доступ к элементам тензора происходит по целочисленному индексу, который начинается с 0. Для многомерного тензора, индексы элемента перечисляются в квадратных скобках через запятую. Поддерживается доступ к элементам через отрицательный индекс, который обрабатывается точно так же, как в Python (-1 последний элемент, -2 предпоследний и т.д.).\nВ качесте индекса тензора могут быть использованы диапазоны которые обработываются точно так же как и в Python, а так же значение :None и многоточие .... Значение :None, т.е. отсуствие индекса, означает произвольный размер тензора в одном конкретном измерении, тогда как многоточие ... обозначет произвольную размерность в любом количестве измерений (поэтому может встречаться в индексе тензора только однократно).\nЛитерал тензор в тексте программы записывается в квадратных скобках с обязательной завершающей запятой, т.е. [1, 2,] — это литерал одномерный тензор из двух чисел. После закрывающей скобки тип тензора может быть указан в явном виде. Если тип не указан, то он выводится автоматически на основании указанных данных и выбирается минимально возможный байтовый размер, который позволяет сохранить все значения без потери точности.\nПримеры создания тензоров и преобразования их размерности можно посмотреть тут.\nРациональные числа Для вычислений с неограниченной точностью в NewLang используются отдельный тип - рациональные числа. Они записываются в форме обыкновенной дроби, в которой числитель должен быть целым числом, а знаменатель натуральным (целым без нуля). В качестве разделителя дроби используется обратная косая черта, т.е. 1\\1 - рациональное число 1, -5\\1 - рациональное числа -5 и т.д.\n","categories":"","description":"","excerpt":"NewLang является языком с динамической типизацией и явное указание …","ref":"/ru/docs/types/numbers/","tags":"","title":"Числа"},{"body":"Блок кода, это сгруппированный набор идущих подряд инструкций, которые выполняются как единое целое с возвращением результата выполнения последней из них. Блок кода, как и любая синтаксическая конструкция языка, должен завершаться точкой с запятой “;”.\nБлоки кода используются для ограничения области видимости переменных. С их помощью определяется иерархия области имен и реализуется система именования свойств и методов для классов. Именованные блоки кода могут выступать в качестве локальных меток для передачи потока выполнения.\nЗа счет того, что к блоку кода можно обратится как к единой инструкции, они могут использоваться в других операторах. Тело функции, также представляет собой блока кода, который располагается в пространстве имен определения этой функции.\nns:: { # Пространство имен ns name { # Пространство имен ns::name # В конце имени \"::\" можно не указывать }; :: { # Глобальное пространство имен ... }; { # Локальная переменная до завершения блока кода $local ::= 0; }; $local; # \u003c-- Ошибка! Локальная переменная не видна }; func_name(val) ::= { # Блок кода func_name:: @if($val) { ... } @else { ... }; }; Оформление блока кода Блок кода всегда начинается и заканчивается на фигурные скобки («{» и «}») и завершается точкой с запятой “;”. Существуют блоки кода, которые перехватывают потоки выполнения, с помощью которых реализуются возврат и обработка ошибок.\nТип возвращаемого значения блоком кода можно указать в явном виде. Для этого, после завершающей фигурной скобки, нужно указать разрешенный тип, после чего компилятор будет проверят корретность данных внутрие блока кода, которые могут быть возвращены.\nМожно указать сразу несколько типов, перечислив их через запятую в угловых скобрах.\n{ op1; op2; }; # \u003c--- Контроль типа возврата не производится { op1; op2; # \u003c--- Проверка типа возвращаемого значения } :Type; # \u003c--- Разрешенный тип { op1; op2; ... }: \u003c:Type1, :Type2, :Type3\u003e; # \u003c--- Несколько разрешенных типов возврата { op1; op2; ... }: \u003c ... \u003e; # \u003c--- Разрешен любой тип возвращаемого значения Расширенный синтаксис Расширенный синтаксис с нативным исходным кодом на языке реализации (С++), это тоже блок кода. Он начинается и заканчивается на фигурные скобки со знаком процента («{%» и «%}»).\nВнутри блока кода с расширенным синтаксисом можно применять произвольные элементы языка реализации (С++), но нужно иметь ввиду, что расширенный синтаксис является исходным текстом программы и напрямую подстваляется и выходной текст трансплайтера во время компиляции файла.\nС помощью блока кода с расширенным синтаксисом можно реализовать разные элементы, которые отсуствуют в основном синтаксисе, например, безусловный переход на заданную метку.\n@@ label $name @@ ::= @@@ {% @$name:; %} @@@; @@ goto $label @@ ::= @@@ {% goto @$label; %} @@@; @goto label_for_goto; # Skip this code @label label_for_goto; Взаимодействие расширенного синтаксиса с основным кодом программы происходит путем обращения к локальным объектам или макросам программы изнутри блока кода. Но для этого, имя объекта должно быть указано полностью, включая все квалификаторы имени.\nЕсли есть необходимость обратится к статическому объекту, его имя нужно заменить макросом, так как символ двоеточия используется в синтаксисе языков C/C++.\nНачиная с версии C++26 взаимодействие с расширенным синтаксисом может быть нарушено!\nAdd the same characters @, $, and ` to the basic character set [C++26] P2558R2\nfactorial := 1000; ::result := 1\\1; /* Rational number */ @@ res @@ ::= ::result; {% // Source on the C++ for( int i=2; i \u003c= static_cast\u003cunsigned int\u003e( $factorial ); i++ ){ @res *= i; } printf(\"\\nFactorial %i! = %s\\n\", static_cast\u003cunsigned int\u003e( $factorial ), static_cast\u003cconst char *\u003e( @res )); # std::cout \u003c\u003c \"Factorial \" \u003c\u003c static_cast\u003cunsigned int\u003e( $factorial ); # std::cout \u003c\u003c \"! = \" \u003c\u003c static_cast\u003cconst char *\u003e( @res ) \u003c\u003c std::endl; %} ","categories":"","description":"","excerpt":"Блок кода, это сгруппированный набор идущих подряд инструкций, которые …","ref":"/docs/ops/block/","tags":"","title":"Блоки кода"},{"body":"Блок кода, это сгруппированный набор идущих подряд инструкций, которые выполняются как единое целое с возвращением результата выполнения последней из них. Блок кода, как и любая синтаксическая конструкция языка, должен завершаться точкой с запятой “;”.\nБлоки кода используются для ограничения области видимости переменных. С их помощью определяется иерархия области имен и реализуется система именования свойств и методов для классов. Именованные блоки кода могут выступать в качестве локальных меток для передачи потока выполнения.\nЗа счет того, что к блоку кода можно обратится как к единой инструкции, они могут использоваться в других операторах. Тело функции, также представляет собой блока кода, который располагается в пространстве имен определения этой функции.\nns:: { # Пространство имен ns name { # Пространство имен ns::name # В конце имени \"::\" можно не указывать }; :: { # Глобальное пространство имен ... }; { # Локальная переменная до завершения блока кода $local ::= 0; }; $local; # \u003c-- Ошибка! Локальная переменная не видна }; func_name(val) ::= { # Блок кода func_name:: @if($val) { ... } @else { ... }; }; Оформление блока кода Блок кода всегда начинается и заканчивается на фигурные скобки («{» и «}») и завершается точкой с запятой “;”. Существуют блоки кода, которые перехватывают потоки выполнения, с помощью которых реализуются возврат и обработка ошибок.\nТип возвращаемого значения блоком кода можно указать в явном виде. Для этого, после завершающей фигурной скобки, нужно указать разрешенный тип, после чего компилятор будет проверят корретность данных внутрие блока кода, которые могут быть возвращены.\nМожно указать сразу несколько типов, перечислив их через запятую в угловых скобрах.\n{ op1; op2; }; # \u003c--- Контроль типа возврата не производится { op1; op2; # \u003c--- Проверка типа возвращаемого значения } :Type; # \u003c--- Разрешенный тип { op1; op2; ... }: \u003c:Type1, :Type2, :Type3\u003e; # \u003c--- Несколько разрешенных типов возврата { op1; op2; ... }: \u003c ... \u003e; # \u003c--- Разрешен любой тип возвращаемого значения Расширенный синтаксис Расширенный синтаксис с нативным исходным кодом на языке реализации (С++), это тоже блок кода. Он начинается и заканчивается на фигурные скобки со знаком процента («{%» и «%}»).\nВнутри блока кода с расширенным синтаксисом можно применять произвольные элементы языка реализации (С++), но нужно иметь ввиду, что расширенный синтаксис является исходным текстом программы и напрямую подстваляется и выходной текст трансплайтера во время компиляции файла.\nС помощью блока кода с расширенным синтаксисом можно реализовать разные элементы, которые отсуствуют в основном синтаксисе, например, безусловный переход на заданную метку.\n@@ label $name @@ ::= @@@ {% @$name:; %} @@@; @@ goto $label @@ ::= @@@ {% goto @$label; %} @@@; @goto label_for_goto; # Skip this code @label label_for_goto; Взаимодействие расширенного синтаксиса с основным кодом программы происходит путем обращения к локальным объектам или макросам программы изнутри блока кода. Но для этого, имя объекта должно быть указано полностью, включая все квалификаторы имени.\nЕсли есть необходимость обратится к статическому объекту, его имя нужно заменить макросом, так как символ двоеточия используется в синтаксисе языков C/C++.\nНачиная с версии C++26 взаимодействие с расширенным синтаксисом может быть нарушено!\nAdd the same characters @, $, and ` to the basic character set [C++26] P2558R2\nfactorial := 1000; ::result := 1\\1; /* Rational number */ @@ res @@ ::= ::result; {% // Source on the C++ for( int i=2; i \u003c= static_cast\u003cunsigned int\u003e( $factorial ); i++ ){ @res *= i; } printf(\"\\nFactorial %i! = %s\\n\", static_cast\u003cunsigned int\u003e( $factorial ), static_cast\u003cconst char *\u003e( @res )); # std::cout \u003c\u003c \"Factorial \" \u003c\u003c static_cast\u003cunsigned int\u003e( $factorial ); # std::cout \u003c\u003c \"! = \" \u003c\u003c static_cast\u003cconst char *\u003e( @res ) \u003c\u003c std::endl; %} ","categories":"","description":"","excerpt":"Блок кода, это сгруппированный набор идущих подряд инструкций, которые …","ref":"/ru/docs/ops/block/","tags":"","title":"Блоки кода"},{"body":"","categories":"","description":"","excerpt":"","ref":"/blog/","tags":"","title":"Articles"},{"body":"NewLang supports two types of strings:\n:StrChar - universal byte UTF-8 strings :StrWide - system character (wide characters) The single element of a universal UTF-8 string is one byte, while the single element of a system character string is a wide character wchar_t. And although the strings differ in the types of single string elements, the internal representation of both types of strings is the same. All data of character strings is stored as a universal byte UTF-8 sequence.\nByte Strings :StrChar The basic element of a universal byte string is one byte (specifically :Int8, i.e. an 8-bit signed integer). The number of characters in a byte string is returned in bytes, and accessing a string element by index is done by the byte of the character sequence.\nSince these strings are interpreted as a sequence of UTF-8 characters, caution must be taken when modifying individual bytes!\nSystem Strings :StrWide The individual element of the system string is a wide character wchar_t, and the number of elements in the system character string is returned in wide characters. The size of the wchar_t type depends on the operating system, so the size of one character :StrWide in Windows will be 2 bytes, and in Linux 4 bytes, which is related to their implementation specifics.\nThe main purpose of system strings is to simplify working in a text terminal, as one character always corresponds to one character cell without the need for constant conversion of UTF-8 code points.\nString Formatting Any variable can be accessed as a function (by specifying parentheses after its name) to create a copy/clone of the object, and for strings, this operation can be used as a template for formatting data.\nString formatting can be done in two ways:\nSpecify a format string with the types of data to be output (the format string corresponds to formatting in the standard printf function). To apply this formatting variant, the format string must specify the corresponding data type (: FmtChar or : FmtWide for regular and wide characters, respectively).\nWith this formatting method, named arguments cannot be used, and the compiler checks the types of the passed values for compliance with the format string only during compilation of the program text. This type of format string can be used as the last argument of a function to check the types of all subsequent arguments for compliance with the format string.\nIn all other cases, any strings and named arguments can be used as the format string, and the format itself corresponds to the format string from the {fmt} library. The only difference is the ability to specify not only the positional number of the argument, but also its name. Argument validation against the format string is performed during string cloning both at compile time and during program execution.\nThe formatting method is used by default for any type of string, but the format string is not checked in the function arguments.\nFor example:\n$fmt := '%s: %d':FmtChar; # Formatting like in printf $result := $fmt('value', 123); # \"value: 123\" - Check compile time only! $template := \"{name} {0}\"; # fmt::format equivalent \"{1} {0}\" $result := $template(\"template\", name = \"String\"); # result = \"String template\" ","categories":"","description":"","excerpt":"NewLang supports two types of strings:\n:StrChar - universal byte UTF-8 …","ref":"/docs/types/strings/","tags":"","title":"Character Strings"},{"body":" The materials are in the process of being translated into English!\nBasic materials on the NewLang programming language.\nThe description is valid for the current version 0.4\n","categories":"","description":"","excerpt":" The materials are in the process of being translated into English! …","ref":"/docs/","tags":"","title":"Documentation"},{"body":"NewLang supports namespaces, where the separator, like in C++, is a double colon “::”.\nA namespace can be specified for an individual identifier or for an entire code block.\nUnlike namespace in C++, namespaces in NewLang are used not only to organize code into logical groups and avoid name conflicts, but also to associate an identifier, explicitly specifying the namespace, with static objects (memory allocated during the compilation stage of the program).\nThe global name cannot be overridden by a macro or local variable during name lookup. To create a global (static) variable in the current namespace, you can specify the variable with the @:: preprocessor.\nTo use a namespace in a code block, it must be specified before the opening curly brace. In such a named code block, it is not necessary to specify the closing “::”.\n::var ::= 0; # Name of global variable explicitly (cannot be overridden) ns { # Equivalent to ns:: var ::= 0; # Name ns::var (can be overridden by macro or local variable) @::var ::= 0; # Name of global variable ::ns::var (cannot be overridden) name:: { var = 0; # Reference to variable ns::var var2 ::= 0; # Name of variable will be ns::name::var2 ::var = 1; # Variable from global namespace }; :: { # Global namespace var = 1; # Name of global variable ::var (can be overridden) ::ns::var = 0; # Name of another global variable (cannot be overridden) }; }; Namespaces, Modules, and Packages The namespace in NewLang supports both a modular code structure like in Java and Python languages, and when specifying the full name of an object, program modules and namespaces can be combined.\nFor example, the full name of a variable can be written with the indication of the program module \\root\\dir\\module::ns::name::var, where root and dir are directories in the file system relative to the current module, and module is the file name, i.e. root/dir/module.src.\nNamespace and OOP In NewLang, name decoration (mangling) based on function argument types is not used.\nHowever, when creating unique identifiers for class methods, NewLang uses an approach similar to that used in the Python language. When creating a class method, a global function is created with the class name and method name combined with the separator “::”.\nFor example, for the class :NewClass, when creating the method method, a function named NewClass::method will be created.\nThis method naming scheme fully corresponds to the naming of functions in the namespace, allowing class methods to be defined outside the body of the class simply by specifying the desired name in the namespace or explicitly.\nExample of creating a method of the class NewClass in the namespace:\nNewClass:: { method() := { }; } Example of creating a method of the class NewClass with specifying the full name:\nNewClass::method() := { }; ","categories":"","description":"","excerpt":"NewLang supports namespaces, where the separator, like in C++, is a …","ref":"/docs/syntax/namespace/","tags":"","title":"Namespaces"},{"body":"Именование объектов основано на правилах и выбирается из расчёта удобства для программиста. Название переменной или функции должно нести смысл, понятные параметры и тип возвращаемого значения, которые упрощают понимание алгоритма при последующем чтении исходного текста программы.\nНо обычные имена мало о чём говорят компьютеру. Поэтому при компиляции программы, имена объектов преобразуются для удобства машинной обработки и к ним добавляется служебная информация.\nВнутреннее имя объекта Каждый объект имеет свое внутреннее имя, уникальное в рамках текущего модуля, с помощью которого комипилятор языка однозначно связывает объект с данными в памяти компьютера.\nВнутреннее имя формируется во время анализа синтаксического дерева программы. Оно включает в себя имя объекта, его квалификатор и полное пространство имен, в котором объект был опеределен.\nУ статических объектов (типов и классов), внутренее имя соотвествует полному имени объекта с учетом всех областей имен, тогда как внутреннее имя автоматичеких объектов включает в себя и пустые (не именованные) блоки кода, которые заменяются на монотонно возрастающий порядковый номер блока (т.е. ::1::, ::2:: и т.д.). Включение в пространство имен пустых блоков кода необходимо для реализации возможности перекрытия имен у объектов, определенных в разных областях видимости.\nКроме этого, все квалификаторы объектов переносятся в конец имени, что и является отличительным признаком внутреннего имени (последний символ должен быть “$” или “:”).\nПримеры внутренних имен:\n# Глобальный статический объект ::var ::= 0; # ::var:: # Локальный объект модуля $var := 0; # var$ # Статический объект модуля @::var ::= 0; # var:: # Глобальные тип и конструктор класса :: :type := :Type; # ::type::: :: :cls := Class(){}; # ::cls::: # Синоним типа или конструктор класса модуля :type := :Type; # type::: :cls := Class(){}; # cls::: # Тип или конструктор класса всегда статические @:: :type := :Type; # type::: @:: :cls := Class(){}; # cls::: ns { $var := 0; # ns::var$ var ::= 0; # ns::var$ @::var ::= 0; # ns::var:: - статический объект :type := :Type; # ns::type::: :cls := Class(){}; # ns::cls::: @::func1() ::= {}; # ns::func1:: func2() ::= {}; # ns::func2:: # Не именованный блок кода { # Локальные имена перекрывают объявления выше $var := 0; # ns::1::var$ var := 0; # ns::1::var$ # Статический объект соответствует области имен @::var ::= 0; # ns::var:: # Типы данных всегда статические :type := :Type; # ns::type::: :cls := Class(){}; # ns::cls::: @::func3() := {}; # ns::func3:: # Локальная функция с ограниченной областью видимости ????? func4() := {}; # ns::1::func4$ } }; # Не именованный блок кода { $var := 0; # 2::var$ var ::= 0; # 2::var$ @::var = 0; # var:: - статический объект :type := :Type; # type::: :cls := Class(){}; # cls::: }; Манглинг внутренних имен Внутреннее имя уникально только в рамках одного модуля, но внутренние имена в разных модулях могут пересекаться.\nМанглинг внутренних имя предназначен для объединения нескольких модулей в рамках одной программы, и используется как способ кодирования имени функции, структуры, класса или другого типа данных при передачи дополнительной семантической информации от компилятора компоновщику.\nВнутреннее имя объекта после манглинга является корректным идентификатором для языков C/C++, что позволяет обращатся к объектам NewLang из внешних библиотек и приложений на языке реализации (C/C++) по семантически похожему имени (в отличии от манглинга имен в С++).\nМанглинг внутреннего имени заключается в замене каждого символа двоеточия на символ $, а у имени типа квалификатор заменяется тремя символами ‘$’, т.е. ’type $$$’.\nПри манглинге, к внутренним именам объектов добавляется специальный префикс, который кодирует имя компилируемого модуля. Имя текущего модуля находится в переменной препроцессора \"@$$\" и по умолчанию, содержит имя файла модуля (у главного модуля приложения имя модуля отсутствует).\nИмя модуля может быть однократно переопределено самым первым оператором модуля или заменено во время импорта модуля с помощью системного параметра __package__.\n# Задать имя модуля @$$ = \"\\dir\\file\"; # Импорт модуля с переопределением имени \\dir\\file(__package__=\"\\new\\module\\name\"); Тоже само с использвоанием DSL:\n@package \\dir\\name; # @$$ = \"\\dir\\file\"; @import \\dir\\name as \\new\\module\\name; # \\dir\\file(__package__=\"\\new\\module\\name\"); При манглинге имя модуля, по умолчанию имя файла отностительно каталога главного файла программы, размещается в начале внутреннего системного имени. Так как имя модуля, согласно правилам синтаксиса, может содерждать только строчные буквы и цифры, то разделитель каталогов (обратный слеш) заменяется на подчерк, а начало и конец имени модуля отмечаются комбинациями символов “_$” и “$_” соответственно.\nТак как локальной переменной с одним подчерком в качестве имени быть не может, то начало строки на “_$” служит отличительным признаком манглинга внутреннего имени объекта.\n@$$ = \"\\dir\\file\"; # Глобальный статический объект ::var ::= 0; # _$dir_file$_$$var$$ # Локальный объект модуля $var := 0; # _$dir_file$_var$ # Статический объект модуля @::var ::= 0; # _$dir_file$_var$$ # Глобальные тип и конструктор класса :: :type := :Type; # _$dir_file$_$$type$$$ :: :cls := Class(){}; # _$dir_file$_$$cls$$$ # Синоним типа или конструктор класса модуля :type := :Type; # _$dir_file$_type$$$ :cls := Class(){}; # _$dir_file$_cls$$$ ns { $var := 0; # _$dir_file$_ns$$var$ var ::= 0; # _$dir_file$_ns$$var$ @::var ::= 0; # _$dir_file$_ns$$var$$ - статический объект :type := :Type; # _$dir_file$_ns$$type$$$ :cls := Class(){}; # _$dir_file$_ns$$cls$$$ @::func() ::= {}; # _$dir_file$_ns$$func$$ func() ::= {}; # _$dir_file$_ns$$func$ # Не именованный блок кода { # Локальные имена перекрывают обяъявления выше $var := 0; # _$dir_file$_ns$$1$$var$ var := 0; # _$dir_file$_ns$$1$$var$ # Статический объект соответствует области имен @::var ::= 0; # _$dir_file$_ns$$var$$ # Типы данных и функции всегда статические :type := :Type; # _$dir_file$_ns$$type$$$ :cls := Class(){}; # _$dir_file$_ns$$cls$$$ @::func() := {}; # _$dir_file$_ns$$func$$ func() := {}; # _$dir_file$_ns$$1$$func$ ???????? } }; # Не именованный блок кода { $var := 0; # _$dir_file$_2::var$ var ::= 0; # _$dir_file$_2::var$ @::var = 0; # _$dir_file$_var$$ - статический объект :type := :Type; # _$dir_file$_type$$$ :cls := Class(){}; # _$dir_file$_cls$$$ }; Манглинг имен блока кода главного модуля программы:\n{ $var := 0; # _$$_1::var$ var ::= 0; # _$$_1::var$ @::var = 0; # _$$_var$$ - статический объект :type := :Type; # _$$_type$$$ :cls := Class(){}; # _$$_cls$$$ }; Встроенный блок кода и вызов функций В расширенном синатксисе с исходным кодом языка реализации можно взаимодействовать с другим кодом программы за счет обращения к локальным объектам или макросам изнутри блока кода.\nЭто досупкается как для обычных переменных, так и для имен функций, реализованных в NewLang, и для того, что бы компилятор C/C++ имел возможность создать правильный код, при раскрытии встроенного блока кода перед ним добавляются сигнатуры переменных и функций, которые используются во строенном блоке кода.\nДля имен переменных дополнительный манглинг имен не производится, а для функций автоматичсеки создается дополнительная сигнатура с описанием типов аргументов и их значений по умолчанию, если таковые используются.\nКаждая функция NewLang имеет две сигнатуры, первая (основная) принимает все аргументы в виде словаря, а вторая (дополнительная) с развернутым списком аргументов, чтобы её можно было вызывать как обычную C++ функцию и проверка типов могла происходить С/С++ непосредственно компилятором.\nМанглинг второго (дополнительного) имени функции заключается в добавлении в конец имени двух символов “_$”.\n# Определение функции в NewLang ::func_embed(int64_t arg_long, uint8_t arg_byte = 10): Int64 ::= { @return arg_long + arg_byte; } # С/С++ прототип для первого (основоного) имени # extern \"C\" _$$_func_embed$( Obj \u0026args ); # С/С++ прототип для второго (дополнительного) имени # extern \"C\" _$$_func_embed$_$(int64_t arg_long, uint8_t arg_byte = 10); # Тогда при раскрытии блока с расширенным синтаксисом # $func_embed заменяется на _$$_func_embed$_$, а компилятор С/С++ # будет в состоянии проверить её аргументы {% int64_t value = $func_embed(10, 20); %} Хотя может имеет смысл сделать inline шаблон для подобного вызова, а не создавать кополнительное имя?\n./object.h:732:25: error: deduced conflicting types ('int' vs 'const char *') for initializer list element type auto list = {args...}; ^~~~~ test/object_test.cpp:131:21: note: in instantiation of function template specialization 'newlang::Obj::operator()\u003cint, const char *\u003e' requested here str3 = (*format)(-1, \"222\"); ^ ","categories":"","description":"","excerpt":"Именование объектов основано на правилах и выбирается из расчёта …","ref":"/docs/arch/mangling/","tags":"","title":"Внутреннее имя и манглинг имен"},{"body":"Именование объектов основано на правилах и выбирается из расчёта удобства для программиста. Название переменной или функции должно нести смысл, понятные параметры и тип возвращаемого значения, которые упрощают понимание алгоритма при последующем чтении исходного текста программы.\nНо обычные имена мало о чём говорят компьютеру. Поэтому при компиляции программы, имена объектов преобразуются для удобства машинной обработки и к ним добавляется служебная информация.\nВнутреннее имя объекта Каждый объект имеет свое внутреннее имя, уникальное в рамках текущего модуля, с помощью которого комипилятор языка однозначно связывает объект с данными в памяти компьютера.\nВнутреннее имя формируется во время анализа синтаксического дерева программы. Оно включает в себя имя объекта, его квалификатор и полное пространство имен, в котором объект был опеределен.\nУ статических объектов (типов и классов), внутренее имя соотвествует полному имени объекта с учетом всех областей имен, тогда как внутреннее имя автоматичеких объектов включает в себя и пустые (не именованные) блоки кода, которые заменяются на монотонно возрастающий порядковый номер блока (т.е. ::1::, ::2:: и т.д.). Включение в пространство имен пустых блоков кода необходимо для реализации возможности перекрытия имен у объектов, определенных в разных областях видимости.\nКроме этого, все квалификаторы объектов переносятся в конец имени, что и является отличительным признаком внутреннего имени (последний символ должен быть “$” или “:”).\nПримеры внутренних имен:\n# Глобальный статический объект ::var ::= 0; # ::var:: # Локальный объект модуля $var := 0; # var$ # Статический объект модуля @::var ::= 0; # var:: # Глобальные тип и конструктор класса :: :type := :Type; # ::type::: :: :cls := Class(){}; # ::cls::: # Синоним типа или конструктор класса модуля :type := :Type; # type::: :cls := Class(){}; # cls::: # Тип или конструктор класса всегда статические @:: :type := :Type; # type::: @:: :cls := Class(){}; # cls::: ns { $var := 0; # ns::var$ var ::= 0; # ns::var$ @::var ::= 0; # ns::var:: - статический объект :type := :Type; # ns::type::: :cls := Class(){}; # ns::cls::: @::func1() ::= {}; # ns::func1:: func2() ::= {}; # ns::func2:: # Не именованный блок кода { # Локальные имена перекрывают объявления выше $var := 0; # ns::1::var$ var := 0; # ns::1::var$ # Статический объект соответствует области имен @::var ::= 0; # ns::var:: # Типы данных всегда статические :type := :Type; # ns::type::: :cls := Class(){}; # ns::cls::: @::func3() := {}; # ns::func3:: # Локальная функция с ограниченной областью видимости ????? func4() := {}; # ns::1::func4$ } }; # Не именованный блок кода { $var := 0; # 2::var$ var ::= 0; # 2::var$ @::var = 0; # var:: - статический объект :type := :Type; # type::: :cls := Class(){}; # cls::: }; Манглинг внутренних имен Внутреннее имя уникально только в рамках одного модуля, но внутренние имена в разных модулях могут пересекаться.\nМанглинг внутренних имя предназначен для объединения нескольких модулей в рамках одной программы, и используется как способ кодирования имени функции, структуры, класса или другого типа данных при передачи дополнительной семантической информации от компилятора компоновщику.\nВнутреннее имя объекта после манглинга является корректным идентификатором для языков C/C++, что позволяет обращатся к объектам NewLang из внешних библиотек и приложений на языке реализации (C/C++) по семантически похожему имени (в отличии от манглинга имен в С++).\nМанглинг внутреннего имени заключается в замене каждого символа двоеточия на символ $, а у имени типа квалификатор заменяется тремя символами ‘$’, т.е. ’type $$$’.\nПри манглинге, к внутренним именам объектов добавляется специальный префикс, который кодирует имя компилируемого модуля. Имя текущего модуля находится в переменной препроцессора \"@$$\" и по умолчанию, содержит имя файла модуля (у главного модуля приложения имя модуля отсутствует).\nИмя модуля может быть однократно переопределено самым первым оператором модуля или заменено во время импорта модуля с помощью системного параметра __package__.\n# Задать имя модуля @$$ = \"\\dir\\file\"; # Импорт модуля с переопределением имени \\dir\\file(__package__=\"\\new\\module\\name\"); Тоже само с использвоанием DSL:\n@package \\dir\\name; # @$$ = \"\\dir\\file\"; @import \\dir\\name as \\new\\module\\name; # \\dir\\file(__package__=\"\\new\\module\\name\"); При манглинге имя модуля, по умолчанию имя файла отностительно каталога главного файла программы, размещается в начале внутреннего системного имени. Так как имя модуля, согласно правилам синтаксиса, может содерждать только строчные буквы и цифры, то разделитель каталогов (обратный слеш) заменяется на подчерк, а начало и конец имени модуля отмечаются комбинациями символов “_$” и “$_” соответственно.\nТак как локальной переменной с одним подчерком в качестве имени быть не может, то начало строки на “_$” служит отличительным признаком манглинга внутреннего имени объекта.\n@$$ = \"\\dir\\file\"; # Глобальный статический объект ::var ::= 0; # _$dir_file$_$$var$$ # Локальный объект модуля $var := 0; # _$dir_file$_var$ # Статический объект модуля @::var ::= 0; # _$dir_file$_var$$ # Глобальные тип и конструктор класса :: :type := :Type; # _$dir_file$_$$type$$$ :: :cls := Class(){}; # _$dir_file$_$$cls$$$ # Синоним типа или конструктор класса модуля :type := :Type; # _$dir_file$_type$$$ :cls := Class(){}; # _$dir_file$_cls$$$ ns { $var := 0; # _$dir_file$_ns$$var$ var ::= 0; # _$dir_file$_ns$$var$ @::var ::= 0; # _$dir_file$_ns$$var$$ - статический объект :type := :Type; # _$dir_file$_ns$$type$$$ :cls := Class(){}; # _$dir_file$_ns$$cls$$$ @::func() ::= {}; # _$dir_file$_ns$$func$$ func() ::= {}; # _$dir_file$_ns$$func$ # Не именованный блок кода { # Локальные имена перекрывают обяъявления выше $var := 0; # _$dir_file$_ns$$1$$var$ var := 0; # _$dir_file$_ns$$1$$var$ # Статический объект соответствует области имен @::var ::= 0; # _$dir_file$_ns$$var$$ # Типы данных и функции всегда статические :type := :Type; # _$dir_file$_ns$$type$$$ :cls := Class(){}; # _$dir_file$_ns$$cls$$$ @::func() := {}; # _$dir_file$_ns$$func$$ func() := {}; # _$dir_file$_ns$$1$$func$ ???????? } }; # Не именованный блок кода { $var := 0; # _$dir_file$_2::var$ var ::= 0; # _$dir_file$_2::var$ @::var = 0; # _$dir_file$_var$$ - статический объект :type := :Type; # _$dir_file$_type$$$ :cls := Class(){}; # _$dir_file$_cls$$$ }; Манглинг имен блока кода главного модуля программы:\n{ $var := 0; # _$$_1::var$ var ::= 0; # _$$_1::var$ @::var = 0; # _$$_var$$ - статический объект :type := :Type; # _$$_type$$$ :cls := Class(){}; # _$$_cls$$$ }; Встроенный блок кода и вызов функций В расширенном синатксисе с исходным кодом языка реализации можно взаимодействовать с другим кодом программы за счет обращения к локальным объектам или макросам изнутри блока кода.\nЭто досупкается как для обычных переменных, так и для имен функций, реализованных в NewLang, и для того, что бы компилятор C/C++ имел возможность создать правильный код, при раскрытии встроенного блока кода перед ним добавляются сигнатуры переменных и функций, которые используются во строенном блоке кода.\nДля имен переменных дополнительный манглинг имен не производится, а для функций автоматичсеки создается дополнительная сигнатура с описанием типов аргументов и их значений по умолчанию, если таковые используются.\nКаждая функция NewLang имеет две сигнатуры, первая (основная) принимает все аргументы в виде словаря, а вторая (дополнительная) с развернутым списком аргументов, чтобы её можно было вызывать как обычную C++ функцию и проверка типов могла происходить С/С++ непосредственно компилятором.\nМанглинг второго (дополнительного) имени функции заключается в добавлении в конец имени двух символов “_$”.\n# Определение функции в NewLang ::func_embed(int64_t arg_long, uint8_t arg_byte = 10): Int64 ::= { @return arg_long + arg_byte; } # С/С++ прототип для первого (основоного) имени # extern \"C\" _$$_func_embed$( Obj \u0026args ); # С/С++ прототип для второго (дополнительного) имени # extern \"C\" _$$_func_embed$_$(int64_t arg_long, uint8_t arg_byte = 10); # Тогда при раскрытии блока с расширенным синтаксисом # $func_embed заменяется на _$$_func_embed$_$, а компилятор С/С++ # будет в состоянии проверить её аргументы {% int64_t value = $func_embed(10, 20); %} Хотя может имеет смысл сделать inline шаблон для подобного вызова, а не создавать кополнительное имя?\n./object.h:732:25: error: deduced conflicting types ('int' vs 'const char *') for initializer list element type auto list = {args...}; ^~~~~ test/object_test.cpp:131:21: note: in instantiation of function template specialization 'newlang::Obj::operator()\u003cint, const char *\u003e' requested here str3 = (*format)(-1, \"222\"); ^ ","categories":"","description":"","excerpt":"Именование объектов основано на правилах и выбирается из расчёта …","ref":"/ru/docs/arch/mangling/","tags":"","title":"Внутреннее имя и манглинг имен"},{"body":"Основные материалы по языку программирования NewLang.\nОписание акутально для текущей версии 4.0\n","categories":"","description":"","excerpt":"Основные материалы по языку программирования NewLang.\nОписание …","ref":"/ru/docs/","tags":"","title":"Документация"},{"body":"Все математические операторы имеют парный аналог с присвоением значения:\n+ и += — сложение арифметических типов данных; - и -= — вычитание арифметических типов данных; / и /= — деление (результат число с плавающей точкой); // и //= — целочисленное деление с округлением к меньшему числу (как в Python); * и *= — умножение (он же используется и для повторения текстовых строк); % и %= — остаток от целочисленного деления; Отдельный оператор для возведения в степень отсуствует.\nОператоры двоичного сдвига *) пока не реализованы .\u003c. - Битовый сдвиг влево .\u003e. - Битовый сдвиг вправо .\u003e\u003e. - Битовый сдвиг вправо с заполнением знакового бита .\u0026. - Битовый оператор И .|. - Битовый оператор ИЛИ .^. - Битовый оператор ИСКЛЮЧАЮЩЕЕ ИЛИ .~. - Битовый унарный оператор НЕ (инверсии) ","categories":"","description":"","excerpt":"Все математические операторы имеют парный аналог с присвоением …","ref":"/docs/ops/math/","tags":"","title":"Математические операторы"},{"body":"Все математические операторы имеют парный аналог с присвоением значения:\n+ и += — сложение арифметических типов данных; - и -= — вычитание арифметических типов данных; / и /= — деление (результат число с плавающей точкой); // и //= — целочисленное деление с округлением к меньшему числу (как в Python); * и *= — умножение (он же используется и для повторения текстовых строк); % и %= — остаток от целочисленного деления; Отдельный оператор для возведения в степень отсуствует.\nОператоры двоичного сдвига *) пока не реализованы .\u003c. - Битовый сдвиг влево .\u003e. - Битовый сдвиг вправо .\u003e\u003e. - Битовый сдвиг вправо с заполнением знакового бита .\u0026. - Битовый оператор И .|. - Битовый оператор ИЛИ .^. - Битовый оператор ИСКЛЮЧАЮЩЕЕ ИЛИ .~. - Битовый унарный оператор НЕ (инверсии) ","categories":"","description":"","excerpt":"Все математические операторы имеют парный аналог с присвоением …","ref":"/ru/docs/ops/math/","tags":"","title":"Математические операторы"},{"body":"NewLang поддерживает пространства имен, разделителем в которых, как и в С++, выступает двойное двоеточие “::”.\nОбласть имен может быть указана как для отдельного индетификатора, так и для целого блока кода.\nВ отличии от namespace в С++, области имен в NewLnag используются не только для организации кода в виде логических групп и с целью избежания конфликтов имен, но и для отнесения идентификатора, в котором явно указана область имен, к статическим объектам (память под которые выделяется на этапе комиляции программы).\nГлобальное имя не может быть перекрыто макросом или локальной переменной при разрешении имен (name lookup). Создать глобальную (статическую) переменную в текущем пространстве имен можно указав переменную препроцессора @::.\nДля использования пространства имен в блоке кода, его нужно указать перед открывающейся фигурной скобкой. В таком именованном блоке кода завершающие “::” указывать не обязательно.\n::var ::= 0; # Имя глобальной переменной в явном виде (не может быть перекрыто) ns { # Можно указать равнозначное ns:: var ::= 0; # Имя ns::var (может быть перекрыто макросом или локальной переменной) @::var ::= 0; # Имя глобальной переменной ::ns::var (не может быть перекрыто) name:: { var = 0; # Обращение к переменной ns::var var2 ::= 0; # Имя переменной будет ns::name::var2 ::var = 1; # Переменная из глобального пространства имен }; :: { # Глобальное пространство имен var = 1; # Имя глобальной переменной ::var (может быть перекрыто) ::ns::var = 0; # Имя другой глобальной переменной (не может быть перекрыто) }; }; Пространство имен, модули и пакеты Пространство имен в NewLang поддерживает одновременно с модульной структурой кода как в языках Java и Python и при указании полного имени объекта, программные модули и пространства имен можно объединять.\nНапример, полное имя переменой можно записать с указанием программного модуля \\root\\dir\\module::ns::name::var, где root и dir это каталоги в файловой системе относительно текущего модуля, а module — имя файла, т.е. root/dir/module.nlp.\nПространство имен и ООП В NewLang не применяется декорирование (манглинг) имен, основанный на типах аргументов функций.\nТем не менее при создания уникальных идентификаторов для методов классов NewLang использует подход, похожий на применяемый в языке Python. При создании метода класса создается глобальная функция с именем класса и именем метода, объединенные через разделитель “::”.\nНапример, для класса :NewClass при создании метода method будет создана функция с именем NewClass::method.\nТакая схема наименований методов полностью соответствует именованию функций в пространстве имен, и тем самым позволяет определять методы класса вне тела самого класса, просто указав нужное имя в пространстве имен или в явном виде.\nПример создания метода класса NewClass в области имен:\nNewClass:: { method() := { }; } Пример создания метода класса NewClass с указанием полного имени:\nNewClass::method() := { }; ","categories":"","description":"","excerpt":"NewLang поддерживает пространства имен, разделителем в которых, как и …","ref":"/ru/docs/syntax/namespace/","tags":"","title":"Пространства имен"},{"body":"Символьные строки NewLang поддерживает два типа строк:\n:StrChar - универсальные байтовые UTF-8 строки :StrWide - системные символьные (широкие символы) Единичным элементом универсальной UTF-8 строки является один байт, тогда как у системных символьных строк единичным элементом строки является широкий символ wchar_t.\nИ хотя строки различаются типами единичного элемента строки, но внутреннее представление у обоих типов строк одинаковое. Все данные символьных строки хранятся в виде универсальной байтовой UTF-8 последовательности.\nБайтовые строки :StrChar Единичным элементом универсальной байтовой строки является один байт (точнее :Int8, т.е. 8-ми битное целое число со знаком). Количество символов байтовой строки возвращается в байтах и обращение к элементу строки по индексу происходит к байту символьной последовательности. Так как данные строки интерпретируется как последовательность UTF-8 символов, нужно соблюдать осторожность при изменении отдельных байт!\nСистемные строки :StrWide Единичным элементом системной строки является широкий символ wchar_t, а количество элементов системной символьной строки возвращается в широких символах. Размер типа wchar_t зависит от операционной системы, поэтому размер одного символа :StrWide в Windows будет 2 байта, а в Linux 4 байта, что связано с их особенностями реализации.\nОсновоне назначение системных строк - упрощение работы в текстовом терминале, так как один символ всегда соответствует одному знакоместу без необходимости постоянного конвертирования кодовых точек UTF-8.\nФорматирование строк К любой переменной можно обратиться как к функции (указав после её имени круглые скобки) для создания копии/клона объекта, а для строк, такую операцию можно использовать как шаблон при форматировании данных.\nФорматирование строк можно сделать двумая способами:\nЗадать строку формата с указанием типов выводимых данных (строка формата соотвествует форматированию в стандартной функции printf). Для применения такого варината форматирования у строки формата необходимо указать соответствующий тип данных (:FmtChar или :FmtWide для обычных и широких символов соответствено).\nПри таком способе форматирования, именнованные аргументы использовать нельзя, а компилятор проверяет типы передаваемых значений на соответствие строке формата только во время компиляции текста программы.\nДанный тип форматной строки можно использовать как последний аргумент функции для проверки типов всех последующих аргументов на соотвестие строки формата.\nВо всех остальных случаях в качестве строки формата можно использовать любые строки и именованные аргументы, а сам формат соотвествует строке формата из библиотеки {fmt}.\nЕдинствено отличие заключается в возможности указания не только порядкового номера аргумента, но и его имени.\nПроверка аргументов на соответствие строки формата производится во время клонирования строки как во время компиляции, так и во время выполняения программы.\nДанный способ форматирования используется по умолчанию для любых типов строк, но проверка строки формата не выполняется в аргументах функции.\nНапример:\n$fmt := '%s: %d':FmtChar; # Форматирование как в printf $result := $fmt('value', 123); # \"value: 123\" - Check compile time only! $template := \"{name} {0}\"; # fmt::format equivalent \"{1} {0}\" $result := $template(\"шаблон\", name = \"Строка\"); # result = \"Строка шаблон\" ","categories":"","description":"","excerpt":"Символьные строки NewLang поддерживает два типа строк:\n:StrChar - …","ref":"/ru/docs/types/strings/","tags":["типы данных","строки"],"title":"Символьные строки"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/blog/","tags":"","title":"Статьи"},{"body":" Select an exmaple... Hello, world! Rational numbers without limitation of precision Factorial 40 Factorial 40 with DSL syntax Tensor example Playground run 0% Playground version: Output: ","categories":"","description":"","excerpt":" Select an exmaple... Hello, world! Rational numbers without …","ref":"/playground/","tags":"","title":"Playground and example code"},{"body":" Select an exmaple... Hello, world! Rational numbers without limitation of precision Factorial 40 Factorial 40 with DSL syntax Tensor example Playground run 0% Playground version: Output: ","categories":"","description":"","excerpt":" Select an exmaple... Hello, world! Rational numbers without …","ref":"/ru/playground/","tags":"","title":"Playground and example code"},{"body":"В NewLang реализована концепция программных модулей и пакетов - которая повторяет идею иерархического расположения файлов в каталогах файловой системы, примерно так же, как это сделано в языке Python, но разделителем имен выступает не точка, а символ “\\” (как разделитель каталогов в Windows).\nИмя модуля может содержать только строчные английские буквы или цифры. Данное ограничение связано с прямым отображением имен модулей на объекты в файловой системе, так как у разных файловых систем могут быть различные возможности с поддержкой кодировок и разные требования к преобразованию регистров символов.\nПод модулем в NewLang понимается файл исходным кодом (с расширением *.src). Модули предназначены для того, чтобы в них хранить часто используемые функции, классы, константы и т.п. Их можно условно разделить на модули и программы: программы предназначены для непосредственного запуска, а модули для импортирования их в другие программы, но функционально модули и программы ничем между собой не отличаются.\nОбъекты модуля Все объекты, определенные внутри одного модуля без указания глобального простанства имен, видны только в рамках текущего файла.\nВремя жизни статической и локальной переменных модуля одинаковые, и ограничены временм жизни самого модуля, но статическая и локальная переменные модуля отличаются с точки зрения многопоточности.\nСтатическая переменная модуля всегда будет в единственном экземпляре для всех потоков, тогда как локальная переменная модуля будет для каждого потока своя (аналог thread_local (C++11)).\nКак импортировать модули? Относительное имя программного модуля начинается на символ “\\”, и в этом случае расположение файла программного модуля указывается относительно текущего файла.\nАбсолютное имя программного модуля начинается на два символа “\\\\” и указывает на файл модуля относительно каталога текущего исполняемого файла (или в списке каталогов для поиска программных модулей, который можно переопределить, например, с помощью аргументов командной строки).\nПолное имя текущего модуля (файла) содержится в переменной препроцессора ‘@\\\\’.\nСамый простой способ импортировать модуль, это записать его имя со скобками как при вызове функции. Причем в скобках можно передать аргументы для инициализации модуля, список импортируемых функций и т.д.\nТак как NewLang разрабатывается как компилируемый язык, то загрузка модулей возможна как статически, так и динамически (очень похоже на статическую и динамическую ликновку с dll библиотеками).\n\\dir\\module() - статическая загрузка модуля по относительному пути \\\\root\\dir\\module() - статическая загрузка модуля по абсолютному пути \\\\(\"каталог\\файл\") - динамическая загрузка модуля во время выполнения программы При динамической линковке, компиляция исходного кода модуля и все проверки будут выполнятся только во время выполнения приложения, тогда как статическая загрузка модуля позволяет выявить возможные ошибки еще на этапе компиляции программы.\nПо умолчанию, при статической линковке модуля, импортируются все его макросы, функции и переменные модуля, тогда как при динамической загрузке моуля, макросы не импортируются. ?????????????????????????????????????????????????????????????\nЧто такое пакет в NewLang? Пакет в NewLang – это имя каталога, который включает в себя другие каталоги и модули и при этом содержит дополнительный файл __init__.src.\nПакеты используются как дополнение к пространству имен, что позволяет работать с модулями через указание уровня вложенности (через символ \\). Но в отличии от Python и Java, где модули и пакеты заменяют собой пространство имен (namespace), в NewLang модульная структура и области имен используются одновременно и при указании полного имени объекта, программные модули и пространства имен можно объединять.\nНапример, полное имя переменой можно записать с указанием программного модуля \\root\\dir\\module::ns::name::var, где root и dir это каталоги в файловой системе относительно текущего моделя, а module — имя файла, т.е. root/dir/module.src\nДля импортирования пакетов используется тот же синтаксис, что и для работы с модулями.\nИспользование пакетов Рассмотрим следующую структуру пакета:\nfincalc |-- __init__.src |-- simper.src |-- compper.src |-- annuity.src Пакет fincalc содержит в себе модули для работы с простыми процентами (simper.src), сложными процентами (compper.src) и аннуитетами (annuity.src). Файл __init__.src в отличии от Python, не может быть пустым, а должен в явном виде содержать команды загрузки модулей, входящих в пакет\nНапример для нашего случая содержимое __init__.src может быть вот таким:\n\\simper(); \\compper(); \\annuity(); Для использования функции fp из модуля для работы с простыми процентами, можно использовать один из следующих вариантов (для сравнения приведен аналогичный код на Python, когда это возможно):\nИмпорт одного модуля без указания псевдонима: Python:\nimport fincalc.simper fv = fincalc.simper.fv(pv, i, n) NewLang:\n\\fincalc\\simper(); fv := \\fincalc\\simper::fv(pv, i, n); С указанием псевдонима имени модуля: Python:\nimport fincalc.simper as sp fv = sp.fv(pv, i, n) NewLang:\nsp := \\fincalc\\simper(); fv := sp.fv(pv, i, n); Импорт одной конкретной функции: Python:\nfrom fincalc import fv result = fv(pv, i, n) NewLang:\n\\fincalc\\simper(__import__=\"fv\"); result := fv(pv, i, n); Импорт всего пакета: NewLang:\n\\fincalc(); result := fv(pv, i, n); ","categories":"","description":"","excerpt":"В NewLang реализована концепция программных модулей и пакетов - …","ref":"/docs/syntax/modules/","tags":"","title":"Модули и пакеты"},{"body":"В NewLang реализована концепция программных модулей и пакетов - которая повторяет идею иерархического расположения файлов в каталогах файловой системы, примерно так же, как это сделано в языке Python, но разделителем имен выступает не точка, а символ “\\” (как разделитель каталогов в Windows).\nИмя модуля может содержать только строчные английские буквы или цифры. Данное ограничение связано с прямым отображением имен модулей на объекты в файловой системе, так как у разных файловых систем могут быть различные возможности с поддержкой кодировок и разные требования к преобразованию регистров символов.\nПод модулем в NewLang понимается файл исходным кодом (с расширением *.src). Модули предназначены для того, чтобы в них хранить часто используемые функции, классы, константы и т.п. Их можно условно разделить на модули и программы: программы предназначены для непосредственного запуска, а модули для импортирования их в другие программы, но функционально модули и программы ничем между собой не отличаются.\nОбъекты модуля Все объекты, определенные внутри одного модуля без указания глобального простанства имен, видны только в рамках текущего файла.\nВремя жизни статической и локальной переменных модуля одинаковые, и ограничены временм жизни самого модуля, но статическая и локальная переменные модуля отличаются с точки зрения многопоточности.\nСтатическая переменная модуля всегда будет в единственном экземпляре для всех потоков, тогда как локальная переменная модуля будет для каждого потока своя (аналог thread_local (C++11)).\nКак импортировать модули? Относительное имя программного модуля начинается на символ “\\”, и в этом случае расположение файла программного модуля указывается относительно текущего файла.\nАбсолютное имя программного модуля начинается на два символа “\\\\” и указывает на файл модуля относительно каталога текущего исполняемого файла (или в списке каталогов для поиска программных модулей, который можно переопределить, например, с помощью аргументов командной строки).\nПолное имя текущего модуля (файла) содержится в переменной препроцессора ‘@\\\\’.\nСамый простой способ импортировать модуль, это записать его имя со скобками как при вызове функции. Причем в скобках можно передать аргументы для инициализации модуля, список импортируемых функций и т.д.\nТак как NewLang разрабатывается как компилируемый язык, то загрузка модулей возможна как статически, так и динамически (очень похоже на статическую и динамическую ликновку с dll библиотеками).\n\\dir\\module() - статическая загрузка модуля по относительному пути \\\\root\\dir\\module() - статическая загрузка модуля по абсолютному пути \\\\(\"каталог\\файл\") - динамическая загрузка модуля во время выполнения программы При динамической линковке, компиляция исходного кода модуля и все проверки будут выполнятся только во время выполнения приложения, тогда как статическая загрузка модуля позволяет выявить возможные ошибки еще на этапе компиляции программы.\nПо умолчанию, при статической линковке модуля, импортируются все его макросы, функции и переменные модуля, тогда как при динамической загрузке моуля, макросы не импортируются. ?????????????????????????????????????????????????????????????\nЧто такое пакет в NewLang? Пакет в NewLang – это имя каталога, который включает в себя другие каталоги и модули и при этом содержит дополнительный файл __init__.src.\nПакеты используются как дополнение к пространству имен, что позволяет работать с модулями через указание уровня вложенности (через символ \\). Но в отличии от Python и Java, где модули и пакеты заменяют собой пространство имен (namespace), в NewLang модульная структура и области имен используются одновременно и при указании полного имени объекта, программные модули и пространства имен можно объединять.\nНапример, полное имя переменой можно записать с указанием программного модуля \\root\\dir\\module::ns::name::var, где root и dir это каталоги в файловой системе относительно текущего моделя, а module — имя файла, т.е. root/dir/module.src\nДля импортирования пакетов используется тот же синтаксис, что и для работы с модулями.\nИспользование пакетов Рассмотрим следующую структуру пакета:\nfincalc |-- __init__.src |-- simper.src |-- compper.src |-- annuity.src Пакет fincalc содержит в себе модули для работы с простыми процентами (simper.src), сложными процентами (compper.src) и аннуитетами (annuity.src). Файл __init__.src в отличии от Python, не может быть пустым, а должен в явном виде содержать команды загрузки модулей, входящих в пакет\nНапример для нашего случая содержимое __init__.src может быть вот таким:\n\\simper(); \\compper(); \\annuity(); Для использования функции fp из модуля для работы с простыми процентами, можно использовать один из следующих вариантов (для сравнения приведен аналогичный код на Python, когда это возможно):\nИмпорт одного модуля без указания псевдонима: Python:\nimport fincalc.simper fv = fincalc.simper.fv(pv, i, n) NewLang:\n\\fincalc\\simper(); fv := \\fincalc\\simper::fv(pv, i, n); С указанием псевдонима имени модуля: Python:\nimport fincalc.simper as sp fv = sp.fv(pv, i, n) NewLang:\nsp := \\fincalc\\simper(); fv := sp.fv(pv, i, n); Импорт одной конкретной функции: Python:\nfrom fincalc import fv result = fv(pv, i, n) NewLang:\n\\fincalc\\simper(__import__=\"fv\"); result := fv(pv, i, n); Импорт всего пакета: NewLang:\n\\fincalc(); result := fv(pv, i, n); ","categories":"","description":"","excerpt":"В NewLang реализована концепция программных модулей и пакетов - …","ref":"/ru/docs/syntax/modules/","tags":"","title":"Модули и пакеты"},{"body":"Арифметическое сравнение Операторы арифметического сравнения представленными классическими \u003c, \u003e, \u003c=, \u003e=, == и !=. Они использются для сравнения между собой скаляров и рациональных чисел, а операторы сранвения на равенство == и !=, позвоялют сравнивать между собой в том числе и матрицы.\nОператоры сравнения == и != — операторы сравнения с автоматическим приведением совместимых типов для любых объектов\n== и != — операторы сравнения с автоматическим приведением совместимых типов для любых объектов\n=== и !== — операторы точного сравнения для любых объектов (автоматического приведения типов не выполняется). Для объектов сравниваются адреса размещения\nСтрогая статическая (номинальная) типизация Строгая статическая номинальная проверка типа объектов во время любых операций производится автоматически во время компиляции исходного текста программы, если хотя бы у одной из переменных при опеределении был указан её тип в явном виде.\nРезультат статической номинальной проверки типов будет успешным, если тип правого объекта может быть автоматически преобразован к типу левого операнда или тип правого операнада присутствует у левого в иерархии наследования.\nДинамическая номинальная типизация Для проверки имени типа (класса) объекта во время выполнения используется оператор тильда “~”. Это таже номинальная проверка типов, но только во время выполнения приложения. Левым операндом должен быть проверяемый объект, а правым — тип с которым сравнивается левый оператор.\nПравый оператор может быть строкой литералом, переменной строкового типа или именем проверяемого класса непосредственно. Результатом операции будет истина, если правый операнд содержит название класса проверяемого объекта или он присутствует у него в иерархии наследования.\nname := \"class\"; # Строковая переменная с именем класса var ~ name; var ~ :class; # Сравнение с типом var ~ \"class\"; # Имя типа как строка литерал Динамическая утиная типизация Оператор утиной типизации, два символа тильды “~~”. Проверяемым типом является левый оператор, а правый выступает в роли облазца для сравнения. Для простых типов сравнивается совместимость типа левого операнда по отношению к правому. А для словарей и классов в левом операнде проверяется наличие всех имен полей, присутствующих у правого операнда, т.е.:\n# Истина (т. е. левый операнд словарь) (field1=\"value\", field2=2,) ~~ (); # Тоже истина (т. к. поле field1 присутствует у левого операнда) (field1=\"value\", field2=2,) ~~ (field1=_); # Ложь, т.к. поле not_found у левого операнда отсутствует (field1=\"value\", field2=2,) ~~ (not_found=_); Строгая утиная типизация Строгая утиная типизация “~~~” для простых типов сравнивается идентичности типов без учета совместимости, а для составных типов происходит сравнение всех свойств с помощью оператора строгого равенства.\nДля данной операции, пустой тип совместим только с другим пустим типом.\n","categories":"","description":"","excerpt":"Арифметическое сравнение Операторы арифметического сравнения …","ref":"/docs/ops/compare/","tags":"","title":"Операторы сравнения и типизация"},{"body":"Арифметическое сравнение Операторы арифметического сравнения представленными классическими \u003c, \u003e, \u003c=, \u003e=, == и !=. Они использются для сравнения между собой скаляров и рациональных чисел, а операторы сранвения на равенство == и !=, позвоялют сравнивать между собой в том числе и матрицы.\nОператоры сравнения == и != — операторы сравнения с автоматическим приведением совместимых типов для любых объектов\n== и != — операторы сравнения с автоматическим приведением совместимых типов для любых объектов\n=== и !== — операторы точного сравнения для любых объектов (автоматического приведения типов не выполняется). Для объектов сравниваются адреса размещения\nСтрогая статическая (номинальная) типизация Строгая статическая номинальная проверка типа объектов во время любых операций производится автоматически во время компиляции исходного текста программы, если хотя бы у одной из переменных при опеределении был указан её тип в явном виде.\nРезультат статической номинальной проверки типов будет успешным, если тип правого объекта может быть автоматически преобразован к типу левого операнда или тип правого операнада присутствует у левого в иерархии наследования.\nДинамическая номинальная типизация Для проверки имени типа (класса) объекта во время выполнения используется оператор тильда “~”. Это таже номинальная проверка типов, но только во время выполнения приложения. Левым операндом должен быть проверяемый объект, а правым — тип с которым сравнивается левый оператор.\nПравый оператор может быть строкой литералом, переменной строкового типа или именем проверяемого класса непосредственно. Результатом операции будет истина, если правый операнд содержит название класса проверяемого объекта или он присутствует у него в иерархии наследования.\nname := \"class\"; # Строковая переменная с именем класса var ~ name; var ~ :class; # Сравнение с типом var ~ \"class\"; # Имя типа как строка литерал Динамическая утиная типизация Оператор утиной типизации, два символа тильды “~~”. Проверяемым типом является левый оператор, а правый выступает в роли облазца для сравнения. Для простых типов сравнивается совместимость типа левого операнда по отношению к правому. А для словарей и классов в левом операнде проверяется наличие всех имен полей, присутствующих у правого операнда, т.е.:\n# Истина (т. е. левый операнд словарь) (field1=\"value\", field2=2,) ~~ (); # Тоже истина (т. к. поле field1 присутствует у левого операнда) (field1=\"value\", field2=2,) ~~ (field1=_); # Ложь, т.к. поле not_found у левого операнда отсутствует (field1=\"value\", field2=2,) ~~ (not_found=_); Строгая утиная типизация Строгая утиная типизация “~~~” для простых типов сравнивается идентичности типов без учета совместимости, а для составных типов происходит сравнение всех свойств с помощью оператора строгого равенства.\nДля данной операции, пустой тип совместим только с другим пустим типом.\n","categories":"","description":"","excerpt":"Арифметическое сравнение Операторы арифметического сравнения …","ref":"/ru/docs/ops/compare/","tags":"","title":"Операторы сравнения и типизация"},{"body":"Для обработки перываний потока выполения, а также для обработки ошибкок компилятора используются С++ классы - наследники от std::exception, которые возвращают объект ошибки (значение).\nОшибка компилятора возвращает не только тестовое описание, но и объект TermPtr, при обработке которого возникла ошибка, тогда как перывание потока выполения возвращается объект ObjPtr.\nstd::exception -+-\u003e :ParserError | (TermPtr) | +-\u003e :RuntimeError ----\u003e :IntAny --+-\u003e :IntPlus (ObjPtr) | | +-\u003e :IntMinus При выполнении (генерации кода) именованные прерывания могут быть реализованы без использования исключений!\n","categories":"","description":"","excerpt":"Для обработки перываний потока выполения, а также для обработки …","ref":"/docs/arch/errors/","tags":"","title":"Реализация обработки ошибок и прерываний"},{"body":"Чтобы не усложнять обработку ошибок и не разделять их на внутренние и внешние, реализовано всего два класса для сообщения об ошибоках, накопительные и непосредственные + возврат значений.\nНакопительные ошибки и их реализация Накопительные ошибки используются при обработке исходного текста программы при его парсинге, анализа или компиляции. Накопительнность данных ошибок заключается в том, что процесс обработки исходного текста прерывается не сразу после возникновения первой ошибки, а только после превышения определнного лимита (по умолчанию –nlc-error-limit=10).\nДля логирования места возникновения ошибки используется макрос LOG_ERROR и при необходиости инкремент количества ошибок, или без оного (LOG_WARNING, LOG_INFO, LOG_DEBUG, LOG_DUMP) и обязательной пометкой термина TermPtr как причины её возникновения.\nПосле превышения лимита накопительных ошибок или при их наличии и завершении исходного текста программы, генерируется обычное исключение std::exception с описанием причины (последней ошибки).\nНепосредственные ошибки и их реализация Непосредственные ошибки применяются при выполнении (интерпретции) тела программы и предназнчены для информирования пользователя о возникновении ошибки прерывания работы программы. Так как контекст (текущий термин или строка в исходном файла) как правило не доступны, то сразу генерируется обычное исключение std::exception с описанием причины возникновения, а идентификация места её возникновения с конкретным исходным местом в тексте программы возлагается на обработчик прерываний.\nВозврат знечений Для обработки перываний потока выполения, используются отдельные С++ классы, которые не являются наследниками std::exception, чтобы специально разделить код обработки возврата значений от обработки ошибок, а при выполнении (генерации кода) именованные прерывания могут быть реализованы вообще без использования исключений (return, break, continue или goto)!\n:IntAny --+-\u003e :IntPlus (ObjPtr) | | +-\u003e :IntMinus ","categories":"","description":"","excerpt":"Чтобы не усложнять обработку ошибок и не разделять их на внутренние и …","ref":"/ru/docs/arch/errors/","tags":"","title":"Реализация прерываний и обработки ошибок"},{"body":"Объектно ориентированное программирование NewLang поддерживает следующую концепцию объектно-ориентированного программирования:\nКаждый объект представляет собой отдельный тип данных, который наследуется от другого типа или от одного из его наследников (что очень похоже на концепцию объектов в языке Java), а экземпляр конкретного класса создается путем вызова его типа.\nНаследование поддерживается для типов словарь (:Dictionary) и класс (:Class) и всех их потомков.\nСловарь Словарь (:Dictionary) — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии (это похоже и на tuple и на структуру одновременно). Словари отличаются от тензоров тем, что всегда имеют только одно измерение, но каждый элемент может содержать произвольное количество элементов любого типа, в том числе и другие словари.\nДоступ к элементам словаря происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. Индекс начинается с 0 и как у тензоров, тоже может быть отрицательным (индекс элемента от “конца”).\n# Новый тип (класс) :NewClass :Dict := :Dictionary() { _ := 1; # У поля данных имя отсутствует two := 2; name := 3; }; dict := :Dict(); # Экземпляр класса (1, two=2, name=3,):Dict dict2 := :Dict(two=42); # Экземпляр класса (1, two=42, name=100,):Dict dict3 := dict2(99, name=0); # Копия объекта dict2 (99, two=42, name=0,):Dict В будущем можно будет добавить возможность указывать индексы элементов словаря с помощь диапазонов\n$dict = :Dict[10](first=1, 4..4 = 29, 2..3 = 15, , 2..3 = 15, 7..9..2 = 7); #(first=1, 0, 15, 15, 29, 0, 0, 7, 0, 7,) Словарь как литерал Литерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, т. е. (,) — пустой словарь, (1, 2= «2», name=3,). Для указания конкретного типа объекта у литерала, его необходимо указать после закрывающей скобки, т.е. (1, two= «2», name=3,):Dict.\nВажный момент! Хоть такой объект и будет иметь указанный тип, но он будет “неполноценным” и содержать только те данные, которые были явно указаны в скобках, что не гарантирует корректного создания реального объекта, т.к. для создания “правильного” объекта требуется вызвать его тип, т.е. :Dict();\nТакой способ создания литералов классов используется в основном в различных операциях сравнения типов и “утиной типизации”, т.к. не требует доступа к рантайму, да и сам класс может быть не определен.\nПеречисление, структура и объединение Существуют три отдельных типа данных, :Enum, :Struct и :Union — которые так же являются словарями, но на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера. Эти типы данных одновременно относятся к группе нативных типов и могут быть представлены в двоичном виде в одной области машинной памяти.\n","categories":"","description":"","excerpt":"Объектно ориентированное программирование NewLang поддерживает …","ref":"/docs/types/dicts/","tags":["типы данных","ООП","коллекции"],"title":"Словари"},{"body":"Объектно ориентированное программирование NewLang поддерживает следующую концепцию объектно-ориентированного программирования:\nКаждый объект представляет собой отдельный тип данных, который наследуется от другого типа или от одного из его наследников (что очень похоже на концепцию объектов в языке Java), а экземпляр конкретного класса создается путем вызова его типа.\nНаследование поддерживается для типов словарь (:Dictionary) и класс (:Class) и всех их потомков.\nСловарь Словарь (:Dictionary) — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии (это похоже и на tuple и на структуру одновременно). Словари отличаются от тензоров тем, что всегда имеют только одно измерение, но каждый элемент может содержать произвольное количество элементов любого типа, в том числе и другие словари.\nДоступ к элементам словаря происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. Индекс начинается с 0 и как у тензоров, тоже может быть отрицательным (индекс элемента от “конца”).\n# Новый тип (класс) :NewClass :Dict := :Dictionary() { _ := 1; # У поля данных имя отсутствует two := 2; name := 3; }; dict := :Dict(); # Экземпляр класса (1, two=2, name=3,):Dict dict2 := :Dict(two=42); # Экземпляр класса (1, two=42, name=100,):Dict dict3 := dict2(99, name=0); # Копия объекта dict2 (99, two=42, name=0,):Dict В будущем можно будет добавить возможность указывать индексы элементов словаря с помощь диапазонов\n$dict = :Dict[10](first=1, 4..4 = 29, 2..3 = 15, , 2..3 = 15, 7..9..2 = 7); #(first=1, 0, 15, 15, 29, 0, 0, 7, 0, 7,) Словарь как литерал Литерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, т. е. (,) — пустой словарь, (1, 2= «2», name=3,). Для указания конкретного типа объекта у литерала, его необходимо указать после закрывающей скобки, т.е. (1, two= «2», name=3,):Dict.\nВажный момент! Хоть такой объект и будет иметь указанный тип, но он будет “неполноценным” и содержать только те данные, которые были явно указаны в скобках, что не гарантирует корректного создания реального объекта, т.к. для создания “правильного” объекта требуется вызвать его тип, т.е. :Dict();\nТакой способ создания литералов классов используется в основном в различных операциях сравнения типов и “утиной типизации”, т.к. не требует доступа к рантайму, да и сам класс может быть не определен.\nПеречисление, структура и объединение Существуют три отдельных типа данных, :Enum, :Struct и :Union — которые так же являются словарями, но на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера. Эти типы данных одновременно относятся к группе нативных типов и могут быть представлены в двоичном виде в одной области машинной памяти.\n","categories":"","description":"","excerpt":"Объектно ориентированное программирование NewLang поддерживает …","ref":"/ru/docs/types/dicts/","tags":["типы данных","ООП","коллекции"],"title":"Словари"},{"body":" Ответ прост: классы не строго необходимы для ООП. Знаю, это может шокировать.\nРазумеется, нам нужна возможность создания новых объектов, и языки на основе классов, очевидно, распространены сильнее. Однако это не единственный способ достижения цели.\nВ языках наподобие JavaScript (хотя ES6 добавил в язык классы6, 7) и Lua используется концепция ООП на основе прототипов или прототипного ООП. Вместо создания схемы для конструирования новых объектов мы используем существующий объект в качестве прототипа. Такой подход даже может иметь реальные преимущества, поскольку снижает сложность языка8.\nТип данных :Class аналогичен словарю, но все его поля обязаны иметь имена (хотя доступ к свойствам класса по индексу так же возможен). При создании экземпляра класса, создается новая переменная, для которой копируются свойства и методы всех родителей.\nСоздание нового сложного типа (класса), происходит согласно правилам синтаксиса как создание функции в пользовательском пространстве имен. Имя функции является именем нового класса, а сама функция будет выступает в роли конструктора экземпляров класса.\nСинтаксис создание класса выглядит следующим образом:\n# Новый тип (класс) :NewClass ns::NewClass() := :Class() { # Родительские класс или несколько классов через запятую # Конструктор класса - весь блок кода с определением полей и методов @::static := 1; # Поле класса (у всех объектов одно значение) static := 1; # Поле класса (у всех объектов одно значение) .field := 1; # Поле объекта func() := {}; # Метод класса всегда статический #.method() := {}; # Метод объекта (у каждого объекта свой) ~NewClass() ::= { # Деструктор класса }; }; obj := ns::NewClass(); # Экземпляр класса Так как NewLang реализует полный набор вариантов проверок при создании объектов, то переопределения наследуемых функций не требует никаких ключевых слов:\nNewClass2() := NewClass() { # Новый класс на базе существующего .field ::= 2; # Будет ошибка, т.к. поле field уже есть в базовом классе method() = {}; # Аналог override, т.к. method должен существовать в базовом классе }; Интерфейсы, именование методов классов и пространства имен Для создания уникальных идентификаторов на основе имен методов классов, NewLang использует подход, похожий на применяемый в языке Python. При создании метода класса, создается глобальная функция с именем класса и именем метода, объединенные через разделитель области имен. Например, в классе NewClass2 при создании метода method будет создана функция с именем ::NewClass2::method.\nТакая схема наименований методов полностью соответствует именованию функций в пространствах имен, и тем самым позволяет определять классы c чистыми виртуальными функциями (методами без реализации), а в последствии определять их в пространстве имен или указав полное имя в явном виде.\nns:: { NewClass3 := NewClass() { # Новый класс на базе существующего virtual() := _; # Виртуальный метод }; }; obj := ns::NewClass3(); # объект создать нельзя, будет ошибка # Определить функцию для виртуального метода ns::NewClass3::virtual() := {}; obj := ns::NewClass3(); # ОК Конструкторы, деструкторы и финализаторы у объектов ns::NewClass() := Class() { # Новый класс на базе существующего # Блок кода функции - конструктор объекта __NewClass__() = {...}; # Метод с системным именем типа - деструктор объекта (вызывается сразу после удаления) _NewClass() := {...}; # Скрытый метод с именем типа - защищенный конструктор объекта ????????????????? __NewClass() := {...}; # Скрытый метод с именем типа - приватный конструктор объекта ????????????????? :NewClass(type) ::= {...}:NewClass; # Функция для приведения типа объекта $type к типу :NewClass ~NewClass() = {...}; # Скрытый метод - финализатор (вызывается перед освобождением памяти) __equals__(obj):Bool = { __compare__($obj) == 0 }; __compare__(obj):Int8 = { :: __compare__(@this, $obj) }; _() := {...}; # ????????????????????????????????????? }; extension methods !\nПишу на С++ последние лет 20, до этого ещё Delphi лет 10. С годами полностью отошёл от ООП в сторону data-driven design. Классы — практически структуры, из методов как правило только декоративные геттеры. Всё остальное — это просто функции с понятными названиями, сигнатурами и операндами-объектами таких вот классов-носителей данных и состояния. Получается, очень легко дышится и чистенько — состояния изолированы в структуры, логика изолирована в функции. Конечно, в C++ всё довольно печально с ООП как таковым, поскольку нет механизма extension methods — это когда вы собираете методы в класс из разных единиц трансляции из-за этого, обычные функции C++ значительно удобнее методов класса\nОсновная мысль, которая почти всегда теряется при обсуждении ООП, это то, зачем он нужен и в чем его суть. Все сводится к инструментам, их правильном и неправильном использовании, практичных архитектурах и оверинженеринге.\nМне кажется самая главная мысль очень проста. Сложная программа это сложное состояние. Проблема в том, что сложно следить за всей возможной суперпозицией всех деталей состояния. Небольшое состояние гораздо проще валидировать и постоянно поддерживать целостным. Если ты собираешь сложное состояние из простых целостных состояний, то его тоже проще поддерживать целостным (потому что нужно следить только за высокоуровневым состоянием, но не за всеми деталями)\nСоответственно ООП - это способ описания программы как набора иерархии изолированных состояний, где операции по изменению состояний максимально приближены к состоянию.\nТочно так же как сложную функцию можно представить как последовательность простых, так и сложное состояние можно представить комбинацией простых состояний. Изоляция и контроль состояний и есть основная идея ООП.\nФП подходит с другой стороны - максимально старается избежать состояния и работать только с текущим контекстом. Подход не лишен логики, но любая программа - это прежде всего состояние.\nВсе остальное - лишь инструменты и особенности реализации. ООП может быть реализовано почти на любом языке самыми разными инструментами и не обязательно требует интерфейсов, классов, сообщений, инкапсуляции и т.д. Но разумеется современные ООП языки хорошо адаптированы для такого способа описания. В конечном итоге если подсказки или области видимости действительно не дают тебе менять состояние объекта - это и есть прямая польза на этапе понимания и доработки твоего кода. Тебе просто не нужно думать и знать о состоянии объекта, когда ты с ним не работаешь.\nГлавное в ООП - это то, что есть данные, и есть методы которые напрямую работают с этими данными. Это то, что можно засунуть в один объект. Другой объект, который хочет получить данные из первого объекта, обязан пользоваться публичными методами.\nЭто упрощает поддержку обратной совместимости, упрощает изоляцию объектов, упрощает версионирование в случае многократного использования одними объектами других объектов.\nИ опять таки, суть не в том, что это чем-то напоминает рест-апи или библиотеки, а в том, что это парадигма программирования, которая упрощает организацию разработки сложных проектов, в которых задействовано много разработчиков.\nВсе остальные штуки - наследование, интерфейсы и все другое - это не суть ООП, а различные варианты решения или оптимизации различных кейсов\n","categories":"","description":"","excerpt":" Ответ прост: классы не строго необходимы для ООП. Знаю, это может …","ref":"/docs/types/class/","tags":["типы данных","ООП","коллекции"],"title":"Классы"},{"body":" Ответ прост: классы не строго необходимы для ООП. Знаю, это может шокировать.\nРазумеется, нам нужна возможность создания новых объектов, и языки на основе классов, очевидно, распространены сильнее. Однако это не единственный способ достижения цели.\nВ языках наподобие JavaScript (хотя ES6 добавил в язык классы6, 7) и Lua используется концепция ООП на основе прототипов или прототипного ООП. Вместо создания схемы для конструирования новых объектов мы используем существующий объект в качестве прототипа. Такой подход даже может иметь реальные преимущества, поскольку снижает сложность языка8.\nТип данных :Class аналогичен словарю, но все его поля обязаны иметь имена (хотя доступ к свойствам класса по индексу так же возможен). При создании экземпляра класса, создается новая переменная, для которой копируются свойства и методы всех родителей.\nСоздание нового сложного типа (класса), происходит согласно правилам синтаксиса как создание функции в пользовательском пространстве имен. Имя функции является именем нового класса, а сама функция будет выступает в роли конструктора экземпляров класса.\nСинтаксис создание класса выглядит следующим образом:\n# Новый тип (класс) :NewClass ns::NewClass() := :Class() { # Родительские класс или несколько классов через запятую # Конструктор класса - весь блок кода с определением полей и методов @::static := 1; # Поле класса (у всех объектов одно значение) static := 1; # Поле класса (у всех объектов одно значение) .field := 1; # Поле объекта func() := {}; # Метод класса всегда статический #.method() := {}; # Метод объекта (у каждого объекта свой) ~NewClass() ::= { # Деструктор класса }; }; obj := ns::NewClass(); # Экземпляр класса Так как NewLang реализует полный набор вариантов проверок при создании объектов, то переопределения наследуемых функций не требует никаких ключевых слов:\nNewClass2() := NewClass() { # Новый класс на базе существующего .field ::= 2; # Будет ошибка, т.к. поле field уже есть в базовом классе method() = {}; # Аналог override, т.к. method должен существовать в базовом классе }; Интерфейсы, именование методов классов и пространства имен Для создания уникальных идентификаторов на основе имен методов классов, NewLang использует подход, похожий на применяемый в языке Python. При создании метода класса, создается глобальная функция с именем класса и именем метода, объединенные через разделитель области имен. Например, в классе NewClass2 при создании метода method будет создана функция с именем ::NewClass2::method.\nТакая схема наименований методов полностью соответствует именованию функций в пространствах имен, и тем самым позволяет определять классы c чистыми виртуальными функциями (методами без реализации), а в последствии определять их в пространстве имен или указав полное имя в явном виде.\nns:: { NewClass3 := NewClass() { # Новый класс на базе существующего virtual() := _; # Виртуальный метод }; }; obj := ns::NewClass3(); # объект создать нельзя, будет ошибка # Определить функцию для виртуального метода ns::NewClass3::virtual() := {}; obj := ns::NewClass3(); # ОК Конструкторы, деструкторы и финализаторы у объектов ns::NewClass() := Class() { # Новый класс на базе существующего # Блок кода функции - конструктор объекта __NewClass__() = {...}; # Метод с системным именем типа - деструктор объекта (вызывается сразу после удаления) _NewClass() := {...}; # Скрытый метод с именем типа - защищенный конструктор объекта ????????????????? __NewClass() := {...}; # Скрытый метод с именем типа - приватный конструктор объекта ????????????????? :NewClass(type) ::= {...}:NewClass; # Функция для приведения типа объекта $type к типу :NewClass ~NewClass() = {...}; # Скрытый метод - финализатор (вызывается перед освобождением памяти) __equals__(obj):Bool = { __compare__($obj) == 0 }; __compare__(obj):Int8 = { :: __compare__(@this, $obj) }; _() := {...}; # ????????????????????????????????????? }; extension methods !\nПишу на С++ последние лет 20, до этого ещё Delphi лет 10. С годами полностью отошёл от ООП в сторону data-driven design. Классы — практически структуры, из методов как правило только декоративные геттеры. Всё остальное — это просто функции с понятными названиями, сигнатурами и операндами-объектами таких вот классов-носителей данных и состояния. Получается, очень легко дышится и чистенько — состояния изолированы в структуры, логика изолирована в функции. Конечно, в C++ всё довольно печально с ООП как таковым, поскольку нет механизма extension methods — это когда вы собираете методы в класс из разных единиц трансляции из-за этого, обычные функции C++ значительно удобнее методов класса\nОсновная мысль, которая почти всегда теряется при обсуждении ООП, это то, зачем он нужен и в чем его суть. Все сводится к инструментам, их правильном и неправильном использовании, практичных архитектурах и оверинженеринге.\nМне кажется самая главная мысль очень проста. Сложная программа это сложное состояние. Проблема в том, что сложно следить за всей возможной суперпозицией всех деталей состояния. Небольшое состояние гораздо проще валидировать и постоянно поддерживать целостным. Если ты собираешь сложное состояние из простых целостных состояний, то его тоже проще поддерживать целостным (потому что нужно следить только за высокоуровневым состоянием, но не за всеми деталями)\nСоответственно ООП - это способ описания программы как набора иерархии изолированных состояний, где операции по изменению состояний максимально приближены к состоянию.\nТочно так же как сложную функцию можно представить как последовательность простых, так и сложное состояние можно представить комбинацией простых состояний. Изоляция и контроль состояний и есть основная идея ООП.\nФП подходит с другой стороны - максимально старается избежать состояния и работать только с текущим контекстом. Подход не лишен логики, но любая программа - это прежде всего состояние.\nВсе остальное - лишь инструменты и особенности реализации. ООП может быть реализовано почти на любом языке самыми разными инструментами и не обязательно требует интерфейсов, классов, сообщений, инкапсуляции и т.д. Но разумеется современные ООП языки хорошо адаптированы для такого способа описания. В конечном итоге если подсказки или области видимости действительно не дают тебе менять состояние объекта - это и есть прямая польза на этапе понимания и доработки твоего кода. Тебе просто не нужно думать и знать о состоянии объекта, когда ты с ним не работаешь.\nГлавное в ООП - это то, что есть данные, и есть методы которые напрямую работают с этими данными. Это то, что можно засунуть в один объект. Другой объект, который хочет получить данные из первого объекта, обязан пользоваться публичными методами.\nЭто упрощает поддержку обратной совместимости, упрощает изоляцию объектов, упрощает версионирование в случае многократного использования одними объектами других объектов.\nИ опять таки, суть не в том, что это чем-то напоминает рест-апи или библиотеки, а в том, что это парадигма программирования, которая упрощает организацию разработки сложных проектов, в которых задействовано много разработчиков.\nВсе остальные штуки - наследование, интерфейсы и все другое - это не суть ООП, а различные варианты решения или оптимизации различных кейсов\n","categories":"","description":"","excerpt":" Ответ прост: классы не строго необходимы для ООП. Знаю, это может …","ref":"/ru/docs/types/class/","tags":["типы данных","ООП","коллекции"],"title":"Классы"},{"body":"https://habr.com/companies/otus/articles/763810/ https://habr.com/articles/764420/\nПоследовательная согласованность отсутствует (отсутствуют атомарныти типы) Любой язык программирования так или иначе вынужден управлять оперативной памятью. В NewLang реализовано автоматическое управление памятью без сборщика мусора.\nЗа основу была взята модель “владения” из языка Rust, но она переработана под концепцию сильных и слабых указателей (аналоги shared_ptr и weak_ptr из С++), где каждое значение в памяти может иметь только одну переменную-владельца с сильным указателем.\nИ когда такая переменная-владелец уходит из области видимости, счетчик ссылок уменьшается и при достжении нуля память освобождается.\nФактически, это автоматическое управление памятью с помощью подсчёта ссылок на этапе компиляции и без использования сборщика мусора.\nСуществование ссылок на объекты предполагает и возможность одновременного доступа к данным из нескольких потоков выполнения. Из-за чего управление памятью включает в себя и элементы межпотокового взаимодействия, так как совместное владение ссылками по любому будет требовать каких либо механизмов синхронизации доступа к разеделяемой памяти объектов.\nПоэтому, при определении объекта указывается, какие типы ссылок допускается создавать на него, а так-же какая используется модель совместного доступа к переменной.\nВесь механизм подсчета ссылок и проверки их корректности реализован на уровне синтаксиса. В рантайме выполняется только контроль идентификатора потока для однопоточных ссылок, а все остальные проверки выполняются во время компиляции.\nУправление памятью и терминология Врчную выделить или освобондить память нельзя\nЛюбой объект - это ссылка на область памяти с данным. Память выделяется и освобожадется автоматически при создании/удалении объектов\nСсылки на объекты, с точки зрения владения, могут быть:\nСильные/Владеющие ссылки (аналог shared_ptr из С++), а фактические, это переменная которая хранит значение объекта. Слабые/Не владеющие ссылки (аналог weak_ptr из С++) - указатели на другим объекты которые перед использованием требуют обязательного захвата (т.е. преобразования в сильную ссылку). Ссылки на объекты, с точки зрения совместного доступа, могут быть:\nЛегкие - ссылки без объекта синхронизации Тяжелые - ссылки с объектом синхронизации совметсного доступа (мьютексом). Переменные - владельцы объектов (в них хранятся ссылки) могут быть двух видов:\nлокальные (контролируемые) - область жизни локальных переменных строго ограничена и определяется правилами синтаксиса языка (аргументы и локальные переменные функций, потоков и т.д.). не контролируемые - глобальные или статические переменные, динамически создаваемые объекты, время жизни которых компилятор не контролирует. Когда локальная переменная удаляется - уменьшается счетчик ссылок, а при достижении нуля - объект освобождается.\nКаждый объект может иметь только одну не контролируемую переменную с сильной ссылкой и произвольное количество любых дргуих типов ссылок в локальных (контролируемых) переменных.\nДля не контролируемых переменных разрешается делать только слабые ссылки, которые перед использованием требуется захватить, например в локальную (контролируемую) переменную.\nУправление временем жизни объекта включает в себя не только управлением памятью, но и при необходимости, создаются механизмы синхронизации доступа к ней. Для этого при определении переменной, описываются возможные типы ссылок, которые разрешено на неё получать:\nбез создания ссылок, т.е. компилятор не даст создать ссылку на данную переменную, а совместный доступ к такой переменой будет не возможен возможно создание легкой ссылки (\"\u0026\"). Компилятору при генерации машинного кода не нужно создавать объект синхронизации доступа к переменной.\nСсылки для полей структур или объектов могут быть только легкими. разрешено создавать ссылки с монопольным доступом (\"\u0026\u0026\"). Компилятор автоматически создает не рекурсивный мьютекс для синхронизации доступа к переменной, т.е. ссылка у этой переменной будет тяжелой. разрешено создавать ссылки с рекурсивным доступом (\"\u0026*\"). Компилятор автоматически создает рекурсивный мьютекс (его можно захватывать несколько раз), а ссылка у этой переменной будет тяжелой. легкая ссылка может быть создана для совместного доступа (\"\u0026?\"), но её захват и синхронизация доступа к ней возможен только при групповом захвате ссылок. Все виды ссылок могут быть константными (\"\u0026^\", “\u0026\u0026^” или “\u0026*^”), т.е. только для чтения (и в случае константных объектов, таким ссылкам мьютекс не потребуется).\nЗахват слабой ссылки может быть индивидуальным или групповым с сохранением результата в локальную (контролируемую) переменную. Такое использование логики захвата объекта на уровне синтаксиса языка гарантирует последующее автоматическое освобождение временной переменной, что равнозначно невозможности создания циклических ссылок.\nПеременная со слабой/не владеющей ссылкой создается только тогда, когда в правой части операции присвоения присутствует любой из операторов получения ссылки (\u0026, \u0026\u0026, \u0026* или \u0026^, \u0026\u0026^, \u0026*^).\nВо всех остальных случаях создается переменная владелец с сильной/владеющей ссылкой (если это разрешено).\nЗахват ссылки и значение переменной Захват ссылки - это преобразование слабой ссылки в сильную с её сохранением в контролируемую переменую с инкрементом счетчика ссылок и возможностью доступа к значению объекта. Это очень похоже на заимствование (Borrowing) в Rust, так как тоже позволяет использовать данные, находящиеся во владении другой переменной, но без перехода владения. Для захвата ссылок используются операторы:\n‘*’ или ‘*( … )’ - автоматический выбор типа доступа (чтения/запись или только чтение) ‘*^’ или ‘*^( … )’ - захват доступа только для чтения ‘**( … )’ - групповой захват ссылок в локальные (контролируемые) переменные () после имени переменной - создание копии значения переменной (глубокое клонирование) ??????????????????????????????????? Упрощенный условный пример:\nref := \u0026 owner; # переменная ref - слабая ссылка на owner ref_ro := \u0026^ owner; # слабая ссылка на owner только для чтения val := * ref; # Автоматический захват только для чтения *ref = val; # Автоматический захват для чтения/записи val := *^ ref; # Захват только для чтения val := *^ ref_ro; val := * ref_ro; # Автоматический захват только для чтения *ref_ro = val; # Ошибка - ссылка только для чтения !!! *^ ref_ro = val; # Ошибка - недопустима конструкция (захват lval - только для чтения) Слабую ссылку можно захватить (превратить в сильную) сохранив результат в локальной переменной, после чего работать с локальной переменной “по значению” без необходимости захватытвать ссылку при каждом обращении к переменной. Значения переменных со слабыми ссылками можно копировать в другие переменные без ограничений. Значение переменной с сильной ссылкой нельзя скопировать в другую переменную или поле объекта, но можно клонировать данные или обменяться значениями “:=:” с другой переменной с сильной ссылкой (swap). Примеры владения:\nowner := \"string\"; other := \"string 2\"; owner = other; # Ошибка - нельзя копировать! owner = other(); # Глубокое клонирование данных owner :=: other; # Обмен значениями (swap) other = _; # Очистка данных объекта Переменную, содержащую ссылку на ссылку создать нельзя, но можно создать ссылочный тип и после этого создать переменную-ссылку на этот тип данных. Упрощенный условный пример:\nvalue := 123; :RefInt := \u0026 Integer; ref_int :RefInt := \u0026 value; ref_ref := \u0026 ref_int; Если переменная владелец разрешает создавать ссылки на объект, тогда при обращении к такой переменой требуется выполнять захват объекта для обеспечения работы механизма совместного доступа. Ссылки и совместный доступ Управление временем жизни переменной включает в себя не только управление памятью, но и механизм синхронизации для монопольного/раздельного доступа к объектам из разных потоков.\nПримеры ссылок:\n\u0026 local := 123; # Разрешено создание ссылок только в текущем потоке \u0026\u0026 thread := 456; # Разрешено создание ссылок с монопольным доступом в любом потоке ref := \u0026 local; # Создание слабой ссылки на local ref2 := \u0026\u0026 local; # Ошибка! многопоточные ссылки не разрешены ref_th := \u0026\u0026 thread; # Создание слабой ссылки на thread # c монопольной блокировкой доступа local += 1; # ОК thread += 1; # Ошибка, требуется захват объекта с разеляемым доступом *local += 1; # ОК, оператор захвата игнорируется *thread += 1; # Захват объекта (как захват слабой ссылки) ref += 1; # Ошибка, требуется захват слабой ссылки ref_th += 1; # Ошибка, требуется захват слабой ссылки *ref += 1; *ref_th += 1; Операторы захвата ссылки и синхронизации доступа к объекту выполняются только для одного действия над переменной. Но захват объекта синхронизации, это относительно медленная операция и выполнять её для каждого действия над переменной не рационально.\nДля того, чтобы однократно захватить объект(ы) синхронизации для выполнения сразу нескольких действий над переменными можно захватить объект в локальную переменую или использовать менеджер контекста.\nПример программы rand():Int32 ::= %rand...; # Создание объекта @( rand():Int32 ); # Предварительное объявление (объект должен быть создан в другом месте) rand():Int32 = ...; usleep(usec:DWord64):None := %usleep...; printf(format:FmtChar, ...):Int32 := %printf...; func(count:Integer, target:String) := { $iter := @iter( 1..$count ); # Итератор для диапазона от 1 до $count @while( @curr($iter) ) { # Цикл, пока итератор валидный $step := @next($iter); # Получить текущий и перейти на следующий элемент итератора printf('Number %d from %s!', $step, $target); usleep( rand() % 1000 ); # Случайная задержка } } thread = :Thread(func, 5, 'thread'); thread.start(); func(5, 'main'); thread.join(); Number 1 from the thread! Number 1 from the main! Number 2 from the thread! Number 2 from the main! Number 3 from the thread! Number 4 from the thread! Number 3 from the main! Number 4 from the main! Number 5 from the main! Number 5 from the thread! Примеры ссылок:\n\u0026 $local := 123; # Разрешено получение легких ссылок \u0026\u0026 $thread := 456; # Доступ к переменной требует захвата тяжелой ссылки $ref := \u0026 $local; # получение слабой ссылки на local $ref2 := \u0026\u0026 $local; # Ошибка! Тяжелой многопоточные ссылки не разрешены $ref_th := \u0026\u0026 $thread; # Получение слабой ссылки на thread # c монопольной блокировкой доступа $local += 1; # ОК (для легких ссылок блокировка объекта не требуется) $thread += 1; # ОК (захват объекта происходит автоматически) $ref += 1; # Ошибка, требуется захват легкой слабой ссылки $ref_th += 1; # Ошибка, требуется захват тяжолой слабой ссылки *$local += 1; # ОК *$thread += 1; # ОК *$ref += 1; # ОК (только захват ссылки, блокировка игнорируется) *$ref_th += 1; # ОК (захват ссылки и блокироваки доступа) Менеджер контекста Операторы захвата ссылки и синхронизации доступа к объекту выполняются только для одного действия над переменной. Но захват объекта синхронизации, это относительно медленная операция и выполнять её для каждого действия над переменной не рационально.\nДля того, чтобы однократно захватить объект(ы) синхронизации для выполнения сразу нескольких действий над переменными используется менеджер контекста.\n","categories":"","description":"","excerpt":"https://habr.com/companies/otus/articles/763810/ …","ref":"/docs/syntax/memory/","tags":"","title":"Управление памятью, ссылки и совместный доступ"},{"body":"https://habr.com/ru/companies/otus/articles/763810/ https://habr.com/ru/articles/764420/\nПоследовательная согласованность отсутствует (отсутствуют атомарныти типы) Любой язык программирования так или иначе вынужден управлять оперативной памятью. В NewLang реализовано автоматическое управление памятью без сборщика мусора.\nЗа основу была взята модель “владения” из языка Rust, но она переработана под концепцию сильных и слабых указателей (аналоги shared_ptr и weak_ptr из С++), где каждое значение в памяти может иметь только одну переменную-владельца с сильным указателем.\nИ когда такая переменная-владелец уходит из области видимости, счетчик ссылок уменьшается и при достжении нуля память освобождается.\nФактически, это автоматическое управление памятью с помощью подсчёта ссылок на этапе компиляции и без использования сборщика мусора.\nСуществование ссылок на объекты предполагает и возможность одновременного доступа к данным из нескольких потоков выполнения. Из-за чего управление памятью включает в себя и элементы межпотокового взаимодействия, так как совместное владение ссылками по любому будет требовать каких либо механизмов синхронизации доступа к разеделяемой памяти объектов.\nПоэтому, при определении объекта указывается, какие типы ссылок допускается создавать на него, а так-же какая используется модель совместного доступа к переменной.\nВесь механизм подсчета ссылок и проверки их корректности реализован на уровне синтаксиса. В рантайме выполняется только контроль идентификатора потока для однопоточных ссылок, а все остальные проверки выполняются во время компиляции.\nУправление памятью и терминология Врчную выделить или освобондить память нельзя\nЛюбой объект - это ссылка на область памяти с данным. Память выделяется и освобожадется автоматически при создании/удалении объектов\nСсылки на объекты, с точки зрения владения, могут быть:\nСильные/Владеющие ссылки (аналог shared_ptr из С++), а фактические, это переменная которая хранит значение объекта. Слабые/Не владеющие ссылки (аналог weak_ptr из С++) - указатели на другим объекты которые перед использованием требуют обязательного захвата (т.е. преобразования в сильную ссылку). Ссылки на объекты, с точки зрения совместного доступа, могут быть:\nЛегкие - ссылки без объекта синхронизации Тяжелые - ссылки с объектом синхронизации совметсного доступа (мьютексом). Переменные - владельцы объектов (в них хранятся ссылки) могут быть двух видов:\nлокальные (контролируемые) - область жизни локальных переменных строго ограничена и определяется правилами синтаксиса языка (аргументы и локальные переменные функций, потоков и т.д.). не контролируемые - глобальные или статические переменные, динамически создаваемые объекты, время жизни которых компилятор не контролирует. Когда локальная переменная удаляется - уменьшается счетчик ссылок, а при достижении нуля - объект освобождается.\nКаждый объект может иметь только одну не контролируемую переменную с сильной ссылкой и произвольное количество любых дргуих типов ссылок в локальных (контролируемых) переменных.\nДля не контролируемых переменных разрешается делать только слабые ссылки, которые перед использованием требуется захватить, например в локальную (контролируемую) переменную.\nУправление временем жизни объекта включает в себя не только управлением памятью, но и при необходимости, создаются механизмы синхронизации доступа к ней. Для этого при определении переменной, описываются возможные типы ссылок, которые разрешено на неё получать:\nбез создания ссылок, т.е. компилятор не даст создать ссылку на данную переменную, а совместный доступ к такой переменой будет не возможен возможно создание легкой ссылки (\"\u0026\"). Компилятору при генерации машинного кода не нужно создавать объект синхронизации доступа к переменной.\nСсылки для полей структур или объектов могут быть только легкими. разрешено создавать ссылки с монопольным доступом (\"\u0026\u0026\"). Компилятор автоматически создает не рекурсивный мьютекс для синхронизации доступа к переменной, т.е. ссылка у этой переменной будет тяжелой. разрешено создавать ссылки с рекурсивным доступом (\"\u0026*\"). Компилятор автоматически создает рекурсивный мьютекс (его можно захватывать несколько раз), а ссылка у этой переменной будет тяжелой. легкая ссылка может быть создана для совместного доступа (\"\u0026?\"), но её захват и синхронизация доступа к ней возможен только при групповом захвате ссылок. Все виды ссылок могут быть константными (\"\u0026^\", “\u0026\u0026^” или “\u0026*^”), т.е. только для чтения (и в случае константных объектов, таким ссылкам мьютекс не потребуется).\nЗахват слабой ссылки может быть индивидуальным или групповым с сохранением результата в локальную (контролируемую) переменную. Такое использование логики захвата объекта на уровне синтаксиса языка гарантирует последующее автоматическое освобождение временной переменной, что равнозначно невозможности создания циклических ссылок.\nПеременная со слабой/не владеющей ссылкой создается только тогда, когда в правой части операции присвоения присутствует любой из операторов получения ссылки (\u0026, \u0026\u0026, \u0026* или \u0026^, \u0026\u0026^, \u0026*^).\nВо всех остальных случаях создается переменная владелец с сильной/владеющей ссылкой (если это разрешено).\nЗахват ссылки и значение переменной Захват ссылки - это преобразование слабой ссылки в сильную с её сохранением в контролируемую переменую с инкрементом счетчика ссылок и возможностью доступа к значению объекта. Это очень похоже на заимствование (Borrowing) в Rust, так как тоже позволяет использовать данные, находящиеся во владении другой переменной, но без перехода владения. Для захвата ссылок используются операторы:\n‘*’ или ‘*( … )’ - автоматический выбор типа доступа (чтения/запись или только чтение) ‘*^’ или ‘*^( … )’ - захват доступа только для чтения ‘**( … )’ - групповой захват ссылок в локальные (контролируемые) переменные () после имени переменной - создание копии значения переменной (глубокое клонирование) ??????????????????????????????????? Упрощенный условный пример:\nref := \u0026 owner; # переменная ref - слабая ссылка на owner ref_ro := \u0026^ owner; # слабая ссылка на owner только для чтения val := * ref; # Автоматический захват только для чтения *ref = val; # Автоматический захват для чтения/записи val := *^ ref; # Захват только для чтения val := *^ ref_ro; val := * ref_ro; # Автоматический захват только для чтения *ref_ro = val; # Ошибка - ссылка только для чтения !!! *^ ref_ro = val; # Ошибка - недопустима конструкция (захват lval - только для чтения) Слабую ссылку можно захватить (превратить в сильную) сохранив результат в локальной переменной, после чего работать с локальной переменной “по значению” без необходимости захватытвать ссылку при каждом обращении к переменной. Значения переменных со слабыми ссылками можно копировать в другие переменные без ограничений. Значение переменной с сильной ссылкой нельзя скопировать в другую переменную или поле объекта, но можно клонировать данные или обменяться значениями “:=:” с другой переменной с сильной ссылкой (swap). Примеры владения:\nowner := \"string\"; other := \"string 2\"; owner = other; # Ошибка - нельзя копировать! owner = other(); # Глубокое клонирование данных owner :=: other; # Обмен значениями (swap) other = _; # Очистка данных объекта Переменную, содержащую ссылку на ссылку создать нельзя, но можно создать ссылочный тип и после этого создать переменную-ссылку на этот тип данных. Упрощенный условный пример:\nvalue := 123; :RefInt := \u0026 Integer; ref_int :RefInt := \u0026 value; ref_ref := \u0026 ref_int; Если переменная владелец разрешает создавать ссылки на объект, тогда при обращении к такой переменой требуется выполнять захват объекта для обеспечения работы механизма совместного доступа. Ссылки и совместный доступ Управление временем жизни переменной включает в себя не только управление памятью, но и механизм синхронизации для монопольного/раздельного доступа к объектам из разных потоков.\nПримеры ссылок:\n\u0026 local := 123; # Разрешено создание ссылок только в текущем потоке \u0026\u0026 thread := 456; # Разрешено создание ссылок с монопольным доступом в любом потоке ref := \u0026 local; # Создание слабой ссылки на local ref2 := \u0026\u0026 local; # Ошибка! многопоточные ссылки не разрешены ref_th := \u0026\u0026 thread; # Создание слабой ссылки на thread # c монопольной блокировкой доступа local += 1; # ОК thread += 1; # Ошибка, требуется захват объекта с разеляемым доступом *local += 1; # ОК, оператор захвата игнорируется *thread += 1; # Захват объекта (как захват слабой ссылки) ref += 1; # Ошибка, требуется захват слабой ссылки ref_th += 1; # Ошибка, требуется захват слабой ссылки *ref += 1; *ref_th += 1; Операторы захвата ссылки и синхронизации доступа к объекту выполняются только для одного действия над переменной. Но захват объекта синхронизации, это относительно медленная операция и выполнять её для каждого действия над переменной не рационально.\nДля того, чтобы однократно захватить объект(ы) синхронизации для выполнения сразу нескольких действий над переменными можно захватить объект в локальную переменую или использовать менеджер контекста.\nПример программы rand():Int32 ::= %rand...; # Создание объекта @( rand():Int32 ); # Предварительное объявление (объект должен быть создан в другом месте) rand():Int32 = ...; usleep(usec:DWord64):None := %usleep...; printf(format:FmtChar, ...):Int32 := %printf...; func(count:Integer, target:String) := { $iter := @iter( 1..$count ); # Итератор для диапазона от 1 до $count @while( @curr($iter) ) { # Цикл, пока итератор валидный $step := @next($iter); # Получить текущий и перейти на следующий элемент итератора printf('Number %d from %s!', $step, $target); usleep( rand() % 1000 ); # Случайная задержка } } thread = :Thread(func, 5, 'thread'); thread.start(); func(5, 'main'); thread.join(); Number 1 from the thread! Number 1 from the main! Number 2 from the thread! Number 2 from the main! Number 3 from the thread! Number 4 from the thread! Number 3 from the main! Number 4 from the main! Number 5 from the main! Number 5 from the thread! Примеры ссылок:\n\u0026 $local := 123; # Разрешено получение легких ссылок \u0026\u0026 $thread := 456; # Доступ к переменной требует захвата тяжелой ссылки $ref := \u0026 $local; # получение слабой ссылки на local $ref2 := \u0026\u0026 $local; # Ошибка! Тяжелой многопоточные ссылки не разрешены $ref_th := \u0026\u0026 $thread; # Получение слабой ссылки на thread # c монопольной блокировкой доступа $local += 1; # ОК (для легких ссылок блокировка объекта не требуется) $thread += 1; # ОК (захват объекта происходит автоматически) $ref += 1; # Ошибка, требуется захват легкой слабой ссылки $ref_th += 1; # Ошибка, требуется захват тяжолой слабой ссылки *$local += 1; # ОК *$thread += 1; # ОК *$ref += 1; # ОК (только захват ссылки, блокировка игнорируется) *$ref_th += 1; # ОК (захват ссылки и блокироваки доступа) Менеджер контекста Операторы захвата ссылки и синхронизации доступа к объекту выполняются только для одного действия над переменной. Но захват объекта синхронизации, это относительно медленная операция и выполнять её для каждого действия над переменной не рационально.\nДля того, чтобы однократно захватить объект(ы) синхронизации для выполнения сразу нескольких действий над переменными используется менеджер контекста.\n","categories":"","description":"","excerpt":"https://habr.com/ru/companies/otus/articles/763810/ …","ref":"/ru/docs/syntax/memory/","tags":"","title":"Управление памятью, ссылки и совместный доступ"},{"body":"Определение функции происходит с помощью операторов создания объектов, имя функции должно соответствовать правилам именования, после которого указываются круглые скобки. В настоящий момент поддерживается создание функций только в качестве статических объектов с однократной инициализацией с помощью оператора ‘::=’;\nТелом функции должен быть блок кода, который располагается в пространстве имен определения этой функции.\nФункции поддерживают аргументы по умолчанию, а сами аргументы указываются как в Python, т.е. вначале идут обязательные, далее идут аргументы со значениями по умолчанию, где его имя отделяется от дефолтного значения знаком равно “=”.\nЕсли функция допускает обработку произвольного количества аргументов, то последним в списке параметров должно быть указано многоточие “…”.\nУ аргументов функции может быть указан допустимый тип данных. Тип возвращаемого значения указывается после закрывающей скобки.\nУ аргументов и у типа возвращаемого значения можно указать сразу несколько допустимых типов данных.\nДля этого их необходимо перечислить через запятую и заключить в угловые скобки, т.е.*\nfunc(arg:\u003c:Int8, :Int16, :Int32\u003e): \u003c:Int8, :Int16, :Int32\u003e ::= {$arg*$arg}; *) Данная функциональность запланирована, но пока не реализована\nДля создания функций используются те же правила синтаксиса и операторы, что и для создания переменных, только после имени функции обязательно должны быть указаны круглые скобки.\nСинтаксис NewLang поддерживает два типа функций: обычные и чистые функции.\nОбычные функции Обычная функция — такие функции являются именно обычными функциями в понимании С/С++. Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д. ?????????????????????????????\nhello(str) ::= { $printf ::= :Pointer('printf(format:FmtChar, ...):Int32'); $printf('call: %s', $str); $str; }; hello('Привет, мир!'); Чистые функции Чистая функция — это тоже обычная функция, только в том смысле, какой в него вкладывает функциональное программирование.\nУ чистой функции отсутствует доступ к контексту и глобальным переменным, поэтому она может обрабатывать только те данные, которые были ей переданы в качестве аргументов.\nСоздание чистой функции происходит с помощью операторов :- или ::-, а сам оператор заимствован из языка Пролог. ???????????????????????????????? Чистые фунции, так же как и обычные, тоже могут быть только статическими объектами, поэтому их нельзя определять с именами лоакльных объектов.\nSum2(arg1, arg2) ::- {$arg1+$arg2;}; # Тоже самое, но если функция с таким именем уже существует, то будет ошибка ??????????????????????????????????????????????????? Sum1(arg1, arg2) :- {$arg1+$arg2;}; # Создать или переопределить простую функцию, которая возвращает сумму аргументов Лямбда функции Лямбда функции, это анонимная функция без указания имени, т.е. вместо имени функции стоит подчерк, и её нельзя вызвать по имени. Но зато лямбда функцию можно передавать как аругмент в другие функции, например при создании итератора.\n_()::={ ... }; Корутины Любую функцию можно определить как корутину (сопрограмма, Coroutine) - функция, выполнение которой можно прерываться явно методами языка программирования. В отличие от прерывания выполнения потока (thread), который реализован средствами ОС и его переключение происходит неявно и в произвольный момент времени.\nfunc() ::= (){ ... }; Переопределение функций Перегрузка функций по типам аргументов NewLang отсуствует, поэтому нельзя создать несколько функций с однинаковым именем, но разными типами аругментов. Но можно переопределить функцию с помощью оператора “[]=”, а в теле новой функции обратиться к первоначальной функции по системному имени “$$”.\n«Требование от субтипов: пусть φ(x) — свойство, доказуемое относительно объектов x типа T. Тогда φ(y) должно быть истинно для объектов y типа S, где S — субтип T»12.\nЭто называется принципом подстановки Лисков. Я не буду вдаваться в подробности, но основной смысл в том, что любое предусловие (для типов, данных или состояния) параметров не может быть строже, чем для супертипа, а любое постусловие не может быть слабее, чем у супертипа13. Эта формулировка связана с методологией контрактного программирования, зародившегося примерно в то же время.\nНовая функция должна иметь аргументы, совместимые с типом аргумента первоначальной функцией.\nfunc(arg:Int8):Int8 ::= ... ; func(arg:Int16):Int16 = ... ; # ОК Int8 -\u003e Int16 func(arg:String):Int16 = ... ; # Ошибка String -\u003e Int16 func(arg:Int16, arg2:Int16):Int16 = ... ; func(arg:Integer, ...):Integer = ... ; # ОК обобщенные тип ","categories":"","description":"","excerpt":"Определение функции происходит с помощью операторов создания объектов, …","ref":"/docs/types/funcs/","tags":["типы данных","функции"],"title":"Функции"},{"body":"Определение функции происходит с помощью операторов создания объектов, имя функции должно соответствовать правилам именования, после которого указываются круглые скобки. В настоящий момент поддерживается создание функций только в качестве статических объектов с однократной инициализацией с помощью оператора ‘::=’;\nТелом функции должен быть блок кода, который располагается в пространстве имен определения этой функции.\nФункции поддерживают аргументы по умолчанию, а сами аргументы указываются как в Python, т.е. вначале идут обязательные, далее идут аргументы со значениями по умолчанию, где его имя отделяется от дефолтного значения знаком равно “=”.\nЕсли функция допускает обработку произвольного количества аргументов, то последним в списке параметров должно быть указано многоточие “…”.\nУ аргументов функции может быть указан допустимый тип данных. Тип возвращаемого значения указывается после закрывающей скобки.\nУ аргументов и у типа возвращаемого значения можно указать сразу несколько допустимых типов данных.\nДля этого их необходимо перечислить через запятую и заключить в угловые скобки, т.е.*\nfunc(arg:\u003c:Int8, :Int16, :Int32\u003e): \u003c:Int8, :Int16, :Int32\u003e ::= {$arg*$arg}; *) Данная функциональность запланирована, но пока не реализована\nДля создания функций используются те же правила синтаксиса и операторы, что и для создания переменных, только после имени функции обязательно должны быть указаны круглые скобки.\nСинтаксис NewLang поддерживает два типа функций: обычные и чистые функции.\nОбычные функции Обычная функция — такие функции являются именно обычными функциями в понимании С/С++. Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д. ?????????????????????????????\nhello(str) ::= { $printf ::= :Pointer('printf(format:FmtChar, ...):Int32'); $printf('call: %s', $str); $str; }; hello('Привет, мир!'); Чистые функции Чистая функция — это тоже обычная функция, только в том смысле, какой в него вкладывает функциональное программирование.\nУ чистой функции отсутствует доступ к контексту и глобальным переменным, поэтому она может обрабатывать только те данные, которые были ей переданы в качестве аргументов.\nСоздание чистой функции происходит с помощью операторов :- или ::-, а сам оператор заимствован из языка Пролог. ???????????????????????????????? Чистые фунции, так же как и обычные, тоже могут быть только статическими объектами, поэтому их нельзя определять с именами лоакльных объектов.\nSum2(arg1, arg2) ::- {$arg1+$arg2;}; # Тоже самое, но если функция с таким именем уже существует, то будет ошибка ??????????????????????????????????????????????????? Sum1(arg1, arg2) :- {$arg1+$arg2;}; # Создать или переопределить простую функцию, которая возвращает сумму аргументов Лямбда функции Лямбда функции, это анонимная функция без указания имени, т.е. вместо имени функции стоит подчерк, и её нельзя вызвать по имени. Но зато лямбда функцию можно передавать как аругмент в другие функции, например при создании итератора.\n_()::={ ... }; Корутины Любую функцию можно определить как корутину (сопрограмма, Coroutine) - функция, выполнение которой можно прерываться явно методами языка программирования. В отличие от прерывания выполнения потока (thread), который реализован средствами ОС и его переключение происходит неявно и в произвольный момент времени.\nfunc() ::= (){ ... }; Переопределение функций Перегрузка функций по типам аргументов NewLang отсуствует, поэтому нельзя создать несколько функций с однинаковым именем, но разными типами аругментов. Но можно переопределить функцию с помощью оператора “[]=”, а в теле новой функции обратиться к первоначальной функции по системному имени “$$”.\n«Требование от субтипов: пусть φ(x) — свойство, доказуемое относительно объектов x типа T. Тогда φ(y) должно быть истинно для объектов y типа S, где S — субтип T»12.\nЭто называется принципом подстановки Лисков. Я не буду вдаваться в подробности, но основной смысл в том, что любое предусловие (для типов, данных или состояния) параметров не может быть строже, чем для супертипа, а любое постусловие не может быть слабее, чем у супертипа13. Эта формулировка связана с методологией контрактного программирования, зародившегося примерно в то же время.\nНовая функция должна иметь аргументы, совместимые с типом аргумента первоначальной функцией.\nfunc(arg:Int8):Int8 ::= ... ; func(arg:Int16):Int16 = ... ; # ОК Int8 -\u003e Int16 func(arg:String):Int16 = ... ; # Ошибка String -\u003e Int16 func(arg:Int16, arg2:Int16):Int16 = ... ; func(arg:Integer, ...):Integer = ... ; # ОК обобщенные тип ","categories":"","description":"","excerpt":"Определение функции происходит с помощью операторов создания объектов, …","ref":"/ru/docs/types/funcs/","tags":["типы данных","функции"],"title":"Функции"},{"body":"Macros are also used to transform the original code of NewLang into a more familiar syntax based on keywords, as such text is much easier to understand when reading the original code later.\nIn NewLang, macros are one or more consecutive terms that are replaced with another term or a whole syntactic construction (a sequence of lexemes).\nMacros are processed during the operation of the lexer, i.e., before passing the sequence of lexemes to the parser, allowing fragments of the language syntax to be modified using macros, for example, when implementing custom DSL dialects.\nDefining Macros The definition of macros is similar to the definition of other objects and consists of three parts \u003ccreation/assignment operator\u003e and ends with a semicolon “;”, i.e., normal operators ::=(::-), =, or :=(:-) are used to create a new or redefine an existing object, and the macro name is indicated between two symbols \"@@\" and can contain one or more lexemes (terms).\nAll macros belong to the global namespace, so the first term in the macro name must be unique, otherwise it will override local and global variables during name lookup if they are written in the program text without qualifiers (sigils).\nUsing the operators ::- and :- creates pure (hygienic) macros, arguments and variables in which are guaranteed not to intersect with the program’s namespace.\nThe body of a macro can be a valid language expression, a sequence of lexemes (enclosed in double at symbols \"@@\", i.e. @@ lexeme1 lexeme2 @@), or a regular text string (which should be specified between triple at symbols \"@@@\", i.e. @@@ text string @@@).\nIn the macro name after the first term, one or more templates may be present. A template is a term that, when matching a sequence of lexemes with the macro identifier, can be replaced by any other single term (effectively, this is pattern/template matching).\nTo create a template term, a dollar sign should be placed at the beginning of its identifier (which corresponds to a qualifier of a local variable), i.e. the macro name @@ FUNC $name @@ will correspond to the sequence of lexemes as FUNC my_func_name as well as FUNC other_name_func.\nTo remove a macro, a special syntax is used: @@@@ name @@@@; or @@@@ two terms @@@@;, i.e. you need to specify the macro identifier between four characters \"@@@@\".\n# Macro body from a text string (as in C/C++ preprocessor) @@macro_str@@ := @@@ string - macro body @@@; # String for the lexer # Removing macro @macro_str @@@@ macro_str @@@@; Macro Arguments and Expansion Macros can be defined with arguments (parameters in parentheses) or without them. If a macro was defined with arguments, their validation will be performed by the macro processor during definition and expansion of the macro. If a macro was defined without arguments, the presence of arguments will be ignored by the macro processor.\nThe macroprocessor considers macros with and without arguments identical, so it is not possible to create two macros with the same name, one with arguments (in parentheses) and the other without.\nTherefore, if you need to use a macro in two different ways (with arguments and without), you should define the macro without arguments, and in this case, the parameter control will be done by the compiler.\n@@ macro @@ := term; # Macro without arguments macro(args); # OK -\u003e term(args); macro; # OK -\u003e term; # But @@ call() @@ := term(); call(); # OK -\u003e term(); call; # Error (@call is defined with arguments) If arguments are specified when defining a macro, the place for their insertion in the body of the macro is written as the name of a local variable with the symbol \"@\" added before it, i.e. @$arg.\nThe place for inserting the number of actual arguments passed is marked by the lexeme \"@$#\". If it is necessary to insert the passed arguments as a dictionary, the place for insertion is marked by the lexeme \"@$*\".\nIf the macro takes an arbitrary number of arguments (the macro arguments are terminated by an ellipsis), the place for their insertion in the body of the macro is marked by the lexeme \"@$…\".\nAnalogous to the C/C++ preprocessor, to concatenate two lexemes into one, the operator \"@##\" is used in the body of the macro, and to convert a lexeme into a text string, the operators @#, @#\", or @#’ are applied, for example, @@macro($arg)@@ := @@ func_ @## @$arg( @#\" arg ) @;, then the call macro(name); will be transformed into func_name (\"name\");\nExamples of using macros:\n# Ordinary macros (the body of the macro is a correct expression) @@ macro @@ := replace(); @@ macro2(arg) @@ := { call(@$arg); call()}; # The body of the macros from a sequence of tokens @@ if(...) @@ := @@ [ @$... ]--\u003e @@; # The expression may not be complete @@ elif(...) @@ := @@ ,[ @$... ]--\u003e @@; @@ else @@ := @@ ,[...]--\u003e @@; # Writing a conditional statement using # the macros defined above @if( condition ){ ... } @elif( condition2 ) { ... } @else { ... }; For example, a loop up to 5:\ncount := 1; [ 1 ] \u003c-\u003e { [ count \u003e 5 ] --\u003e { -- 42 --; }; count+=1; }; This will look more familiar:\ncount := 1; @while( true ) { @if( count \u003e 5 ) { @return 42; }; count += 1; }; ","categories":"","description":"","excerpt":"Macros are also used to transform the original code of NewLang into a …","ref":"/docs/syntax/macros/","tags":"","title":"Macros"},{"body":"Итераторы в NewLang, как и в остальных языках программирования, предназначены для перебора элементов. Но, в отличии от итераторов в С++, итераторы NewLang являются самостоятельными объектами, а не указателями на отдельные элементы объекта-контейнера. Итераторы NewLang поддерживают фильтрацию элементов по имени за счет использования функций обратного вызова.\nДля работы с итераторами используется следующий синтаксис:\n? или ?( текст ) - создание итератора без фильтра или с regex фильтрацией по имени поля ?( func, args… ) - создание итератора с использованием лямбда функции или функции обратного вызова ! или !( количество возвращаемых элементов ) - перебор элементов итератора ?! или !? - получить текущий элемент без перемещение курсора !! - сбросить указатель итератора в начальное состояние (на первый элемент) ?? - создать итератор и сразу его выполнить, возвращая все значения в виде элементов словаря максимально возможного размера. Это своего рода синтаксический сахар для краткой записи последовательности команд ?; !(9223372036854775807);, что удобно использовать при отладке для вывода значений переменных. Для работы с итераторами можно использовании DSL операторы:\niter() - Создать итератор (?) next() - перебор элементов итератора (! или !( количество возвращаемых элементов )) curr() - Получить текущий элемент без перемещение курсора (?! или !?) first() - Сбросить указатель итератора на первый элемент (!!) all() - Создать итератор и сразу его выполнить (??) Примеры создания итераторов с разными фильтрами отбора данных:\niter := dict ? (\"name\"); # Создание итератора для значений с указанным именем iter := dict ? (\"regex.\"); # Создание итератора для полей с префиксом \"regex\" # Чистая функция для фильтрации по значению filter(value) :- { $value \u0026\u0026 $value \u003c 10; }; iter := dict ? (filter); # Создание итератора для значений меньше 10 equal(value, arg) := { $value == arg }; # Обычная функция iter := dict ? (equal, 100); # Создать итератор только для значений 100 Оператор перебора элементов итератора ! возвращает текущий элемент и сдвигает указатель на следующий. Точнее, на количество считанных элементов, так как прочитать элементы из итератора можно не только по одному, а и заданными порциями, например по 10 за один раз, iter ! (10);.\nЕсли указать количество считываемых элементов !(0), то будет возвращен сам элемент, но для значений отличных от нуля будет возвращаться не элемент данных, а словарь с данными, считанными из итератора. Из-за этого операторы ! и !(0) НЕ эквивалентны, т.к. по разному обрабатывают конец данных.\nЛучше всего это показать на примерах для словаря с пятью элементами:\ndict := (1,2,3,4,5,)?; # Создать итератор для словаря dict!; # -\u003e 1 dict!; # -\u003e 2 dict!; # -\u003e 3 dict!; # -\u003e 4 dict!; # -\u003e 5 dict!; # -\u003e будет исключение \"конец итератора\" # Но dict !(0); # -\u003e (1,) dict !(0); # -\u003e (2,) dict !(0); # -\u003e (3,) dict !(0); # -\u003e (4,) dict !(0); # -\u003e (5,) dict !(0); # -\u003e (,) - вернется пустой словарь Так же для чтения итератора можно указывать и отрицательное количество элементов. В этом случае будет возвращаться словарь всегда указанного размера, но элементы в словаре будут присутствовать только в случае чтения реальных данных из итератора:\ndict := (1,2,3,4,5,) ?; # Итератор для словаря с пятью элементами dict !(3); # -\u003e (1,2,3,) dict !(3); # -\u003e (4,5,) dict !(3); # -\u003e (,) # Но dict !(-3); # -\u003e (1,2,3,) dict !(-3); # -\u003e (4,5, :IteratorEnd) dict !(-3); # -\u003e (:IteratorEnd, :IteratorEnd, :IteratorEnd) ","categories":"","description":"","excerpt":"Итераторы в NewLang, как и в остальных языках программирования, …","ref":"/docs/types/iter/","tags":["типы данных","итераторы"],"title":"Итераторы"},{"body":"Итераторы в NewLang, как и в остальных языках программирования, предназначены для перебора элементов. Но, в отличии от итераторов в С++, итераторы NewLang являются самостоятельными объектами, а не указателями на отдельные элементы объекта-контейнера. Итераторы NewLang поддерживают фильтрацию элементов по имени за счет использования функций обратного вызова.\nДля работы с итераторами используется следующий синтаксис:\n? или ?( текст ) - создание итератора без фильтра или с regex фильтрацией по имени поля ?( func, args… ) - создание итератора с использованием лямбда функции или функции обратного вызова ! или !( количество возвращаемых элементов ) - перебор элементов итератора ?! или !? - получить текущий элемент без перемещение курсора !! - сбросить указатель итератора в начальное состояние (на первый элемент) ?? - создать итератор и сразу его выполнить, возвращая все значения в виде элементов словаря максимально возможного размера. Это своего рода синтаксический сахар для краткой записи последовательности команд ?; !(9223372036854775807);, что удобно использовать при отладке для вывода значений переменных. Для работы с итераторами можно использовании DSL операторы:\niter() - Создать итератор (?) next() - перебор элементов итератора (! или !( количество возвращаемых элементов )) curr() - Получить текущий элемент без перемещение курсора (?! или !?) first() - Сбросить указатель итератора на первый элемент (!!) all() - Создать итератор и сразу его выполнить (??) Примеры создания итераторов с разными фильтрами отбора данных:\niter := dict ? (\"name\"); # Создание итератора для значений с указанным именем iter := dict ? (\"regex.\"); # Создание итератора для полей с префиксом \"regex\" # Чистая функция для фильтрации по значению filter(value) :- { $value \u0026\u0026 $value \u003c 10; }; iter := dict ? (filter); # Создание итератора для значений меньше 10 equal(value, arg) := { $value == arg }; # Обычная функция iter := dict ? (equal, 100); # Создать итератор только для значений 100 Оператор перебора элементов итератора ! возвращает текущий элемент и сдвигает указатель на следующий. Точнее, на количество считанных элементов, так как прочитать элементы из итератора можно не только по одному, а и заданными порциями, например по 10 за один раз, iter ! (10);.\nЕсли указать количество считываемых элементов !(0), то будет возвращен сам элемент, но для значений отличных от нуля будет возвращаться не элемент данных, а словарь с данными, считанными из итератора. Из-за этого операторы ! и !(0) НЕ эквивалентны, т.к. по разному обрабатывают конец данных.\nЛучше всего это показать на примерах для словаря с пятью элементами:\ndict := (1,2,3,4,5,)?; # Создать итератор для словаря dict!; # -\u003e 1 dict!; # -\u003e 2 dict!; # -\u003e 3 dict!; # -\u003e 4 dict!; # -\u003e 5 dict!; # -\u003e будет исключение \"конец итератора\" # Но dict !(0); # -\u003e (1,) dict !(0); # -\u003e (2,) dict !(0); # -\u003e (3,) dict !(0); # -\u003e (4,) dict !(0); # -\u003e (5,) dict !(0); # -\u003e (,) - вернется пустой словарь Так же для чтения итератора можно указывать и отрицательное количество элементов. В этом случае будет возвращаться словарь всегда указанного размера, но элементы в словаре будут присутствовать только в случае чтения реальных данных из итератора:\ndict := (1,2,3,4,5,) ?; # Итератор для словаря с пятью элементами dict !(3); # -\u003e (1,2,3,) dict !(3); # -\u003e (4,5,) dict !(3); # -\u003e (,) # Но dict !(-3); # -\u003e (1,2,3,) dict !(-3); # -\u003e (4,5, :IteratorEnd) dict !(-3); # -\u003e (:IteratorEnd, :IteratorEnd, :IteratorEnd) ","categories":"","description":"","excerpt":"Итераторы в NewLang, как и в остальных языках программирования, …","ref":"/ru/docs/types/iter/","tags":["типы данных","итераторы"],"title":"Итераторы"},{"body":"Макросы используются и для превращеня исходного кода NewLang в более привычный синтаксис на основе ключевых слов, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода.\nМакросы в NewLang, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем).\nМакросы обработываются во время работы лексера, т.е. перед передачей последовательности лексем в парсер, что позволяет с помощью маросов изменять фрагменты синтаксиса языка, например, при реализации собственных диалектов DSL.\nОпределение макросов Определение макросов аналогично определению других объектов и состоит из трех частей \u003cимя макроса\u003e \u003cоператор создания/присвоения\u003e \u003cтело макроса\u003e и завершающая точка с запятой “;”, т.е. применяются обычные операторы ::=(::-), = или :=(:-) для создания нового или переопределения уже существующего объекта, а имя макроса указывается между двумя символами \"@@\" и может содержать одну или нескольких лексем (терминов).\nВсе макросы относятся к глобальному пространству имен, поэтому первый термин в имени макроса должен быть уникальным, иначе он будет прекрывать локальные и глобальные переменные при разрешении имен, если они записаны в тексте программы без квалификаторов (сигилов).\nС помощью операторов ::- и :- создаются чистые (гигиеничные) макросы, аргументы и переменные в которых гарантированно не пересекаются с пространством имен программы.\nТелом макроса могут быть корректное выражение языка, последовательность лексем (которые заключается в двойные собачки \"@@\", т.е. @@ лексема1 лексема1 @@) или обычная текстовая строка (которую нужно указать между тройными собачками \"@@@\", т.е. @@@ текстовая строка @@@).\nВ имени макроса после первого термина могут присутствовать один или несколько шаблонов. Шаблон — это термин, который при сопоставлении последовательности лексем с идентификатором макроса может заменяться любым другим одиночным термином (т.е. фактически это сопоставление по образцу/шаблону).\nДля создания термина-шаблона в начале его идентификатора нужно поставить знак доллара (что соответствует квалификатору локальной переменой), т.е. имя макроса @@ FUNC $name @@ будет соответствовать последовательности лексем как FUNC my_func_name, так и FUNC other_name_func.\nДля удаления макроса используется специальный синтаксис: @@@@ name @@@@; или @@@@ два термина @@@@;, т.е. необходимо указать идентификатор макроса между четырмя символами \"@@@@\".\n# Тело макроса из текстовой строки (как в препроцессоре С/С++) @@macro_str@@ := @@@ строка - тело макроса @@@; # Строка для лексера # Удаления макроса @macro_str @@@@ macro_str @@@@; Аргументы макросов и их раскрытие Макросы можно определять как с аргументами (параметрами в скобках), так и без них. Если макрос был определен с аргументами, то их проверка будет выполнятся макропроцессором при определении и раскрытии макроса. Если макрос был определен без аргументов, то их наличие макропроцессором игнорируется.\nМакропроцессор считает макросы с аргументами и без оных идентичными, то нельзя создать два макроса с одинаковыми именами, один из которых будет с аргументами (скобками), а другой без них.\nПоэтому, если требуется использовать макрос в двух разных вариантах (с аргументами и без оных), следует определять макрос без аргументов и в этом случае контроль параметров будет выполнятся компилятором.\n@@ macro @@ := term; # Макрос без аргументов macro(args); # ОК -\u003e term(args); macro; # ОК -\u003e term; # Но @@ call() @@ := term(); call(); # ОК -\u003e term(); call; # Ошибка (@call определен с аргументами) Если при определении макроса указаны аргументы, то место для их вставки в теле макроса записывается как имя локальной переменой, перед которой добавлен символ \"@\", т.е. @$arg.\nМесто для вставки числа реально переданных аргументов отмечается лексемой \"@$#\". Если требуется вставить переданные аргументы в виде словаря, то место для вставки отмечается лексемой \"@$*\".\nЕсли макрос принимае произвольное количество аргументов (аргуметы макроса завершает многоточие), то место их вставки в тело макроса отмечается лексемой \"@$…\".\nПо аналогии с препроцессором С/С++, для соединения двух лексем в одну, в теле макроса используется оператор \"@##\", а для преобразование лексемы в текстову строку применяется операторы @#, @#\" или @#’, например, @@macro($arg)@@ := @@ func_ @## @$arg( @#\" arg ) @;, тогда вызов macro(name); будет преобразован в func_name (\"name\");\nПримеры использования макросов:\n# Обычные макросы (тело макроса корректное выражение) @@ macro @@ := replace(); @@ macro2(arg) @@ := { call(@$arg); call()}; # Тело макросов из последовательности лексем @@ if(...) @@ := @@ [ @$... ]--\u003e @@; # Выражение может быть не полным @@ elif(...) @@ := @@ ,[ @$... ]--\u003e @@; @@ else @@ := @@ ,[...]--\u003e @@; # Запись условного оператора с использованием # определенных выше макросов @if( condition ){ ... } @elif( condition2 ) { ... } @else { ... }; Например цикл до 5:\ncount := 1; [ 1 ] \u003c-\u003e { [ count \u003e 5 ] --\u003e { -- 42 --; }; count+=1; }; Будет выглядеть более привычно:\ncount := 1; @while( true ) { @if( count \u003e 5 ) { @return 42; }; count += 1; }; Далее идеи на будущее Символьное программирование Символьное программирование, часто называемое декларативным программированием, представляет собой парадигму программирования, которая использует математическую логику, отношения и символы для представления знаний и помощи в решении проблем. Вместо того, чтобы сосредотачиваться на описании последовательности операций, необходимых для выполнения вычислений, как в императивном программировании, символическое программирование делает упор на выражении отношений и ограничений между структурами данных, уделяя особое внимание «что», а не «как».\nВ контексте парадигм программирования символическое программирование часто противопоставляется процедурному или императивному программированию, где программы определяют пошаговые процедуры для достижения своих целей. В то время как императивное программирование фокусируется на описании потока управления с использованием таких конструкций, как циклы и условные выражения, для управления выполнением, символическое программирование сосредоточено на выражении фактов о проблеме и позволяет выполнению естественным образом выводить последующие последствия из предоставленной информации.\nОдним из основных преимуществ символьного программирования является его способность обеспечивать более высокий уровень абстракции, что упрощает анализ кода и снижает вероятность ошибок. Непосредственно выражая отношения и ограничения, символическое программирование позволяет разработчикам сосредоточиться на моделировании и спецификации проблем, позволяя базовой системе управлять реализацией и выполнением алгоритмов.\nСуществует несколько языков программирования и сред, использующих парадигму символьного программирования, например Prolog, Lisp и Haskell. Например, Пролог — это язык логического программирования, который позволяет разработчикам выражать взаимосвязи и факты о проблемных областях, в то время как выполнение автоматически обосновывает и извлекает новые факты на основе исходной информации. В том же духе Лисп, функциональный язык программирования, использует символьные вычисления для манипулирования структурами данных и выполнения сложных операций над ними, используя краткий и математически обоснованный синтаксис. Haskell, еще один функциональный язык программирования, использует строгую типизацию и ленивые вычисления, чтобы обеспечить символическое рассуждение и облегчить эффективное создание программ.\nСимвольное программирование может быть полезным в широком спектре проблемных областей, включая искусственный интеллект, экспертные системы, программирование логики ограничений и символьную математику, среди других. Более высокий уровень абстракции, обеспечиваемый декларативными языками программирования, облегчает разработку сложных систем, сводя к минимуму вероятность ошибки и улучшая удобство обслуживания. В частности, использование символьного программирования в искусственном интеллекте позволяет разработчикам создавать системы представления знаний и механизмы рассуждения, которые можно применять для обработки естественного языка, машинного обучения и автоматического доказательства теорем.\nРазличие между символьным программированием и препроцессором\nЗадача препроцессора - раскрыть(расширить) макрос, тогда как при символьном программировании нужно сокращать (сворачивать) выражения Препроцессор обрабатывает последовательности лексем (плоские данные), тогда как символьное программирование оперирует выражениями (деревом лексем) Макрос у препроцессора идентифицируется первым термином, и если макрос не может быть раскрыт, то возникает ошибка. В символьном программировани требуется точное соответствие всего выражения и только в этом случае производится сокращение выражения. Предпосылки для реализации символьного программирования Компилятор - интерепретатор с REPL и обработка AST как во время компиляции, так и во время выполнения. Необходимо добавить конструкции для определения правил символьного программрования (чистые функции?) Необходимо добавить конструкцию для вычисления выражений в символьном программировании.\nWolfram https://habr.com/ru/articles/772984/\ndiffRules = { Sin[x] -\u003e Cos[x], Cos[x] -\u003e -Sin[x], x^2 -\u003e 2*x, x -\u003e 1, Log[x] -\u003e 1/x }; diffRules := ( Sin(x) @-\u003e Cos(x), Cos(x) @-\u003e -Sin(x), x^2 @-\u003e 2*x, x @-\u003e 1, Log(x) @-\u003e 1\\x, ); expr @-\u003e Sin(x) - x^2 + Log(x); # И применим к нему правила дифференцирования #expr /. diffRules #(* 1/x - 2 x + Cos[x] *) sym := SymEval(expr, diffRules); res := Eval(sym, x=0.123); expr = a^2 + 3 * b^3 - c^4 + 2 * x^2 - x + 4*c + 3 И я хочу это выражение линеаризовать, т.е. отбросить все степени выше первой. Я могу сделать это напрямую, как в примерах выше: expr /. { a^2 -\u003e 0, b^3 -\u003e 0, c^4 -\u003e 0, x^2 -\u003e 0 } (* 3 + 4 c - x *) Но это слишком неудобно. Что если я не знаю ни точную степень, ни имя переменной? Как просто указать, что нужно заменить все места, где встречается возведение в степень на ноль? Это можно сделать при помощи шаблонов вот так: expr /. Power[_, _] -\u003e 0 (* 3 + 4 c - x *) Либо вот так: expr /. _ ^ _ -\u003e 0 (* 3 + 4 c - x *) :diffRules() := { {@ Sin(x) @} ::- {@ Cos(x) @}; Cos(x) @-\u003e -Sin(x), x^2 @-\u003e 2*x, x @-\u003e 1, Log(x) @-\u003e 1\\x, }; expr @-\u003e Sin(x) - x^2 + Log(x); # И применим к нему правила дифференцирования #expr /. diffRules #(* 1/x - 2 x + Cos[x] *) sym := SymEval(expr, diffRules); res := Eval(sym, x=0.123); ","categories":"","description":"","excerpt":"Макросы используются и для превращеня исходного кода NewLang в более …","ref":"/ru/docs/syntax/macros/","tags":"","title":"Макросы"},{"body":"Пусто (:None) :None (пусто) — не содержит значения (точнее имеет одно значение :None). Указывается в тексте программы как один подчерк «_». Значение None имеют не инициализированные переменные и при попытке чтения из такой переменной возникает ошибка.\nТип переменной может быть явно указан или выведен автоматически из присваиваемого значения. Присвоить новое значение уже инициализированной переменной можно только для совместимого типа, так как неявное преобразование типов не допускаются.\n$var := _; # Создать не инициализированную переменную $var2 := var; # Ошибка!!! Нельзя прочитать не инициализированную переменную var $var = 1000; # У переменной будет тип Short (минимальный размер для хранения значения) $var = 0,5; # Ошибка!!! Short ← Float не совместимы $var = _; # Очистить значение переменной $var = 0,5; # Теперь можно, т. к. None совместим с любым типом Диапазон (:Range) Диапазон — специальный тип данных, являющейся приблизительным аналогом типа «генератор» в Python. К диапазону можно обращаться как к итератору и он будет поочередно выдавать элементы в указанном интервале с заданным шагом. Диапазон в тексте программы указывается как два или три элемента через две точки, например 1..5 — диапазон от единицы до пяти с шагом по умолчанию 1. В качестве параметров диапазона можно указывать не только литералы, но и имена переменных и даже рациональные числа. Например, 0,1..$stop..0,1 — диапазон от 0,1 до значения, указанного в переменной $stop с шагом 0,1 или 0..1\\10 - диапазон рациональных числе от 0 до 10.\nДиапазон целых чисел можно использовать в качестве индекса у тензоров (точнее, у любых объектов, которые допускают доступ к своим элементам по индексу, т.е. тензоры, словари и текстовые строки). Фактический, это поведение аналогично slice в языке Python и array[1:5] в Python означает тоже самое, что и array[1..5] в NewLang.\nВ качестве индекса у тензоров еще можно указать произвольное количество измерений с помощью многоточия, т.е.\n$tensor[…, 0] = 0; # Обнулить все первые элементы в каждом измерении. В будущем можно будет добавить возможность указывать индексы элементов с помощь диапазонов\n$tensor = :Tensor[12](4..4 = 29, 2..3 = 15, , 7..9..2 = 7, 10 ...); # [0, 0, 15, 15, 29, 0, 0, 7, 0, 7, 10, 10,] Поток (:Thread) Поток — специальный тип данных, который запускает функцию в отдельном потоке, который выполнтеся паралельно основному потоку приложения. Поток созадется в остановленном виде и для его запуска необходимо вызвать метод start(), а чтобы дождаться завершения потока вызывается метод join().\nrand():Int32 := %rand; usleep(usec:DWord64):None := %usleep; printf(format:FmtChar, ...):Int32 := %printf; func(count:Integer, target:String) := { $iter := 1..$count?; # Итератор для диапазона от 1 до $count [ $iter ?! ] \u003c-\u003e { # Цикл, пока итератор валидный $step := $iter!; # Получить текущий и перейти на следующий элемент итератора printf('Number %d from %s!', $step, $target); usleep( rand() % 1000 ); # Случайная задержка } } thread = :Thread(func, 5, 'thread'); thread.start(); func(5, 'main'); thread.join(); Number 1 from the thread! Number 1 from the main! Number 2 from the thread! Number 2 from the main! Number 3 from the thread! Number 4 from the thread! Number 3 from the main! Number 4 from the main! Number 5 from the main! Number 5 from the thread!\nУсловные переменные (condvars). Сходны с событиями, но не являются объектами, занимающими память — используется только адрес переменной, понятие «содержимое переменной» не существует, в качестве условной переменной может использоваться адрес произвольного объекта. В отличие от событий, установка условной переменной в просигнализированное состояние не влечёт за собой никаких последствий в случае, если на данный момент нет потоков, ожидающих на переменной. Установка события в аналогичном случае влечёт за собой запоминание состояния «просигнализировано» внутри самого события, после чего следующие потоки, желающие ожидать события, продолжают исполнение немедленно без остановки. Для полноценного использования такого объекта необходима также операция «освободить mutex и ожидать условную переменную атомарно». Активно используются в UNIX-подобных ОС. Дискуссии о преимуществах и недостатках событий и условных переменных являются заметной частью дискуссий о преимуществах и недостатках Windows и UNIX.\nERESOURCE. Мьютекс, поддерживающий рекурсивный захват, с семантикой разделяемого или эксклюзивного захвата. Семантика: объект может быть либо свободен, либо захвачен произвольным числом потоков разделяемым образом, либо захвачен всего одним потоком эксклюзивным образом. Любые попытки осуществить захваты, нарушающее это правило, приводят к блокировке потока до тех пор, пока объект не освободится так, чтобы сделать захват разрешённым. Также есть операции вида TryToAcquire — никогда не блокирует поток, либо захватывает, либо (если нужна блокировка) возвращает FALSE, ничего не делая. Используется в ядре Windows, особенно в файловых системах — так, например, любому кем-то открытому дисковому файлу соответствует структура FCB, в которой есть 2 таких объекта для синхронизации доступа к размеру файла. Один из них — paging IO resource — захватывается эксклюзивно только в пути обрезания файла, и гарантирует, что в момент обрезания на файле нет активного ввода-вывода от кэша и от отображения в память.\nИнтерфейс операционной системы (:System) Для доступа к различным функциям операционной системы NewLang предоставляет специальный тип данных :System. Он позволяет запускать системные команды и переопределять для них параметры системного окружения.\nВыполнение команды происходит при вызове метода run(), которому нужно передать имя системной команды и при необходимости дополнительные аргументы командной строки.\nРезультат выполнения команды (текстовый вывод, код завершения и т.д.) доступен как отдельные свойства объекта.\nПример:\n:System().run(\"echo\", \"Hello from the other side!\"); os := :System(); home_dir := os.run(\"cd\", \"~\"); printf(\"`cd ~` ran with exit code %d\", os.exitcode()); unknown_dir := os.run(\"cd\", \"doesnotexist\"); printf(\"`cd doesnotexis` ran with exit code %d\", os.exitcode()); Первая строка делает запускает команду echo.\nПотом создается объект :System и далее мы создаем две переменные, в которых хранятся результаты этой выполнения команды cd, которые изменяют каталог на домашнюю папку и на несуществующую папку.\nЗапустив этот файл, мы увидим:\nHello from the other side! `cd ~` ran with exit code 0 sh: line 0: cd: doesnotexist: No such file or directory `cd doesnotexist` ran with exit code 256 Первая строка - результат выполнения команды echo.\nДалее команда cd выполняется успешно и изменяет каталог на домашний. Следовательно, код возврата ноль, который получаем с помощью вызова метода exitcode().\nПоследняя команда cd выполняется с ошибкой, так как пытается изменить каталог на несуществующую папку.\nПростой варинат выполнение системной команды Есть упрощенный вариант выполнения системной команды с помощью заключения строки выполнения в обратные кавычки (как в bash).\n`echo Hello from the other side!`; В этом случае системная команда :System.run() сразу выполняется, а её текстовый вывод сохраняется в текстовую строку с широкими символами (:StrWide).\nЧтобы получить код возврата (например, чтобы проверить результат завершения на ошибки), можно обратится к результату выполнения последней команды $^.exitcode() или сохранить результат выполнения предыдущей команды в отдельную переменню, которая будет иметь тип :System.\n`echo Hello from the other side!`; res := $^; printf(\"`cd doesnotexis` ran with exit code %d\", res.exitcode()); В дальнейшем планируется расширить возможности интерфейса с операционной системой фоновое выполнение программ (useless_cat_call = subprocess.run([“cat”], stdout=subprocess.PIPE, text=True, input=“Hello from the other side”)) переназначение ввода/вывода (list_dir = subprocess.Popen([“ls”, “-l”]); list_dir.wait()) чтение/изменние перемнных окржения Еще пример возможностей для расширения os.name - имя операционной системы. Доступные варианты: ‘posix’, ’nt’, ‘mac’, ‘os2’, ‘ce’, ‘java’. os.environ - словарь переменных окружения. Изменяемый (можно добавлять и удалять переменные окружения). os.getlogin() - имя пользователя, вошедшего в терминал (Unix). os.getpid() - текущий id процесса. os.uname() - информация об ОС. возвращает объект с атрибутами: sysname - имя операционной системы, nodename - имя машины в сети (определяется реализацией), release - релиз, version - версия, machine - идентификатор машины. os.access(path, mode, *, dir_fd=None, effective_ids=False, follow_symlinks=True) - проверка доступа к объекту у текущего пользователя. Флаги: os.F_OK - объект существует, os.R_OK - доступен на чтение, os.W_OK - доступен на запись, os.X_OK - доступен на исполнение. os.chdir(path) - смена текущей директории. os.chmod(path, mode, *, dir_fd=None, follow_symlinks=True) - смена прав доступа к объекту (mode - восьмеричное число). os.chown(path, uid, gid, *, dir_fd=None, follow_symlinks=True) - меняет id владельца и группы (Unix). os.getcwd() - текущая рабочая директория. os.link(src, dst, *, src_dir_fd=None, dst_dir_fd=None, follow_symlinks=True) - создаёт жёсткую ссылку. os.listdir(path=\".\") - список файлов и директорий в папке. os.mkdir(path, mode=0o777, *, dir_fd=None) - создаёт директорию. OSError, если директория существует. os.makedirs(path, mode=0o777, exist_ok=False) - создаёт директорию, создавая при этом промежуточные директории. os.remove(path, *, dir_fd=None) - удаляет путь к файлу. os.rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None) - переименовывает файл или директорию из src в dst. os.renames(old, new) - переименовывает old в new, создавая промежуточные директории. os.replace(src, dst, *, src_dir_fd=None, dst_dir_fd=None) - переименовывает из src в dst с принудительной заменой. os.rmdir(path, *, dir_fd=None) - удаляет пустую директорию. os.removedirs(path) - удаляет директорию, затем пытается удалить родительские директории, и удаляет их рекурсивно, пока они пусты. os.symlink(source, link_name, target_is_directory=False, *, dir_fd=None) - создаёт символическую ссылку на объект. os.sync() - записывает все данные на диск (Unix). os.truncate(path, length) - обрезает файл до длины length. os.utime(path, times=None, *, ns=None, dir_fd=None, follow_symlinks=True) - модификация времени последнего доступа и изменения файла. Либо times - кортеж (время доступа в секундах, время изменения в секундах), либо ns - кортеж (время доступа в наносекундах, время изменения в наносекундах). os.walk(top, topdown=True, onerror=None, followlinks=False) - генерация имён файлов в дереве каталогов, сверху вниз (если topdown равен True), либо снизу вверх (если False). Для каждого каталога функция walk возвращает кортеж (путь к каталогу, список каталогов, список файлов). os.system(command) - исполняет системную команду, возвращает код её завершения (в случае успеха 0). os.urandom(n) - n случайных байт. Возможно использование этой функции в криптографических целях. ","categories":"","description":"","excerpt":"Пусто (:None) :None (пусто) — не содержит значения (точнее имеет одно …","ref":"/docs/types/other/","tags":["типы данных"],"title":"Другие типы данных"},{"body":"Пусто (:None) :None (пусто) — не содержит значения (точнее имеет одно значение :None). Указывается в тексте программы как один подчерк «_». Значение None имеют не инициализированные переменные и при попытке чтения из такой переменной возникает ошибка.\nТип переменной может быть явно указан или выведен автоматически из присваиваемого значения. Присвоить новое значение уже инициализированной переменной можно только для совместимого типа, так как неявное преобразование типов не допускаются.\n$var := _; # Создать не инициализированную переменную $var2 := var; # Ошибка!!! Нельзя прочитать не инициализированную переменную var $var = 1000; # У переменной будет тип Short (минимальный размер для хранения значения) $var = 0,5; # Ошибка!!! Short ← Float не совместимы $var = _; # Очистить значение переменной $var = 0,5; # Теперь можно, т. к. None совместим с любым типом Диапазон (:Range) Диапазон — специальный тип данных, являющейся приблизительным аналогом типа «генератор» в Python. К диапазону можно обращаться как к итератору и он будет поочередно выдавать элементы в указанном интервале с заданным шагом. Диапазон в тексте программы указывается как два или три элемента через две точки, например 1..5 — диапазон от единицы до пяти с шагом по умолчанию 1. В качестве параметров диапазона можно указывать не только литералы, но и имена переменных и даже рациональные числа. Например, 0,1..$stop..0,1 — диапазон от 0,1 до значения, указанного в переменной $stop с шагом 0,1 или 0..1\\10 - диапазон рациональных числе от 0 до 10.\nДиапазон целых чисел можно использовать в качестве индекса у тензоров (точнее, у любых объектов, которые допускают доступ к своим элементам по индексу, т.е. тензоры, словари и текстовые строки). Фактический, это поведение аналогично slice в языке Python и array[1:5] в Python означает тоже самое, что и array[1..5] в NewLang.\nВ качестве индекса у тензоров еще можно указать произвольное количество измерений с помощью многоточия, т.е.\n$tensor[…, 0] = 0; # Обнулить все первые элементы в каждом измерении. В будущем можно будет добавить возможность указывать индексы элементов с помощь диапазонов\n$tensor = :Tensor[12](4..4 = 29, 2..3 = 15, , 7..9..2 = 7, 10 ...); # [0, 0, 15, 15, 29, 0, 0, 7, 0, 7, 10, 10,] Поток (:Thread) Поток — специальный тип данных, который запускает функцию в отдельном потоке, который выполнтеся паралельно основному потоку приложения. Поток созадется в остановленном виде и для его запуска необходимо вызвать метод start(), а чтобы дождаться завершения потока вызывается метод join().\nrand():Int32 := %rand; usleep(usec:DWord64):None := %usleep; printf(format:FmtChar, ...):Int32 := %printf; func(count:Integer, target:String) := { $iter := 1..$count?; # Итератор для диапазона от 1 до $count [ $iter ?! ] \u003c-\u003e { # Цикл, пока итератор валидный $step := $iter!; # Получить текущий и перейти на следующий элемент итератора printf('Number %d from %s!', $step, $target); usleep( rand() % 1000 ); # Случайная задержка } } thread = :Thread(func, 5, 'thread'); thread.start(); func(5, 'main'); thread.join(); Number 1 from the thread! Number 1 from the main! Number 2 from the thread! Number 2 from the main! Number 3 from the thread! Number 4 from the thread! Number 3 from the main! Number 4 from the main! Number 5 from the main! Number 5 from the thread!\nУсловные переменные (condvars). Сходны с событиями, но не являются объектами, занимающими память — используется только адрес переменной, понятие «содержимое переменной» не существует, в качестве условной переменной может использоваться адрес произвольного объекта. В отличие от событий, установка условной переменной в просигнализированное состояние не влечёт за собой никаких последствий в случае, если на данный момент нет потоков, ожидающих на переменной. Установка события в аналогичном случае влечёт за собой запоминание состояния «просигнализировано» внутри самого события, после чего следующие потоки, желающие ожидать события, продолжают исполнение немедленно без остановки. Для полноценного использования такого объекта необходима также операция «освободить mutex и ожидать условную переменную атомарно». Активно используются в UNIX-подобных ОС. Дискуссии о преимуществах и недостатках событий и условных переменных являются заметной частью дискуссий о преимуществах и недостатках Windows и UNIX.\nERESOURCE. Мьютекс, поддерживающий рекурсивный захват, с семантикой разделяемого или эксклюзивного захвата. Семантика: объект может быть либо свободен, либо захвачен произвольным числом потоков разделяемым образом, либо захвачен всего одним потоком эксклюзивным образом. Любые попытки осуществить захваты, нарушающее это правило, приводят к блокировке потока до тех пор, пока объект не освободится так, чтобы сделать захват разрешённым. Также есть операции вида TryToAcquire — никогда не блокирует поток, либо захватывает, либо (если нужна блокировка) возвращает FALSE, ничего не делая. Используется в ядре Windows, особенно в файловых системах — так, например, любому кем-то открытому дисковому файлу соответствует структура FCB, в которой есть 2 таких объекта для синхронизации доступа к размеру файла. Один из них — paging IO resource — захватывается эксклюзивно только в пути обрезания файла, и гарантирует, что в момент обрезания на файле нет активного ввода-вывода от кэша и от отображения в память.\nИнтерфейс операционной системы (:System) Для доступа к различным функциям операционной системы NewLang предоставляет специальный тип данных :System. Он позволяет запускать системные команды и переопределять для них параметры системного окружения.\nВыполнение команды происходит при вызове метода run(), которому нужно передать имя системной команды и при необходимости дополнительные аргументы командной строки.\nРезультат выполнения команды (текстовый вывод, код завершения и т.д.) доступен как отдельные свойства объекта.\nПример:\n:System().run(\"echo\", \"Hello from the other side!\"); os := :System(); home_dir := os.run(\"cd\", \"~\"); printf(\"`cd ~` ran with exit code %d\", os.exitcode()); unknown_dir := os.run(\"cd\", \"doesnotexist\"); printf(\"`cd doesnotexis` ran with exit code %d\", os.exitcode()); Первая строка делает запускает команду echo.\nПотом создается объект :System и далее мы создаем две переменные, в которых хранятся результаты этой выполнения команды cd, которые изменяют каталог на домашнюю папку и на несуществующую папку.\nЗапустив этот файл, мы увидим:\nHello from the other side! `cd ~` ran with exit code 0 sh: line 0: cd: doesnotexist: No such file or directory `cd doesnotexist` ran with exit code 256 Первая строка - результат выполнения команды echo.\nДалее команда cd выполняется успешно и изменяет каталог на домашний. Следовательно, код возврата ноль, который получаем с помощью вызова метода exitcode().\nПоследняя команда cd выполняется с ошибкой, так как пытается изменить каталог на несуществующую папку.\nПростой варинат выполнение системной команды Есть упрощенный вариант выполнения системной команды с помощью заключения строки выполнения в обратные кавычки (как в bash).\n`echo Hello from the other side!`; В этом случае системная команда :System.run() сразу выполняется, а её текстовый вывод сохраняется в текстовую строку с широкими символами (:StrWide).\nЧтобы получить код возврата (например, чтобы проверить результат завершения на ошибки), можно обратится к результату выполнения последней команды $^.exitcode() или сохранить результат выполнения предыдущей команды в отдельную переменню, которая будет иметь тип :System.\n`echo Hello from the other side!`; res := $^; printf(\"`cd doesnotexis` ran with exit code %d\", res.exitcode()); В дальнейшем планируется расширить возможности интерфейса с операционной системой фоновое выполнение программ (useless_cat_call = subprocess.run([“cat”], stdout=subprocess.PIPE, text=True, input=“Hello from the other side”)) переназначение ввода/вывода (list_dir = subprocess.Popen([“ls”, “-l”]); list_dir.wait()) чтение/изменние перемнных окржения Еще пример возможностей для расширения os.name - имя операционной системы. Доступные варианты: ‘posix’, ’nt’, ‘mac’, ‘os2’, ‘ce’, ‘java’. os.environ - словарь переменных окружения. Изменяемый (можно добавлять и удалять переменные окружения). os.getlogin() - имя пользователя, вошедшего в терминал (Unix). os.getpid() - текущий id процесса. os.uname() - информация об ОС. возвращает объект с атрибутами: sysname - имя операционной системы, nodename - имя машины в сети (определяется реализацией), release - релиз, version - версия, machine - идентификатор машины. os.access(path, mode, *, dir_fd=None, effective_ids=False, follow_symlinks=True) - проверка доступа к объекту у текущего пользователя. Флаги: os.F_OK - объект существует, os.R_OK - доступен на чтение, os.W_OK - доступен на запись, os.X_OK - доступен на исполнение. os.chdir(path) - смена текущей директории. os.chmod(path, mode, *, dir_fd=None, follow_symlinks=True) - смена прав доступа к объекту (mode - восьмеричное число). os.chown(path, uid, gid, *, dir_fd=None, follow_symlinks=True) - меняет id владельца и группы (Unix). os.getcwd() - текущая рабочая директория. os.link(src, dst, *, src_dir_fd=None, dst_dir_fd=None, follow_symlinks=True) - создаёт жёсткую ссылку. os.listdir(path=\".\") - список файлов и директорий в папке. os.mkdir(path, mode=0o777, *, dir_fd=None) - создаёт директорию. OSError, если директория существует. os.makedirs(path, mode=0o777, exist_ok=False) - создаёт директорию, создавая при этом промежуточные директории. os.remove(path, *, dir_fd=None) - удаляет путь к файлу. os.rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None) - переименовывает файл или директорию из src в dst. os.renames(old, new) - переименовывает old в new, создавая промежуточные директории. os.replace(src, dst, *, src_dir_fd=None, dst_dir_fd=None) - переименовывает из src в dst с принудительной заменой. os.rmdir(path, *, dir_fd=None) - удаляет пустую директорию. os.removedirs(path) - удаляет директорию, затем пытается удалить родительские директории, и удаляет их рекурсивно, пока они пусты. os.symlink(source, link_name, target_is_directory=False, *, dir_fd=None) - создаёт символическую ссылку на объект. os.sync() - записывает все данные на диск (Unix). os.truncate(path, length) - обрезает файл до длины length. os.utime(path, times=None, *, ns=None, dir_fd=None, follow_symlinks=True) - модификация времени последнего доступа и изменения файла. Либо times - кортеж (время доступа в секундах, время изменения в секундах), либо ns - кортеж (время доступа в наносекундах, время изменения в наносекундах). os.walk(top, topdown=True, onerror=None, followlinks=False) - генерация имён файлов в дереве каталогов, сверху вниз (если topdown равен True), либо снизу вверх (если False). Для каждого каталога функция walk возвращает кортеж (путь к каталогу, список каталогов, список файлов). os.system(command) - исполняет системную команду, возвращает код её завершения (в случае успеха 0). os.urandom(n) - n случайных байт. Возможно использование этой функции в криптографических целях. ","categories":"","description":"","excerpt":"Пусто (:None) :None (пусто) — не содержит значения (точнее имеет одно …","ref":"/ru/docs/types/other/","tags":["типы данных"],"title":"Другие типы данных"},{"body":"Native (machine) data can be variables or functions, and the names of native objects start with the percent symbol “%”.\nIn the case of variables, these are binary data located in a single continuous area of machine memory at a specific address and have a strictly defined format.\nTo use existing libraries, you need to import the native object, thereby creating an object NewLang, but with an implementation in another language, for example, in C/C++.\nThe syntax for importing native objects is the same as for creating regular language objects, only the name of the native object needs to be specified as the right operand in the creation operator.\nWhen importing a native object, it is necessary to always specify the variable types, as well as the types of arguments and return values for functions.\nIf the data types of the created object and the native object match (i.e., no type conversion is required), then the native object name can be specified with an ellipsis, which means that the data types will replicate those specified at the left operand.\n:FILE ::= :Plain; fopen(filename:StrChar, modes:StrChar):FILE ::= %fopen...; fclose(f:FILE):Int32 ::= %fclose...; fflush(f:FILE):Int32 ::= %fflush...; fprintf(f:FILE, format:FmtChar, ...):Int32 ::= %fprintf...; fremove(filename:String):Int32 ::= %remove...; frename(old:String, new:String):Int32 ::= %rename...; The following description is under development.\n","categories":"","description":"","excerpt":"Native (machine) data can be variables or functions, and the names of …","ref":"/docs/types/native/","tags":["типы данных","системые типы","коллекции"],"title":"Native Data Types"},{"body":"Нативные типы данных Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента “%”.\nВ случае переменных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определенный формат.\nЧтобы использовать уже существующие библиотеки, нужно импортировать нативный объект, тем самым создав объкт NewLang, но с реализацией на другом языке, например на С/С++.\nСинтаксис импорта нативных объектов такой же, как и для создания обычных объектов языка, только в качестве правого операнда в операторе создания требуется указать имя нативнного объекта.\nПри импорте нативного объекта необходимо всегда указывать типы переменных, а также типы аргументов и возвращаемых значений для функций.\nЕсли типы данных у создаваемого и нативного объекта совпадают (т.е. не требуется преобразование типов), то нативное имя объекта можно указать с многоточием, которое означает, что типы данных будут повторять заданные у левого операнда.\n:FILE ::= :Plain; fopen(filename:StrChar, modes:StrChar):FILE ::= %fopen...; fclose(f:FILE):Int32 ::= %fclose...; fflush(f:FILE):Int32 ::= %fflush...; fprintf(f:FILE, format:FmtChar, ...):Int32 ::= %fprintf...; fremove(filename:String):Int32 ::= %remove...; frename(old:String, new:String):Int32 ::= %rename...; Последующее описание находится в процессе разработки.\n:Pointer — указатель на системную область памяти или нативную функцию Так как любой программе приходится взаимодействовать с внешним миром, то по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип :Pointer. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. Но можно вывести его значение, например для отладки.\n:Plain — указатель на представление данных в бинарном виде Для взаимодействия с внешними библиотеками требуется еще и обмен данными. И для этих целей служит тип данных :Plain — который также является указателем, но на двоичное представление данных в области памяти. Конечно, если их можно представить в виде одного фрагмента.\nПеречисление, структура и объединение :Enum, :Struct и :Union — это такие же словари, только на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера. Эти типы данных так же относятся к группе :Plain и могут быть представлены в двоичном виде в одной области машинной памяти.\n","categories":"","description":"","excerpt":"Нативные типы данных Нативными (машинные) данными могут быть как …","ref":"/ru/docs/types/native/","tags":["типы данных","системые типы","коллекции"],"title":"Нативные типы"},{"body":"Несмотря на динамическую типизацию языка, если тип переменной указан явно, то автоматическое приведение типов не выполняется, и чтобы присвоить переменой значение не совместимого типа, требуется его явное преобразование.\nТак как символьные названия типов относятся к деталям реализации, то явное преобразование в конкретный тип данных производится с помощью вызова функции с именем типа, т.е. :Bool(), :StrWide(), :Int64() и т.д.\nПримеры:\nСтроки и тензоры # Создать тензор из строки широких символов с автоматическим выводом типа #(тип Int32 будет на системах с Linux, а под Windows тип тензора будет Int16) \u003e tstr := :Tensor(\"Тест\"); [1058, 1077, 1089, 1090,]:Int32 # Тоже самое, но тензор заданной размерности \u003e t2 := :Tensor[2,2](\"Тест\"); [ [1058, 1077,], [1089, 1090,], ]:Int32 # Создать символьную строку из тензора \u003e :StrWide(tstr) Тест # Изменить тип данных тензора без изменения размерности \u003e :Float64(t2) [ [1058, 1077,], [1089, 1090,], ]:Float64 # Изменить размерность тензора и его тип # (в данном случае с частичной потерей данных) \u003e t3 := :Int8[4]( t2 ) [34, 53, 65, 66,]:Int8 Словари # Создать тензор из словаря \u003e:Tensor( (1,2,3,) ); [1, 2, 3,]:Int8 # Преобразовать байтовую строку в тензор \u003e:Tensor( 'first second' ) [102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Int8 # Получаем тензор из словаря с такими же данными \u003e:Tensor( ('first', space=32, second='second',) ) [102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Int8 ","categories":"","description":"","excerpt":"Несмотря на динамическую типизацию языка, если тип переменной указан …","ref":"/docs/types/convert/","tags":["типы данных"],"title":"Преобразование типов"},{"body":"Несмотря на динамическую типизацию языка, если тип переменной указан явно, то автоматическое приведение типов не выполняется, и чтобы присвоить переменой значение не совместимого типа, требуется его явное преобразование.\nТак как символьные названия типов относятся к деталям реализации, то явное преобразование в конкретный тип данных производится с помощью вызова функции с именем типа, т.е. :Bool(), :StrWide(), :Int64() и т.д.\nПримеры:\nСтроки и тензоры # Создать тензор из строки широких символов с автоматическим выводом размера и типа данных #(тип Int32 будет на системах с Linux, а под Windows тип тензора будет Int16) \u003e tstr := :Tensor[...](\"Тест\"); [1058, 1077, 1089, 1090,]:Int32 # Тоже самое, но тензор заданной размерности \u003e t2 := :Tensor[2,2](\"Тест\"); [ [1058, 1077,], [1089, 1090,], ]:Int32 # Создать символьную строку из тензора \u003e :StrWide(tstr) Тест # Изменить тип данных тензора без изменения размерности \u003e :Float64[...](t2) [ [1058, 1077,], [1089, 1090,], ]:Float64 # Изменить размерность тензора и его тип # (в данном случае с частичной потерей данных) \u003e t3 := :Int8[4]( t2 ) [34, 53, 65, 66,]:Int8 # Логическое значение - скаляр \u003e:Bool( [0, 53, 65, 66,] ); 1:Bool # Или так (тензор нулевой размерности) \u003e:Bool[0]( [0, 53, 65, 66,] ); 1:Bool # Тензор логических значений без изменения размера \u003e:Bool[_]( [0, 53, 65, 66,] ); [0, 1, 1, 1,]:Bool Словари # Создать тензор из словаря с автоматическим выводом размера \u003e:Tensor[...]( (1,2,3,) ); [1, 2, 3,]:Int8 # Преобразовать байтовую строку в одномерный тензор \u003e:Tensor[_]( 'first second' ) [102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Int8 # Получаем тензор из словаря с такими же данными \u003e:Tensor[...]( ('first', space=32, second='second',) ) [102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Int8 # Логическое значение - скаляр \u003e:Bool( (0,1,2,3,) ); 1:Bool # Тензор логических значений \u003e:Bool[...]( (0,1,2,3,) ); [0, 1, 1, 1]:Bool # Различия между \"...\" и \"_\" # Автоматический вывод размеров измерений \u003e:Tensor[...]( ((1,2,3,), (4,5,6,), (7,8,9,),) ); [ [1, 2, 3,], [4, 5, 6,], [7, 8, 9,] ]:Int8 # Одномерный тензор с произвольным размером \u003e:Tensor[_]( ((1,2,3,), (4,5,6,), (7,8,9,),) ); [ 1, 2, 3, 4, 5, 6, 7, 8, 9,]:Int8 ","categories":"","description":"","excerpt":"Несмотря на динамическую типизацию языка, если тип переменной указан …","ref":"/ru/docs/types/convert/","tags":["типы данных"],"title":"Преобразование типов"},{"body":"Системные свойства Несмотря на то, что не все объекты NewLang являются классами с точки зрения реализованной концепции ООП, тем не менее, каждый объект имеет системные свойства, которые можно считать во время выполнения как обычные свойства объекта:\nУ всех переменных (объектов) есть системные свойства __name__ - краткое имя переменной (объекта)\n__full_name__ - полное имя переменной, включая имя модуля и пространство имен\n__type__ - текущий тип переменной. Может изменится при некоторых операциях\n__type_fixed__ - тип переменной (объекта) который не может измениться (ограничитель)\n__module__ - имя модуля в котором определена переменная (объект)\n__class__ - имя класса переменной или пусто, если объект не является классом\n__base__ - словарь со списком базовых классов или пусто, если объект не является классом\n__size__ - количество элементов у объекта, если применимо или :None\n__doc__ - документация по текущему объекту (если есть, иначе пустая строка)\n__str__ - строковое представление объекта для дампа\n__source__ - исходный текст модуля или функции\nСистемные свойства у модулей __file__ - полный путь к файлу модуля (соответствует С/С++ макросу __FILE__) __timestamp__ - дата и время последней модификации файла модуля (соответствует макросу С/С++ __TIMESTAMP__) __md5__ - хеш исходных данных модуля (соответствует макросу __MD5__) DSL Особенности ассоциативной памяти Синтаксис языка NewLang основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например if, чем комбинация минус минус правая угловая скобка –\u003e. Из-за этого имеет смысл использовать не “чистый” базовый синтаксис, а более привычный диалект с использованием ключевых слов.\nСинтаксис на ключевых словах В файле dsl.nlp находится набор макросов, которые расширяют базовый синтаксис NewLang, основанный на правилах, набором предопределенных ключевых слов как в классических языках программирования. А при необходимости, их можно адаптировать или дополнить под собственную предметную область.\nКонстанты Логические true - 1 yes - 1 false - 0 no - 0 Системные имена this - Текущий объект ($0) parent - Родительский объект ($$) last - Результат выполнения последнего оператора ($^) !!!!!!!!- args - Все аргументы функции ($*)\n!!!!!!!!- sys - Системный контекст запущенной программы (@@) !!!!!!!!- current - Текущий модуль (@$) !!!!!!!!- cmd - Все аргументы выполняющегося приложения из командной строки (@*)\n!!!!!!!!!!1### Типовые функции и проверки !!!!!!!!!!- run(‘filename’) - Выполнить указанный файл (@@(‘filename’)) !!!!!!!!!!- ifmain - Проверка, если текущий модуль основной ([@$.$0] –\u003e { … }) !!!!!!!!!!- ifload - Проверка, если текущий модуль загружается впервые ([@$.load] –\u003e { … })\nОператоры match(cond) - Оператор оценки выражения\nif(…) - Первый условный оператор ([$*]–\u003e { … })\nelif(…) - Второй и все последующие (,[$*]–\u003e { … })\nelse - Оператор иначе (,[_]–\u003e { … })\nwhile(cond) - Оператор цикла с предусловием ([@$cond] \u003c-\u003e { … } )\ndowhile(cond) - Оператор цикла с постусловием ({ … } \u003c-\u003e[@$cond])\niter(obj, … ) - Создание итератора ( @$obj ? (@$*) )\nnext(obj, … ) - Следующий элемент итератора ( @$obj ! ($*) )\ncurr(obj, … ) - Текущий элемент итератора ( @$obj !? ($*) )\nfirst(obj) - Перейти на первый элемент итератора ( @$obj !! )\nall(obj) - Получить сразу все элементы итератора ( @$obj ??)\nПрерывания return - Положительное прерывание (++)\nreturn(…)- Положительное прерывание с возвратом значения (++ @$value ++)\nerror - Отрицательное прерывание (--)\nerror(…) - Отрицательное прерывание с возвратом значения (-- @$value --)\nbreak+ и break- - Выход из цикла:\nwhile(...) {+ ++ :Break ++ +} while(...) {- -- :Break -- -} continue+ и continue- - В начало цикла: while(...) {+ ++ :Continue ++ +} while(...) {- -- :Continue -- -} obj { .field = 1; .prop(); };\n#Python\n1) without using with statement file = open(‘file_path’, ‘w’) file.write(‘hello world !’) file.close()\n2) without using with statement file = open(‘file_path’, ‘w’) try: file.write(‘hello world’) finally: file.close()\nopen(‘file_path’, ‘w’) { .write(‘hello world !’); .close(); }\nPython3\nusing with statement with open(‘file_path’, ‘w’) as file: file.write(‘hello world !’)\na simple file writer object class MessageWriter(object): def init(self, file_name): self.file_name = file_name\ndef __enter__(self): self.file = open(self.file_name, 'w') return self.file def __exit__(self, *args): self.file.close() using with statement with MessageWriter with MessageWriter(‘my_file.txt’) as xfile: xfile.write(‘hello world’)\na simple file writer object :MessageWriter { def init(self, file_name): self.file_name = file_name\ndef __enter__(self): self.file = open(self.file_name, 'w') return self.file def __exit__(self, *args): self.file.close() }\nusing with statement with MessageWriter MessageWriter(‘my_file.txt’) { .write(‘hello world’); };\nfrom contextlib import contextmanager\nclass MessageWriter(object): def init(self, filename): self.file_name = filename\n@contextmanager def open_file(self): try: file = open(self.file_name, 'w') yield file finally: file.close() usage message_writer = MessageWriter(‘hello.txt’) with message_writer.open_file() as my_file: my_file.write(‘hello world’)\n:MessageWriter(object) { def init(self, filename): self.file_name = filename\n@contextmanager def open_file(self): try: file = open(self.file_name, 'w') yield file finally: file.close() }\nusage message_writer = MessageWriter(‘hello.txt’) with message_writer.open_file() as my_file: my_file.write(‘hello world’)\nПриложения Предопределенные макросы При работе парсера NewLang автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. Данные предопределенные макросы можно использовать как обычные константы.\n__FILE__ или __FILE_NAME__ - имя и полный путь текущего файла\n__LINE__ или __FILE_LINE__ - содержит номер текущей строки в файле\n__FILE_TIMESTAMP__ - дату и время последней модификации текущего файла в строковом представлении\n__FILE_MD5__ - md5 хеш текущего файла в строковом виде\n__COUNTER__ - целочисленный счетчик, который увеличивает свое значение при каждом обращении\n__DATE__ - дата начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIME__ - время начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIMESTAMP__ - дату и время начала запуска компилятора (например: “Fri 19 Aug 13:32:58 2016”)\n__TIMESTAMP_ISO__ - дату и время начала запуска компилятора в формате ISO (например: “2013-07-06T00:50:06Z”)\n__NLC_VER__ - Страшая и младшая версия компилятора NewLang (8 битное число, по 4 бита на цифру)\n__NLC_DATE_BUILD__ - текстовая строка с датой сборки компилятора NewLang (например, “23.06.04 20:51:39”)\n__NLC_SOURCE_GIT__ - текстовая строка с идентификатором исходных файлов NewLang git репозитория, использованных при сборке компилятора (например, “v0.3.0-fef8c371”)\n__NLC_SOURCE_BUILD__ - дата сборки и git идентификатор исходных файлов NewLang одной текстовой строкой (например, “v0.3.0-fef8c371 23.06.04 20:51:39”)\n","categories":"","description":"","excerpt":"Системные свойства Несмотря на то, что не все объекты NewLang являются …","ref":"/docs/syntax/sysprop/","tags":"","title":"Системные свойства"},{"body":"Системные свойства Несмотря на то, что не все объекты NewLang являются классами с точки зрения реализованной концепции ООП, тем не менее, каждый объект имеет системные свойства, которые можно считать во время выполнения как обычные свойства объекта:\nУ всех переменных (объектов) есть системные свойства __name__ - краткое имя переменной (объекта)\n__full_name__ - полное имя переменной, включая имя модуля и пространство имен\n__type__ - текущий тип переменной. Может изменится при некоторых операциях\n__type_fixed__ - тип переменной (объекта) который не может измениться (ограничитель)\n__module__ - имя модуля в котором определена переменная (объект)\n__class__ - имя класса переменной или пусто, если объект не является классом\n__base__ - словарь со списком базовых классов или пусто, если объект не является классом\n__size__ - количество элементов у объекта, если применимо или :None\n__doc__ - документация по текущему объекту (если есть, иначе пустая строка)\n__str__ - строковое представление объекта для дампа\n__source__ - исходный текст модуля или функции\nСистемные свойства у модулей __file__ - полный путь к файлу модуля (соответствует С/С++ макросу __FILE__) __timestamp__ - дата и время последней модификации файла модуля (соответствует макросу С/С++ __TIMESTAMP__) __md5__ - хеш исходных данных модуля (соответствует макросу __MD5__) DSL Особенности ассоциативной памяти Синтаксис языка NewLang основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например if, чем комбинация минус минус правая угловая скобка –\u003e. Из-за этого имеет смысл использовать не “чистый” базовый синтаксис, а более привычный диалект с использованием ключевых слов.\nСинтаксис на ключевых словах В файле dsl.nlp находится набор макросов, которые расширяют базовый синтаксис NewLang, основанный на правилах, набором предопределенных ключевых слов как в классических языках программирования. А при необходимости, их можно адаптировать или дополнить под собственную предметную область.\nКонстанты Логические true - 1 yes - 1 false - 0 no - 0 Системные имена this - Текущий объект ($0) parent - Родительский объект ($$) last - Результат выполнения последнего оператора ($^) !!!!!!!!- args - Все аргументы функции ($*)\n!!!!!!!!- sys - Системный контекст запущенной программы (@@) !!!!!!!!- current - Текущий модуль (@$) !!!!!!!!- cmd - Все аргументы выполняющегося приложения из командной строки (@*)\n!!!!!!!!!!1### Типовые функции и проверки !!!!!!!!!!- run(‘filename’) - Выполнить указанный файл (@@(‘filename’)) !!!!!!!!!!- ifmain - Проверка, если текущий модуль основной ([@$.$0] –\u003e { … }) !!!!!!!!!!- ifload - Проверка, если текущий модуль загружается впервые ([@$.load] –\u003e { … })\nОператоры match(cond) - Оператор оценки выражения\nif(…) - Первый условный оператор ([$*]–\u003e { … })\nelif(…) - Второй и все последующие (,[$*]–\u003e { … })\nelse - Оператор иначе (,[_]–\u003e { … })\nwhile(cond) - Оператор цикла с предусловием ([@$cond] \u003c-\u003e { … } )\ndowhile(cond) - Оператор цикла с постусловием ({ … } \u003c-\u003e[@$cond])\niter(obj, … ) - Создание итератора ( @$obj ? (@$*) )\nnext(obj, … ) - Следующий элемент итератора ( @$obj ! ($*) )\ncurr(obj, … ) - Текущий элемент итератора ( @$obj !? ($*) )\nfirst(obj) - Перейти на первый элемент итератора ( @$obj !! )\nall(obj) - Получить сразу все элементы итератора ( @$obj ??)\nПрерывания return - Положительное прерывание (++)\nreturn(…)- Положительное прерывание с возвратом значения (++ @$value ++)\nerror - Отрицательное прерывание (--)\nerror(…) - Отрицательное прерывание с возвратом значения (-- @$value --)\nbreak+ и break- - Выход из цикла:\nwhile(...) {+ ++ :Break ++ +} while(...) {- -- :Break -- -} continue+ и continue- - В начало цикла: while(...) {+ ++ :Continue ++ +} while(...) {- -- :Continue -- -} obj { .field = 1; .prop(); };\n#Python\n1) without using with statement file = open(‘file_path’, ‘w’) file.write(‘hello world !’) file.close()\n2) without using with statement file = open(‘file_path’, ‘w’) try: file.write(‘hello world’) finally: file.close()\nopen(‘file_path’, ‘w’) { .write(‘hello world !’); .close(); }\nPython3\nusing with statement with open(‘file_path’, ‘w’) as file: file.write(‘hello world !’)\na simple file writer object class MessageWriter(object): def init(self, file_name): self.file_name = file_name\ndef __enter__(self): self.file = open(self.file_name, 'w') return self.file def __exit__(self, *args): self.file.close() using with statement with MessageWriter with MessageWriter(‘my_file.txt’) as xfile: xfile.write(‘hello world’)\na simple file writer object :MessageWriter { def init(self, file_name): self.file_name = file_name\ndef __enter__(self): self.file = open(self.file_name, 'w') return self.file def __exit__(self, *args): self.file.close() }\nusing with statement with MessageWriter MessageWriter(‘my_file.txt’) { .write(‘hello world’); };\nfrom contextlib import contextmanager\nclass MessageWriter(object): def init(self, filename): self.file_name = filename\n@contextmanager def open_file(self): try: file = open(self.file_name, 'w') yield file finally: file.close() usage message_writer = MessageWriter(‘hello.txt’) with message_writer.open_file() as my_file: my_file.write(‘hello world’)\n:MessageWriter(object) { def init(self, filename): self.file_name = filename\n@contextmanager def open_file(self): try: file = open(self.file_name, 'w') yield file finally: file.close() }\nusage message_writer = MessageWriter(‘hello.txt’) with message_writer.open_file() as my_file: my_file.write(‘hello world’)\nПриложения Предопределенные макросы При работе парсера NewLang автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. Данные предопределенные макросы можно использовать как обычные константы.\n__FILE__ или __FILE_NAME__ - имя и полный путь текущего файла\n__LINE__ или __FILE_LINE__ - содержит номер текущей строки в файле\n__FILE_TIMESTAMP__ - дату и время последней модификации текущего файла в строковом представлении\n__FILE_MD5__ - md5 хеш текущего файла в строковом виде\n__COUNTER__ - целочисленный счетчик, который увеличивает свое значение при каждом обращении\n__DATE__ - дата начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIME__ - время начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIMESTAMP__ - дату и время начала запуска компилятора (например: “Fri 19 Aug 13:32:58 2016”)\n__TIMESTAMP_ISO__ - дату и время начала запуска компилятора в формате ISO (например: “2013-07-06T00:50:06Z”)\n__NLC_VER__ - Страшая и младшая версия компилятора NewLang (8 битное число, по 4 бита на цифру)\n__NLC_DATE_BUILD__ - текстовая строка с датой сборки компилятора NewLang (например, “23.06.04 20:51:39”)\n__NLC_SOURCE_GIT__ - текстовая строка с идентификатором исходных файлов NewLang git репозитория, использованных при сборке компилятора (например, “v0.3.0-fef8c371”)\n__NLC_SOURCE_BUILD__ - дата сборки и git идентификатор исходных файлов NewLang одной текстовой строкой (например, “v0.3.0-fef8c371 23.06.04 20:51:39”)\n","categories":"","description":"","excerpt":"Системные свойства Несмотря на то, что не все объекты NewLang являются …","ref":"/ru/docs/syntax/sysprop/","tags":"","title":"Системные свойства"},{"body":"В качестве оператора проверки условия используется синтаксическая конструкция, которая соответствует по смыслу термину «следует», т.е. два тире и угловая скобка --\u003e. Такая запись условного оператора очень похожа на математическую и легко объединяется в последовательности для проверки множественных условий вида «else if».\nВ общем случае условный оператор имеет вид: [ условие ] --\u003e { действие }; или с условием иначе [ условие ] --\u003e { действие }, […] --\u003e { действие иначе };\nДля наглядности записанный с отступами:\n[ условие1 ] --\u003e { действие1 }, [ условие2 ] --\u003e действие2, [ условие3 ] --\u003e действие3, [...] --\u003e {действие_иначе}; Или тоже самое, но с использованием макросов DSL.:\n@if( условие1 ) { действие1 } @elif( условие2 ) действие2 @elif( условие3 ) действие3 @else { действие_иначе }; ","categories":"","description":"","excerpt":"В качестве оператора проверки условия используется синтаксическая …","ref":"/docs/ops/if/","tags":"","title":"Условный оператор"},{"body":"В качестве оператора проверки условия используется синтаксическая конструкция, которая соответствует по смыслу термину «следует», т.е. два тире и угловая скобка --\u003e. Такая запись условного оператора очень похожа на математическую и легко объединяется в последовательности для проверки множественных условий вида «else if».\nВ общем случае условный оператор имеет вид: [ условие ] --\u003e { действие }; или с условием иначе [ условие ] --\u003e { действие }, […] --\u003e { действие иначе };\nДля наглядности записанный с отступами:\n[ условие1 ] --\u003e { действие1 }, [ условие2 ] --\u003e действие2, [ условие3 ] --\u003e действие3, [...] --\u003e {действие_иначе}; Или тоже самое, но с использованием макросов DSL.:\n@if( условие1 ) { действие1 } @elif( условие2 ) действие2 @elif( условие3 ) действие3 @else { действие_иначе }; ","categories":"","description":"","excerpt":"В качестве оператора проверки условия используется синтаксическая …","ref":"/ru/docs/ops/if/","tags":"","title":"Условный оператор"},{"body":"Прагмы Предварительное объевления объектов @__PRAGMA_DECLARE__\n@__PRAGMA_DECLARE__( func(arg) ); Импорт нативной функции / переменной @__PRAGMA_NATIVE__\n// import native int printf(char *format, ...) @__PRAGMA_NATIVE__( printf(format:FmtChar, ...):Int32 ); Управление диагностикой компилятора @__PRAGMA_DIAG__ -\n@__PRAGMA_DIAG__(push) @__PRAGMA_DIAG__(ignored, \"-Wundef\") @__PRAGMA_DIAG__(warning, \"-Wformat\" , \"-Wundef\", \"-Wuninitialized\") @__PRAGMA_DIAG__(error, \"-Wuninitialized\") @__PRAGMA_DIAG__(pop) @__PRAGMA_MESSAGE__\n#pragma message \"Compiling \" __FILE__ \"...\" @__PRAGMA_MESSAGE__(\"Compiling \", __FILE__, \"...\") #define DO_PRAGMA(x) _Pragma (#x) #define TODO(x) DO_PRAGMA(message (\"TODO - \" #x)) @@TODO( ... )@@ := @__PRAGMA_MESSAGE__(\"TODO - \", @#...) @TODO(Remember to fix this) # note: TODO - Remember to fix this @__PRAGMA_WARNING__ @__PRAGMA_ERROR__\n@__PRAGMA_LOCATION__ // #line 303 \"location.hh\" // Prototype - @__PRAGMA_LOCATION__( pop ) // Prototype - @__PRAGMA_LOCATION__( push ) or @__PRAGMA_LOCATION__( push, 'filename') or @__PRAGMA_LOCATION__( push, 'filename', line) // Prototype - @__PRAGMA_LOCATION__( line ) or @__PRAGMA_LOCATION__( line, 'filename') Управление макросами @__PRAGMA_EXPECTED__ - Следующий символ должен быть одним из списка\n@__PRAGMA_EXPECTED__( @\\ {, @\\ {*, @\\ {+ ) { } @__PRAGMA_EXPECTED__( @\\ {, @\\ {*, @\\ {+) {+ +} @__PRAGMA_UNEXPECTED__ - Запретить использование перечисленных символов\n@__PRAGMA_UNEXPECTED__( @\\{, @\\{*, @\\{+) {- -} @__PRAGMA_UNEXPECTED__( @\\{*, @\\{+) { } @__PRAGMA_NO_MACRO__ - Следующий символ не макрос\nАннотации @__ANNOTATION_SET__\n@__ANNOTATION_SET__(name) @__ANNOTATION_SET__(name, \"value\") @__ANNOTATION_SET__(name, 1) @__ANNOTATION_IIF__\nНе используется (заготовки на будущее) @__PRAGMA_IGNORE__\nstatic const char * ignore_space = \"space\"; static const char * ignore_indent = \"indent\"; static const char * ignore_comment = \"comment\"; static const char * ignore_crlf = \"crlf\"; @__PRAGMA_INDENT_BLOCK__\n@__PRAGMA_MACRO__ -\n@__PRAGMA_MACRO_COND__\n@__PRAGMA_FINALIZE__\n","categories":"","description":"","excerpt":"Прагмы Предварительное объевления объектов @__PRAGMA_DECLARE__ …","ref":"/docs/syntax/pragmas/","tags":"","title":"Опции и настройки компилятора"},{"body":"Прагмы Предварительное объевления объектов @__PRAGMA_DECLARE__\n@__PRAGMA_DECLARE__( func(arg) ); Импорт нативной функции / переменной @__PRAGMA_NATIVE__\n// import native int printf(char *format, ...) @__PRAGMA_NATIVE__( printf(format:FmtChar, ...):Int32 ); Управление диагностикой компилятора @__PRAGMA_DIAG__ -\n@__PRAGMA_DIAG__(push) @__PRAGMA_DIAG__(ignored, \"-Wundef\") @__PRAGMA_DIAG__(warning, \"-Wformat\" , \"-Wundef\", \"-Wuninitialized\") @__PRAGMA_DIAG__(error, \"-Wuninitialized\") @__PRAGMA_DIAG__(pop) @__PRAGMA_MESSAGE__\n#pragma message \"Compiling \" __FILE__ \"...\" @__PRAGMA_MESSAGE__(\"Compiling \", __FILE__, \"...\") #define DO_PRAGMA(x) _Pragma (#x) #define TODO(x) DO_PRAGMA(message (\"TODO - \" #x)) @@TODO( ... )@@ := @__PRAGMA_MESSAGE__(\"TODO - \", @#...) @TODO(Remember to fix this) # note: TODO - Remember to fix this @__PRAGMA_WARNING__ @__PRAGMA_ERROR__\n@__PRAGMA_LOCATION__ // #line 303 \"location.hh\" // Prototype - @__PRAGMA_LOCATION__( pop ) // Prototype - @__PRAGMA_LOCATION__( push ) or @__PRAGMA_LOCATION__( push, 'filename') or @__PRAGMA_LOCATION__( push, 'filename', line) // Prototype - @__PRAGMA_LOCATION__( line ) or @__PRAGMA_LOCATION__( line, 'filename') Управление макросами @__PRAGMA_EXPECTED__ - Следующий символ должен быть одним из списка\n@__PRAGMA_EXPECTED__( @\\ {, @\\ {*, @\\ {+ ) { } @__PRAGMA_EXPECTED__( @\\ {, @\\ {*, @\\ {+) {+ +} @__PRAGMA_UNEXPECTED__ - Запретить использование перечисленных символов\n@__PRAGMA_UNEXPECTED__( @\\{, @\\{*, @\\{+) {- -} @__PRAGMA_UNEXPECTED__( @\\{*, @\\{+) { } @__PRAGMA_NO_MACRO__ - Следующий символ не макрос\nАннотации @__ANNOTATION_SET__\n@__ANNOTATION_SET__(name) @__ANNOTATION_SET__(name, \"value\") @__ANNOTATION_SET__(name, 1) @__ANNOTATION_IIF__\nНе используется (заготовки на будущее) @__PRAGMA_IGNORE__\nstatic const char * ignore_space = \"space\"; static const char * ignore_indent = \"indent\"; static const char * ignore_comment = \"comment\"; static const char * ignore_crlf = \"crlf\"; @__PRAGMA_INDENT_BLOCK__\n@__PRAGMA_MACRO__ -\n@__PRAGMA_MACRO_COND__\n@__PRAGMA_FINALIZE__\n","categories":"","description":"","excerpt":"Прагмы Предварительное объевления объектов @__PRAGMA_DECLARE__ …","ref":"/ru/docs/syntax/pragmas/","tags":"","title":"Опции и настройки компилятора"},{"body":"DSL Особенности ассоциативной памяти Синтаксис языка NewLang основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например if, чем комбинация минус минус правая угловая скобка –\u003e. Из-за этого имеет смысл использовать не “чистый” базовый синтаксис, а более привычный диалект с использованием ключевых слов.\nСинтаксис на ключевых словах В файле dsl.nlp находится набор макросов, которые расширяют базовый синтаксис NewLang, основанный на правилах, набором предопределенных ключевых слов как в классических языках программирования. А при необходимости, их можно адаптировать или дополнить под собственную предметную область.\nКонстанты Логические true - 1 yes - 1 false - 0 no - 0 Системные имена this - Текущий объект ($0) parent - Родительский объект ($$) last - Результат выполнения последнего оператора ($^) !!!!!!!!- args - Все аргументы функции ($*)\n!!!!!!!!- sys - Системный контекст запущенной программы (@@) !!!!!!!!- current - Текущий модуль (@$) !!!!!!!!- cmd - Все аргументы выполняющегося приложения из командной строки (@*)\n!!!!!!!!!!1### Типовые функции и проверки !!!!!!!!!!- run(‘filename’) - Выполнить указанный файл (@@(‘filename’)) !!!!!!!!!!- ifmain - Проверка, если текущий модуль основной ([@$.$0] –\u003e { … }) !!!!!!!!!!- ifload - Проверка, если текущий модуль загружается впервые ([@$.load] –\u003e { … })\nОператоры match(cond) - Оператор оценки выражения\nif(…) - Первый условный оператор ([$*]–\u003e { … })\nelif(…) - Второй и все последующие (,[$*]–\u003e { … })\nelse - Оператор иначе (,[_]–\u003e { … })\nwhile(cond) - Оператор цикла с предусловием ([@$cond] \u003c-\u003e { … } )\ndowhile(cond) - Оператор цикла с постусловием ({ … } \u003c-\u003e[@$cond])\niter(obj, … ) - Создание итератора ( @$obj ? (@$*) )\nnext(obj, … ) - Следующий элемент итератора ( @$obj ! ($*) )\ncurr(obj, … ) - Текущий элемент итератора ( @$obj !? ($*) )\nfirst(obj) - Перейти на первый элемент итератора ( @$obj !! )\nall(obj) - Получить сразу все элементы итератора ( @$obj ??)\nПрерывания return - Положительное прерывание (++)\nreturn(…)- Положительное прерывание с возвратом значения (++ @$value ++)\nerror - Отрицательное прерывание (--)\nerror(…) - Отрицательное прерывание с возвратом значения (-- @$value --)\nbreak+ и break- - Выход из цикла:\nwhile(...) {+ ++ :Break ++ +} while(...) {- -- :Break -- -} continue+ и continue- - В начало цикла: while(...) {+ ++ :Continue ++ +} while(...) {- -- :Continue -- -} obj { .field = 1; .prop(); };\n#Python\n1) without using with statement file = open(‘file_path’, ‘w’) file.write(‘hello world !’) file.close()\n2) without using with statement file = open(‘file_path’, ‘w’) try: file.write(‘hello world’) finally: file.close()\nopen(‘file_path’, ‘w’) { .write(‘hello world !’); .close(); }\nPython3\nusing with statement with open(‘file_path’, ‘w’) as file: file.write(‘hello world !’)\na simple file writer object class MessageWriter(object): def init(self, file_name): self.file_name = file_name\ndef __enter__(self): self.file = open(self.file_name, 'w') return self.file def __exit__(self, *args): self.file.close() using with statement with MessageWriter with MessageWriter(‘my_file.txt’) as xfile: xfile.write(‘hello world’)\na simple file writer object :MessageWriter { def init(self, file_name): self.file_name = file_name\ndef __enter__(self): self.file = open(self.file_name, 'w') return self.file def __exit__(self, *args): self.file.close() }\nusing with statement with MessageWriter MessageWriter(‘my_file.txt’) { .write(‘hello world’); };\nfrom contextlib import contextmanager\nclass MessageWriter(object): def init(self, filename): self.file_name = filename\n@contextmanager def open_file(self): try: file = open(self.file_name, 'w') yield file finally: file.close() usage message_writer = MessageWriter(‘hello.txt’) with message_writer.open_file() as my_file: my_file.write(‘hello world’)\n:MessageWriter(object) { def init(self, filename): self.file_name = filename\n@contextmanager def open_file(self): try: file = open(self.file_name, 'w') yield file finally: file.close() }\nusage message_writer = MessageWriter(‘hello.txt’) with message_writer.open_file() as my_file: my_file.write(‘hello world’)\nПриложения Предопределенные макросы При работе парсера NewLang автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. Данные предопределенные макросы можно использовать как обычные константы.\n__FILE__ или __FILE_NAME__ - имя и полный путь текущего файла\n__LINE__ или __FILE_LINE__ - содержит номер текущей строки в файле\n__FILE_TIMESTAMP__ - дату и время последней модификации текущего файла в строковом представлении\n__FILE_MD5__ - md5 хеш текущего файла в строковом виде\n__COUNTER__ - целочисленный счетчик, который увеличивает свое значение при каждом обращении\n__DATE__ - дата начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIME__ - время начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIMESTAMP__ - дату и время начала запуска компилятора (например: “Fri 19 Aug 13:32:58 2016”)\n__TIMESTAMP_ISO__ - дату и время начала запуска компилятора в формате ISO (например: “2013-07-06T00:50:06Z”)\n__NLC_VER__ - Страшая и младшая версия компилятора NewLang (8 битное число, по 4 бита на цифру)\n__NLC_DATE_BUILD__ - текстовая строка с датой сборки компилятора NewLang (например, “23.06.04 20:51:39”)\n__NLC_SOURCE_GIT__ - текстовая строка с идентификатором исходных файлов NewLang git репозитория, использованных при сборке компилятора (например, “v0.3.0-fef8c371”)\n__NLC_SOURCE_BUILD__ - дата сборки и git идентификатор исходных файлов NewLang одной текстовой строкой (например, “v0.3.0-fef8c371 23.06.04 20:51:39”)\n","categories":"","description":"","excerpt":"DSL Особенности ассоциативной памяти Синтаксис языка NewLang основан …","ref":"/docs/syntax/sysmacro/","tags":"","title":"Системные макросы"},{"body":"DSL Особенности ассоциативной памяти Синтаксис языка NewLang основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например if, чем комбинация минус минус правая угловая скобка –\u003e. Из-за этого имеет смысл использовать не “чистый” базовый синтаксис, а более привычный диалект с использованием ключевых слов.\nСинтаксис на ключевых словах В файле dsl.nlp находится набор макросов, которые расширяют базовый синтаксис NewLang, основанный на правилах, набором предопределенных ключевых слов как в классических языках программирования. А при необходимости, их можно адаптировать или дополнить под собственную предметную область.\nКонстанты Логические true - 1 yes - 1 false - 0 no - 0 Системные имена this - Текущий объект ($0) parent - Родительский объект ($$) last - Результат выполнения последнего оператора ($^) !!!!!!!!- args - Все аргументы функции ($*)\n!!!!!!!!- sys - Системный контекст запущенной программы (@@) !!!!!!!!- current - Текущий модуль (@$) !!!!!!!!- cmd - Все аргументы выполняющегося приложения из командной строки (@*)\n!!!!!!!!!!1### Типовые функции и проверки !!!!!!!!!!- run(‘filename’) - Выполнить указанный файл (@@(‘filename’)) !!!!!!!!!!- ifmain - Проверка, если текущий модуль основной ([@$.$0] –\u003e { … }) !!!!!!!!!!- ifload - Проверка, если текущий модуль загружается впервые ([@$.load] –\u003e { … })\nОператоры match(cond) - Оператор оценки выражения\nif(…) - Первый условный оператор ([$*]–\u003e { … })\nelif(…) - Второй и все последующие (,[$*]–\u003e { … })\nelse - Оператор иначе (,[_]–\u003e { … })\nwhile(cond) - Оператор цикла с предусловием ([@$cond] \u003c-\u003e { … } )\ndowhile(cond) - Оператор цикла с постусловием ({ … } \u003c-\u003e[@$cond])\niter(obj, … ) - Создание итератора ( @$obj ? (@$*) )\nnext(obj, … ) - Следующий элемент итератора ( @$obj ! ($*) )\ncurr(obj, … ) - Текущий элемент итератора ( @$obj !? ($*) )\nfirst(obj) - Перейти на первый элемент итератора ( @$obj !! )\nall(obj) - Получить сразу все элементы итератора ( @$obj ??)\nПрерывания return - Положительное прерывание (++)\nreturn(…)- Положительное прерывание с возвратом значения (++ @$value ++)\nerror - Отрицательное прерывание (--)\nerror(…) - Отрицательное прерывание с возвратом значения (-- @$value --)\nbreak+ и break- - Выход из цикла:\nwhile(...) {+ ++ :Break ++ +} while(...) {- -- :Break -- -} continue+ и continue- - В начало цикла: while(...) {+ ++ :Continue ++ +} while(...) {- -- :Continue -- -} obj { .field = 1; .prop(); };\n#Python\n1) without using with statement file = open(‘file_path’, ‘w’) file.write(‘hello world !’) file.close()\n2) without using with statement file = open(‘file_path’, ‘w’) try: file.write(‘hello world’) finally: file.close()\nopen(‘file_path’, ‘w’) { .write(‘hello world !’); .close(); }\nPython3\nusing with statement with open(‘file_path’, ‘w’) as file: file.write(‘hello world !’)\na simple file writer object class MessageWriter(object): def init(self, file_name): self.file_name = file_name\ndef __enter__(self): self.file = open(self.file_name, 'w') return self.file def __exit__(self, *args): self.file.close() using with statement with MessageWriter with MessageWriter(‘my_file.txt’) as xfile: xfile.write(‘hello world’)\na simple file writer object :MessageWriter { def init(self, file_name): self.file_name = file_name\ndef __enter__(self): self.file = open(self.file_name, 'w') return self.file def __exit__(self, *args): self.file.close() }\nusing with statement with MessageWriter MessageWriter(‘my_file.txt’) { .write(‘hello world’); };\nfrom contextlib import contextmanager\nclass MessageWriter(object): def init(self, filename): self.file_name = filename\n@contextmanager def open_file(self): try: file = open(self.file_name, 'w') yield file finally: file.close() usage message_writer = MessageWriter(‘hello.txt’) with message_writer.open_file() as my_file: my_file.write(‘hello world’)\n:MessageWriter(object) { def init(self, filename): self.file_name = filename\n@contextmanager def open_file(self): try: file = open(self.file_name, 'w') yield file finally: file.close() }\nusage message_writer = MessageWriter(‘hello.txt’) with message_writer.open_file() as my_file: my_file.write(‘hello world’)\nПриложения Предопределенные макросы При работе парсера NewLang автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. Данные предопределенные макросы можно использовать как обычные константы.\n__FILE__ или __FILE_NAME__ - имя и полный путь текущего файла\n__LINE__ или __FILE_LINE__ - содержит номер текущей строки в файле\n__FILE_TIMESTAMP__ - дату и время последней модификации текущего файла в строковом представлении\n__FILE_MD5__ - md5 хеш текущего файла в строковом виде\n__COUNTER__ - целочисленный счетчик, который увеличивает свое значение при каждом обращении\n__DATE__ - дата начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIME__ - время начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIMESTAMP__ - дату и время начала запуска компилятора (например: “Fri 19 Aug 13:32:58 2016”)\n__TIMESTAMP_ISO__ - дату и время начала запуска компилятора в формате ISO (например: “2013-07-06T00:50:06Z”)\n__NLC_VER__ - Страшая и младшая версия компилятора NewLang (8 битное число, по 4 бита на цифру)\n__NLC_DATE_BUILD__ - текстовая строка с датой сборки компилятора NewLang (например, “23.06.04 20:51:39”)\n__NLC_SOURCE_GIT__ - текстовая строка с идентификатором исходных файлов NewLang git репозитория, использованных при сборке компилятора (например, “v0.3.0-fef8c371”)\n__NLC_SOURCE_BUILD__ - дата сборки и git идентификатор исходных файлов NewLang одной текстовой строкой (например, “v0.3.0-fef8c371 23.06.04 20:51:39”)\n","categories":"","description":"","excerpt":"DSL Особенности ассоциативной памяти Синтаксис языка NewLang основан …","ref":"/ru/docs/syntax/sysmacro/","tags":"","title":"Системные макросы"},{"body":"Features of associative memory The syntax of the NewLang language is based on strict rules without the use of keywords, and no matter how logical it may seem, association by keywords is much easier to remember, for example, if, than the combination minus minus right angle bracket –\u003e. Because of this, it makes sense to use not a “pure” basic syntax, but a more familiar dialect with the use of keywords.\nNewLang already contains a set of macros that extend the basic rule-based syntax of NewLang, a set of predefined keywords as in classical programming languages, which can be adapted or supplemented to suit your own subject area.\nConstants @true - 1\n@yes - 1\n@false - 0\n@no - 0\n@this или @self - Current object\n@super - Parent object\n@latter or @last- Result of the last operation\nLogical operators @and - Logical AND @or - Logical OR @xor - Logical Exclusive OR @not(value) - Logical negation Operators @if(…) - First conditional statement\n@elif(…) - Second and all subsequent conditional statements\n@else - Operator otherwise\n@while(…) - Loop operator with precondition\n@dowhile(…) - Loop operator with postcondition\n@loop - Infinite loop operator\n@break $label - Operator to break out of a named named block of code\n@continue $label - Jump operator to the beginning of a named block of code\n@return( result ) - Operator for returning a value and exiting a function\n@throw( error ) - Operator for creating an exception and returning an error\n@match( … ) - Expression evaluation operator\n@case( … ) - Pattern comparison operator\n@default - Selection operator\n@iter(obj, … ) - Creating an iterator\n@next(obj, … ) - Get the next element of the iterator\n@curr(obj, … ) - Get the current iterator element\n@first(obj) - Go to the first element of the iterator\n@all(obj) - Get all elements of the iterator at once\nPredefined macros When the NewLang parser is running, several reserved macros are automatically generated, some of which correspond to preprocessor macros in C/C++. These predefined macros can be used as regular constants.\n__FILE__ or __FILE_NAME__ - name and full path of the current file\n__LINE__ or __FILE_LINE__ - contains the number of the current line in the file\n__FILE_TIMESTAMP__ - date and time of the last modification of the current file in string representation\n__FILE_MD5__ - md5 hash of the current file in string form\n__COUNTER__ - an integer counter that increases its value with each access\n__DATE__ - start date of the compiler launch (has the same value for all processed files)\n__TIME__ - start time of the compiler launch (has the same value for all processed files)\n__TIMESTAMP__ - date and time when the compiler started running (for example: “Fri 19 Aug 13:32:58 2016”)\n__TIMESTAMP_ISO__ - date and time when the compiler started running in ISO format (for example: “2013-07-06T00:50:06Z”)\n__NLC_VER__ - Older and younger version of the NewLang compiler (8-bit number, 4 bits per digit)\n__NLC_DATE_BUILD__ - text string with the build date of the NewLang compiler (for example, “06/23/04 20:51:39”)\n__NLC_SOURCE_GIT__ - text string with the identifier of the NewLang git repository source files used to build the compiler (for example, “v0.3.0-fef8c371”)\n__NLC_SOURCE_BUILD__ - build date and git identifier of NewLang source files in one text line (for example, “v0.3.0-fef8c371 06/23/04 20:51:39”)\n","categories":"","description":"","excerpt":"Features of associative memory The syntax of the NewLang language is …","ref":"/docs/syntax/dsl/","tags":"","title":"Keyword syntax (DSL)"},{"body":"Особенности ассоциативной памяти Синтаксис языка NewLang основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например if, чем комбинация минус минус правая угловая скобка –\u003e. Из-за этого имеет смысл использовать не “чистый” базовый синтаксис, а более привычный диалект с использованием ключевых слов.\nNewLang уже содержит набор макросов, которые расширяют базовый синтаксис NewLang, основанный на правилах, набором предопределенных ключевых слов как в классических языках программирования, которые можно адаптировать или дополнить под собственную предметную область.\nКонстанты @true - 1\n@yes - 1\n@false - 0\n@no - 0\n@this или @self - Текущий объект\n@super - Родительский объект\n@latter или @last- Результат выполенения последнего оператора Result of the last operation\nЛогические операторы @and - Логическое И @or - Логическое ИЛИ @xor - Логическое Исключающее ИЛИ @not(value) - Логическое отрицание Операторы @if(…) - Первый условный оператор\n@elif(…) - Второй и все последующие условные операторы\n@else - Оператор иначе\n@while(…) - Оператор цикла с предусловием\n@dowhile(…) - Оператор цикла с постусловием\n@loop - Оператор безконечного цикла\n@break $label - Оператор выхода из именованного именованного блока кода\n@continue $label - Оператор прехода на начало именованного блока кода\n@return( result ) - Оператор возврата значения и выхода из функции\n@throw( error ) - Оператор создания исключения и возврата ошибки\n@match( … ) - Оператор оценки выражения\n@case( … ) - Оператор сравнения с образцом\n@default - Оператор выбора по улочанию\n@iter(obj, … ) - Создание итератора\n@next(obj, … ) - Получить следующий элемент итератора\n@curr(obj, … ) - Получить текущий элемент итератора\n@first(obj) - Перейти на первый элемент итератора\n@all(obj) - Получить сразу все элементы итератора\nПредопределенные макросы При работе парсера NewLang автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. Данные предопределенные макросы можно использовать как обычные константы.\n__FILE__ или __FILE_NAME__ - имя и полный путь текущего файла\n__LINE__ или __FILE_LINE__ - содержит номер текущей строки в файле\n__FILE_TIMESTAMP__ - дату и время последней модификации текущего файла в строковом представлении\n__FILE_MD5__ - md5 хеш текущего файла в строковом виде\n__COUNTER__ - целочисленный счетчик, который увеличивает свое значение при каждом обращении\n__DATE__ - дата начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIME__ - время начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов)\n__TIMESTAMP__ - дату и время начала запуска компилятора (например: “Fri 19 Aug 13:32:58 2016”)\n__TIMESTAMP_ISO__ - дату и время начала запуска компилятора в формате ISO (например: “2013-07-06T00:50:06Z”)\n__NLC_VER__ - Страшая и младшая версия компилятора NewLang (8 битное число, по 4 бита на цифру)\n__NLC_DATE_BUILD__ - текстовая строка с датой сборки компилятора NewLang (например, “23.06.04 20:51:39”)\n__NLC_SOURCE_GIT__ - текстовая строка с идентификатором исходных файлов NewLang git репозитория, использованных при сборке компилятора (например, “v0.3.0-fef8c371”)\n__NLC_SOURCE_BUILD__ - дата сборки и git идентификатор исходных файлов NewLang одной текстовой строкой (например, “v0.3.0-fef8c371 23.06.04 20:51:39”)\n","categories":"","description":"","excerpt":"Особенности ассоциативной памяти Синтаксис языка NewLang основан на …","ref":"/ru/docs/syntax/dsl/","tags":"","title":"Keyword syntax (DSL)"},{"body":"Синтаксическая конструкция с помощью которой реализуется примерный аналог оператора switch или match выглядит следующим образом:\n[ $var ] ==\u003e { [1] --\u003e { code }; # Выполнится проверка условия $var == 1 [1, 2] --\u003e { code }; # Выполнится проверка условия ($var == 1 || $var == 2) [...] --\u003e { code default }; # Ветка условия иначе }; Или тоже самое, но с использованием макросов из модуля dsl:\n@match( $var ) ==\u003e { @case( 1 ) { code }; @case( 1, 2 ) { code }; @default { code default }; }; Этот оператор очень похож на Pattern Matching, но все же не является сопоставлением с образцом, а скорее более краткая запись множественного оператора сравнения, так как в качестве оператора для оценки могут быть использован любые имеющиеся операторы сравнения на равенство:\n==\u003e — проверка на равенство с приведением типов; ===\u003e — проверка на точное равенство; ~\u003e — проверка типа (имени класса); ~~\u003e — утиная типизация; ~~~\u003e — строгая утиная типизация. Но если в качестве оператора сравнения использовать оператор утиной типизации, то оценка выражения превращается в классический Pattern Matching:\n$value := (f1=1, f2=\"2\",); @match( $value ) ~~\u003e { @case((f1=_, ), (f1=_, f2=0, )) { ... code ... }; # Поле f2 отсутствует или число @case((f1=_, f2=\"\",), (f1=_, f2='',)) { ... code ... }; # Поле f2 строка @default { ... code default ... }; # Код по умолчанию }; ","categories":"","description":"","excerpt":"Синтаксическая конструкция с помощью которой реализуется примерный …","ref":"/docs/ops/match/","tags":"","title":"Оценка выражения"},{"body":"Синтаксическая конструкция с помощью которой реализуется примерный аналог оператора switch или match выглядит следующим образом:\n[ $var ] ==\u003e { [1] --\u003e { code }; # Выполнится проверка условия $var == 1 [1, 2] --\u003e { code }; # Выполнится проверка условия ($var == 1 || $var == 2) [...] --\u003e { code default }; # Ветка условия иначе }; Или тоже самое, но с использованием макросов из модуля dsl:\n@match( $var ) ==\u003e { @case( 1 ) { code }; @case( 1, 2 ) { code }; @default { code default }; }; Этот оператор очень похож на Pattern Matching, но все же не является сопоставлением с образцом, а скорее более краткая запись множественного оператора сравнения, так как в качестве оператора для оценки могут быть использован любые имеющиеся операторы сравнения на равенство:\n==\u003e — проверка на равенство с приведением типов; ===\u003e — проверка на точное равенство; ~\u003e — проверка типа (имени класса); ~~\u003e — утиная типизация; ~~~\u003e — строгая утиная типизация. Но если в качестве оператора сравнения использовать оператор утиной типизации, то оценка выражения превращается в классический Pattern Matching:\n$value := (f1=1, f2=\"2\",); @match( $value ) ~~\u003e { @case((f1=_, ), (f1=_, f2=0, )) { ... code ... }; # Поле f2 отсутствует или число @case((f1=_, f2=\"\",), (f1=_, f2='',)) { ... code ... }; # Поле f2 строка @default { ... code default ... }; # Код по умолчанию }; ","categories":"","description":"","excerpt":"Синтаксическая конструкция с помощью которой реализуется примерный …","ref":"/ru/docs/ops/match/","tags":"","title":"Оценка выражения"},{"body":"Для записи циклов используются оператор \u003c-\u003e, который ставится между условием цикла (проверкой логического выражения) и телом цикла. Условие цикла записывается в квадратных скобках и в зависимости от взаимного расположения цикл может быть с предусловием (while) или постусловием (dowhile):\n[условие while] \u003c-\u003e { тело цикла while }; { тело цикла do while } \u003c-\u003e [условие do while]; Цикл с предусловием (while) поддерживает конструкцию else, которая выполняется, если условие входа в цикл не было выполнено.\nВнимание! Это поведение отличается от аналогичных конструкций в языке Python, у которого секция else выполняется всегда, кроме прерывания цикла по break.\nВетка else у оператора цикла записывается так же как и ветка иначе в условном операторе, т.е.\n[ cond ] \u003c-\u003e { ... },[...] --\u003e { ... }; Или тоже самое, но с использованием макросов из модуля dsl:\n@while(cond) { ... } @else { ... # Выполнится, только если cond будет false при входе в цикл }; Пример реализации цикла foreach для суммирования всех элементов словаря (или одномерного тензора) с использованием оператора раскрытия списка:\nsumma := 0; dict := (1,2,3,4,5,); [ dict ] \u003c-\u003e { # Условие цикла, пока есть данные # Результат оператора распаковка словаря - первый элемент перемещается в item item, dict := ... dict; summa += item; # Вычисление суммы всех элементов словаря }; ","categories":"","description":"","excerpt":"Для записи циклов используются оператор \u003c-\u003e, который ставится между …","ref":"/docs/ops/while/","tags":"","title":"Операторы циклов"},{"body":"Для записи циклов используются оператор \u003c-\u003e, который ставится между условием цикла (проверкой логического выражения) и телом цикла. Условие цикла записывается в квадратных скобках и в зависимости от взаимного расположения цикл может быть с предусловием (while) или постусловием (dowhile):\n[условие while] \u003c-\u003e { тело цикла while }; { тело цикла do while } \u003c-\u003e [условие do while]; Цикл с предусловием (while) поддерживает конструкцию else, которая выполняется, если условие входа в цикл не было выполнено.\nВнимание! Это поведение отличается от аналогичных конструкций в языке Python, у которого секция else выполняется всегда, кроме прерывания цикла по break.\nВетка else у оператора цикла записывается так же как и ветка иначе в условном операторе, т.е.\n[ cond ] \u003c-\u003e { ... },[...] --\u003e { ... }; Или тоже самое, но с использованием макросов из модуля dsl:\n@while(cond) { ... } @else { ... # Выполнится, только если cond будет false при входе в цикл }; Пример реализации цикла foreach для суммирования всех элементов словаря (или одномерного тензора) с использованием оператора раскрытия списка:\nsumma := 0; dict := (1,2,3,4,5,); [ dict ] \u003c-\u003e { # Условие цикла, пока есть данные # Результат оператора распаковка словаря - первый элемент перемещается в item item, dict := ... dict; summa += item; # Вычисление суммы всех элементов словаря }; ","categories":"","description":"","excerpt":"Для записи циклов используются оператор \u003c-\u003e, который ставится между …","ref":"/ru/docs/ops/while/","tags":"","title":"Операторы циклов"},{"body":"Одиночный оператор захвата ссылки и синхронизации доступа к объекту ‘*’ или ‘*(…)’ выполняется только для одной переменной при использовании в одном действии. Но захват ссылки и объекта синхронизации, это относительно медленная операция и выполнять её для каждого действия над переменной не рационально.\nДля того, чтобы захватить одновременно сразу несколько объектов синхронизации для выполнения группы последовательных действий используется менеджер контекста.\n**( val1 = *ref1, val2 = *ref2, __timeout__ = 10000 ){ ... }; **( ... ){ ... } , [...] { # Ветка else при ошибке захвата ссылки # Информация об ошибке в переменной $^ ... }; Или таже самая запись с использованием макросов DSL:\n@with( val1 = *ref1, val2 = *ref2, __timeout__ = 10000 ){ ... }; @with( ... ){ ... } @else { # Ветка else при ошибке захвата ссылки # Информация об ошибке в переменной $^ ... }; Захват легких ссылок совместного доступа При захвате обычной легкой ссылки всегда сравнивается идентификатор текущего потока с идентифкатором потока - владельца объекта. Использование обычных легких ссылок допускается только в рамках одного потока - владельца объекта.\nЧтобы можно было использовать ссылки на легкие объекты в других потоках, для них требуется создать легкие ссылки для совместного доступа (\"\u0026?\").\nЗахват легких ссылок для совместного доступа возможен только с помощью оператора группового захвата, при условии, что как миниму одна из первых ссылок будет тяжелой. т.е. с реализованным объектом синхронизации.\nПример реализации критической секции с помощью оператора группового захвата @with и статической переменной @::sync в качестве флага блокировки доступа:\n# Функция для вызова в разных потоках show( \u0026? win1, \u0026? win2) := { \u0026\u0026 @::sync := @false; # Global (static) synchronization object @with (*sync, w1 = *win1, w2 = *win2){ ... # Критическая секция } } Расширенный синтаксис определения ссылок При определении переменной, у которой допускается создание ссылок и синхронизация доступа, можно указать дополнительные параметры работы. Это делается с помощью указания системных параметров в типе разрешенных ссылок при определении объекта.\nУсловный пример:\n\u0026\u0026 sync; # Объект синхронизации \u0026\u0026(__timeout__=1000) sync_other; # Объект синхронизации c таймаутом на блокировку with(*sync_other) { # Блокировка с таймаутом ... } # Переменная value с конкретным объектом синхроинзации \u0026?(sync) value := 123; with(*sync, lock = *value) { # ОК ... } with(*sync_other, val = *value) { # Ошибка компиляции # для синхронизации должен использоваться sync ... } Автоматическое освобождение ресурсов Менеджер контекста, кроме захвата слабых ссылок в локальные переменные и блокировки доступа, одновременно с этим позволяет выделять и освобождать ресурсы, автоматически вызывая декструктор локального объекта при выходе из блока кода оператора.\nОсвобождение ресурсов (вызов деструктора у объекта) происходит до попадания в ветку else, если она присутствует.\nСамый популярный пример использования менеджера контекста - связанные операции открытия, чтения/записи и закрытия файла в одном блоке кода.\nНапример:\n# Фрагмент определения класса File File(name, mode) := :Class() { .file ::= fopen($name, $mode); # Handle file ~File() := { # Destructor of class @if(@this.file){ fclose(@this.file); @this.file := _; } } ... }; @with( file = :File('some_file', 'w') ) { file.write('Oppa!'); }; Код выше открывает файл, записывает в него данные и закрывает файл при выходе из блока кода.\nЭтот код эквивалентен следующему на Python:\nwith open('some_file', 'w') as file: file.write('Oppa!') # Или без менеджера контекста file = open('some_file', 'w') try: file.write('Oppa!') finally: file.close() Более сложный пример чтение файла с одновремнным захватом ссылки на буфер и обработкой ошибок:\n@with( file = :File('some_file', 'r'), buffer = *ref_buffer ) { file.read(buffer); } @else { @match(@latter){ @case( :ErrorLock ) { /* Ошибка захвата ссылки ref_buffer */ }; @case( :ErrorOpenFile ) { /* Ошибка открытия для записи файла some_file */ }; @case( :ErrorReadWrite ) { /* Ошибка чтения-записи в файл some_file */ }; @default @forward; /* Остальные ошибки пробросить дальше */ }; }; Использование менеджера контекста - это гарантия закрытия файла и освобождения буфера вне зависимости от того, как будет завершён вложенный код. Распространенный паттерн использования контекстных менеджеров - блокирование и разблокирование ресурсов при многопоточном доступе к объетам, а также закрытие открытых файлов или освобождение захваченных ресурсов.\nprintf(format:FmtChar, ...):Int32 := %printf...; \u0026\u0026 holder: Integer[] = [,]; # Empty tensor Runnable(cnt:Integer) := { $i := 1; @while( $i \u003c= $cnt ) { *holder []= $i; # Lock and add new value $i += 1; @if( $i % ($cnt // 10) == 0) { @with(*holder){ # Lock only printf(\".\"); } } } } $count = 10000; thread1 = :Thread(Runnable, $count); thread2 = :Thread(Runnable, $count); thread3 = :Thread(Runnable, $count); thread4 = :Thread(Runnable, $count); thread5 = :Thread(Runnable, $count); thread1.start(); thread2.start(); thread3.start(); thread4.start(); thread5.start(); thread1.join(); thread2.join(); thread3.join(); thread4.join(); thread5.join(); @assert(*holder.size() == 5*$count); printf(\"Complete %d!\\n\", *holder.size()); Вывод:\n\u003e.................................................. \u003eComplete 50000! \u003e_ ","categories":"","description":"","excerpt":"Одиночный оператор захвата ссылки и синхронизации доступа к объекту …","ref":"/docs/ops/with/","tags":"","title":"Менеджер контекста"},{"body":"Одиночный оператор захвата ссылки и синхронизации доступа к объекту ‘*’ или ‘*(…)’ выполняется только для одной переменной при использовании в одном действии. Но захват ссылки и объекта синхронизации, это относительно медленная операция и выполнять её для каждого действия над переменной не рационально.\nДля того, чтобы захватить одновременно сразу несколько объектов синхронизации для выполнения группы последовательных действий используется менеджер контекста.\n**( val1 = *ref1, val2 = *ref2, __timeout__ = 10000 ){ ... }; **( ... ){ ... } , [...] { # Ветка else при ошибке захвата ссылки # Информация об ошибке в переменной $^ ... }; Или таже самая запись с использованием макросов DSL:\n@with( val1 = *ref1, val2 = *ref2, __timeout__ = 10000 ){ ... }; @with( ... ){ ... } @else { # Ветка else при ошибке захвата ссылки # Информация об ошибке в переменной $^ ... }; Захват легких ссылок совместного доступа При захвате обычной легкой ссылки всегда сравнивается идентификатор текущего потока с идентифкатором потока - владельца объекта. Использование обычных легких ссылок допускается только в рамках одного потока - владельца объекта.\nЧтобы можно было использовать ссылки на легкие объекты в других потоках, для них требуется создать легкие ссылки для совместного доступа (\"\u0026?\").\nЗахват легких ссылок для совместного доступа возможен только с помощью оператора группового захвата, при условии, что как миниму одна из первых ссылок будет тяжелой. т.е. с реализованным объектом синхронизации.\nПример реализации критической секции с помощью оператора группового захвата @with и статической переменной @::sync в качестве флага блокировки доступа:\n# Функция для вызова в разных потоках show( \u0026? win1, \u0026? win2) := { \u0026\u0026 @::sync := @false; # Global (static) synchronization object @with (*sync, w1 = *win1, w2 = *win2){ ... # Критическая секция } } Расширенный синтаксис определения ссылок При определении переменной, у которой допускается создание ссылок и синхронизация доступа, можно указать дополнительные параметры работы. Это делается с помощью указания системных параметров в типе разрешенных ссылок при определении объекта.\nУсловный пример:\n\u0026\u0026 sync; # Объект синхронизации \u0026\u0026(__timeout__=1000) sync_other; # Объект синхронизации c таймаутом на блокировку with(*sync_other) { # Блокировка с таймаутом ... } # Переменная value с конкретным объектом синхроинзации \u0026?(sync) value := 123; with(*sync, lock = *value) { # ОК ... } with(*sync_other, val = *value) { # Ошибка компиляции # для синхронизации должен использоваться sync ... } Автоматическое освобождение ресурсов Менеджер контекста, кроме захвата слабых ссылок в локальные переменные и блокировки доступа, одновременно с этим позволяет выделять и освобождать ресурсы, автоматически вызывая декструктор локального объекта при выходе из блока кода оператора.\nОсвобождение ресурсов (вызов деструктора у объекта) происходит до попадания в ветку else, если она присутствует.\nСамый популярный пример использования менеджера контекста - связанные операции открытия, чтения/записи и закрытия файла в одном блоке кода.\nНапример:\n# Фрагмент определения класса File File(name, mode) := :Class() { .file ::= fopen($name, $mode); # Handle file ~File() := { # Destructor of class @if(@this.file){ fclose(@this.file); @this.file := _; } } ... }; @with( file = :File('some_file', 'w') ) { file.write('Oppa!'); }; Код выше открывает файл, записывает в него данные и закрывает файл при выходе из блока кода.\nЭтот код эквивалентен следующему на Python:\nwith open('some_file', 'w') as file: file.write('Oppa!') # Или без менеджера контекста file = open('some_file', 'w') try: file.write('Oppa!') finally: file.close() Более сложный пример чтение файла с одновремнным захватом ссылки на буфер и обработкой ошибок:\n@with( file = :File('some_file', 'r'), buffer = *ref_buffer ) { file.read(buffer); } @else { @match(@latter){ @case( :ErrorLock ) { /* Ошибка захвата ссылки ref_buffer */ }; @case( :ErrorOpenFile ) { /* Ошибка открытия для записи файла some_file */ }; @case( :ErrorReadWrite ) { /* Ошибка чтения-записи в файл some_file */ }; @default @forward; /* Остальные ошибки пробросить дальше */ }; }; Использование менеджера контекста - это гарантия закрытия файла и освобождения буфера вне зависимости от того, как будет завершён вложенный код. Распространенный паттерн использования контекстных менеджеров - блокирование и разблокирование ресурсов при многопоточном доступе к объетам, а также закрытие открытых файлов или освобождение захваченных ресурсов.\nprintf(format:FmtChar, ...):Int32 := %printf...; \u0026\u0026 holder: Integer[] = [,]; # Empty tensor Runnable(cnt:Integer) := { $i := 1; @while( $i \u003c= $cnt ) { *holder []= $i; # Lock and add new value $i += 1; @if( $i % ($cnt // 10) == 0) { @with(*holder){ # Lock only printf(\".\"); } } } } $count = 10000; thread1 = :Thread(Runnable, $count); thread2 = :Thread(Runnable, $count); thread3 = :Thread(Runnable, $count); thread4 = :Thread(Runnable, $count); thread5 = :Thread(Runnable, $count); thread1.start(); thread2.start(); thread3.start(); thread4.start(); thread5.start(); thread1.join(); thread2.join(); thread3.join(); thread4.join(); thread5.join(); @assert(*holder.size() == 5*$count); printf(\"Complete %d!\\n\", *holder.size()); Вывод:\n\u003e.................................................. \u003eComplete 50000! \u003e_ ","categories":"","description":"","excerpt":"Одиночный оператор захвата ссылки и синхронизации доступа к объекту …","ref":"/ru/docs/ops/with/","tags":"","title":"Менеджер контекста"},{"body":"Последовательность команд (блок кода) можно прервать в любом месте с помощью специальных операторов.\nДля этого используются две разные команды, которые условно можно назвать положительным и отрицательным прерыванием потока выполнения, что примерно соответствует семантике их записи. “Отрицательное” прерывание записывается в виде двух минусов, а “положительное” прерывание в виде двух плюсов, т.е. -- или ++.\nОператор прерывания не возвращает никакого значения (точнее, возвращает пустое значение). Чтобы прерывание вернуло другое значение, возвращаемые данные нужно записать между парой соответствующих символов, т.е. -- 100 --, что является примерным аналогом оператора return 100; в других языках программирования, а ++‘Строка’++ - аналогом return 'Строка';.\nЛокальный переход Именованные блоки кода могут выступать в качестве локальных меток для передачи потока выполнения. Если перед оператором прерывания указать пространство имен, то оператор прерывания станет именованным и будет действовать только для указанного блока кода.\nВ этом случае отрицательное прерывание будет работать как оператор continue, передавая поток выполнения на первую инструкцию блока кода, а положительное прерывание как оператор break, выходя из него.\nЛокальная передача потока управления работает с именованными блоками кода, поэтому переход в начало блока кода или выход из него, возможны в том числе и изнутри нескольких вложенных именнованных блоков кода.\nb1 := 1; # Бесконечный цикл с именованным блоком кода [1] \u003c-\u003e outer_loop:: { # Именованный блок кода outer_loop b2 := 1; [1] \u003c-\u003e inner_loop { # Именованный блок кода inner_loop printf(\"Values: b1=%d, b2=%d\", b1, b2); # Проверка условий [b1 == 2 \u0026\u0026 b2 == 2] --\u003e { outer_loop:: ++; # Прерываем outer_loop }, [b2 == 5] --\u003e { inner_loop:: ++; # Прерываем inner_loop } b2 += 1; } b1 += 1; } Тоже самое с использованием макросов DSL.:\nb1 := 1; @loop outer_loop:: { # @while(@true) b2 := 1; @loop inner_loop { printf(\"Values: b1=%d, b2=%d\", b1, b2); @if( b1 == 2 @and b2 == 2) { @break outer_loop; } @elif( b2 == 5 ) { @break inner_loop; } b2 += 1; } b1 += 1; } Возврат результата Для возврата результата из тела функции используется положительное прерывание из блока кода, меткой которого является полное имя функции, включая текущую область имен. Имя блока кода тела функции соответствует её имени.\nns:: { # Пространство имен ns func_name(val):Int32 ::= { # Блок кода тела функции ns::func_name:: ... # Возврат из функции func_name ++ 0 ++; # Или @return(0); с ипользованием DSL :: ++ 0 ++; # Завершение программы? exit(0) :: -- ; # Прерывание выполенения программы? abort() }; }; Для оператора прерывания выполенения можно указать и глобальную область видимости. Тогда при выполнении такого прерывания происходит выход из самого верхнеуровневого блока кода, что приводит к завершение работы приложения.\nАналогом такого поведения являются функции exit() для положительного прерывания и abort() для отрицательного, что отражено в DSL.\nПерехват прерывааний Именованные прерывания потока выполнения можно использовать только внутри именованных блоков кода, что контроллируется во время компиляции программы на уровне исходного кода.\nДля не именованных прерываний такое ограничение отсуствует, поэтому более точным аналогом не именованного прерывания будет не return или break, а throw, т.к. эти операторы не только прерывают выполнение последовательности команд в любом блоке кода и возвращают результат, но их еще и можно “ловить”.\nДля перехвата не именованных прерываний используются блоки кода с соответствующей семантикой, {+ … +} - блок кода, который перехватывает положительные прерывания и {- … -} - блок кода, который перехватывает отрицательные прерывания, созданные операторами --, и блок кода {* … *}, который перехватывает сразу оба типа прерываний.\nНапример, возврат из нескольких вложенных функций без необходимости обрабатывать результат возврата в каждой из них. В этом примере функция Test перехватывает “положительные” прерывания из вложенных функций:\nLevel2(arg) := { if($arg==2) { ++ \"Level - 2\" ++; }; \"Level2 - DONE\"; }; Level1(arg) := { if($arg==1) { ++ \"Level - 1\" ++; }; Level2($arg); }; Test(arg) := {+ if($arg \u003e= 0) { Level1($arg); } $arg; +}; Test(2); # Вернет \"Level — 2\" возврат из вложенной функции Level2 Test(1); # Вернет \"Level — 1\" возврат из вложенной функции Level1 Test(0); # Вернет \"Level2 - DONE\" возврат из вложенной функции Level2 Test(-2); # Вернет -2 — возврат из функции Test Обработка ошибок Оба варианта прерываний равнозначны и “отрицательное” прерывание для возврата ошибки используется только условно. Блоки кода с перехватом прерываний, совместно с оператором оценки выражения, можно использовать для обработки исключений в классическом стиле.\n[ {* # Перехват всех исключений на базовом синтаксисе op1; op2; ... *} ] ~\u003e { # Сопоставление по типу возвращенного значения [:ErrorType1] --\u003e { code }; [:ErrorType2, :ErrorType3] --\u003e { code }; [...] --\u003e { code default }; }; # Семантика с применением DSL @try { op1; op2; ... } @catch (...) { # Перехват всех исключений @case(:Error){ ... }; @default @forward; }; # Тоже самое, только для заданных типов @try { op1; op2; ... } @catch (:Type, :Type2, :Type3) { @case(:Type){ ... }; @case(:Type2, :Type3){ ... }; @default @forward; }; Расширенные варинаты прерывания выполнения Добавить реализациию для короутин после их полной реализации в clang (скорее всего на уровне аннотаций)\n@@ coroutine @@ ::= @@ __ANNOTATION_SET__(coroutine) @@; @@ co_yield(...) @@ ::= @@ __ANNOTATION_CHECK__(coroutine) @__FUNC_BLOCK__ :: -- @$... -- @@ co_await @@ ::= @@ __ANNOTATION_CHECK__(coroutine) @__FUNC_BLOCK__ :: +- @@ co_return(...) @@ ::= @@ __ANNOTATION_CHECK__(coroutine) @__FUNC_BLOCK__ :: ++ @$... ++ ns { @coroutine co_func(val):Int32 ::= { # Блок кода тела функции ... # Возврат и приостановка выполнения функции @__FUNC_BLOCK__ :: -- 0 --; # ns::co_func:: -- 0 --; # Или @co_yield(0); с ипользованием DSL # Приостановить и вернуть управление @__FUNC_BLOCK__ :: +-; # ns::co_func:: +-; # Или @co_await; с ипользованием DSL # Возврат и завершение функции @__FUNC_BLOCK__ :: ++ 0 ++; # ns::co_func:: ++ 0 ++; # Или @co_return(0); с ипользованием DSL }; }; Выражение co_yield возвращает значение вызывающей стороне и приостанавливает текущую сопрограмму: это общий строительный блок возобновляемых функций-генераторов.\nco_await +-\nУнарный оператор co_await приостанавливает сопрограмму и возвращает управление вызывающей стороне. Его операнд представляет собой выражение, которое либо (1) относится к типу класса, определяющему оператор-член co_await, либо может быть передано оператору, не являющемуся членом co_await, либо (2) может быть преобразовано в такой тип класса с помощью текущей сопрограммы.\nauto request = await socket.read(...); auto result = await db_client.do_query(prepare_request(request)); await socket.write(prepare_result(result)); socket.close(); request := (){ socket.read(...) }; auto result = (){ request, db_client.do_query(prepare_request(request)) }; (){ socket.write(prepare_result(result)) }; socket.close(); ","categories":"","description":"","excerpt":"Последовательность команд (блок кода) можно прервать в любом месте с …","ref":"/docs/ops/throw/","tags":"","title":"Ввозврат, прерывания и обработка ошибок"},{"body":"Последовательность команд (блок кода) можно прервать в любом месте с помощью специальных операторов.\nДля этого используются две разные команды, которые условно можно назвать положительным и отрицательным прерыванием потока выполнения, что примерно соответствует семантике их записи. “Отрицательное” прерывание записывается в виде двух минусов, а “положительное” прерывание в виде двух плюсов, т.е. -- или ++.\nОператор прерывания не возвращает никакого значения (точнее, возвращает пустое значение). Чтобы прерывание вернуло другое значение, возвращаемые данные нужно записать между парой соответствующих символов, т.е. -- 100 --, что является примерным аналогом оператора return 100; в других языках программирования, а ++‘Строка’++ - аналогом return 'Строка';.\nЛокальный переход Именованные блоки кода могут выступать в качестве локальных меток для передачи потока выполнения. Если перед оператором прерывания указать пространство имен, то оператор прерывания станет именованным и будет действовать только для указанного блока кода.\nВ этом случае отрицательное прерывание будет работать как оператор continue, передавая поток выполнения на первую инструкцию блока кода, а положительное прерывание как оператор break, выходя из него.\nЛокальная передача потока управления работает с именованными блоками кода, поэтому переход в начало блока кода или выход из него, возможны в том числе и изнутри нескольких вложенных именнованных блоков кода.\nb1 := 1; # Бесконечный цикл с именованным блоком кода [1] \u003c-\u003e outer_loop:: { # Именованный блок кода outer_loop b2 := 1; [1] \u003c-\u003e inner_loop { # Именованный блок кода inner_loop printf(\"Values: b1=%d, b2=%d\", b1, b2); # Проверка условий [b1 == 2 \u0026\u0026 b2 == 2] --\u003e { outer_loop:: ++; # Прерываем outer_loop }, [b2 == 5] --\u003e { inner_loop:: ++; # Прерываем inner_loop } b2 += 1; } b1 += 1; } Тоже самое с использованием макросов DSL.:\nb1 := 1; @loop outer_loop:: { # @while(@true) b2 := 1; @loop inner_loop { printf(\"Values: b1=%d, b2=%d\", b1, b2); @if( b1 == 2 @and b2 == 2) { @break outer_loop; } @elif( b2 == 5 ) { @break inner_loop; } b2 += 1; } b1 += 1; } Возврат результата Для возврата результата из тела функции используется положительное прерывание из блока кода, меткой которого является полное имя функции, включая текущую область имен.\nИменованный блок кода при перехвате прерываний возвращают объект, который передавался с помощью прервывания, либо пусто, если возвращаемое значение отсуствует.\nИмя блока кода тела функции соответствует её имени.\nns:: { # Пространство имен ns func_name(val):Int32 ::= { # Блок кода тела функции ns::func_name:: ... # Возврат из функции func_name ++ 0 ++; # Или @return(0); с ипользованием DSL :: ++ 0 ++; # Завершение программы? exit(0) :: -- ; # Прерывание выполенения программы? abort() }; }; Для оператора прерывания выполенения можно указать и глобальную область видимости. Тогда при выполнении такого прерывания происходит выход из самого верхнеуровневого блока кода, что приводит к завершение работы приложения.\nАналогом такого поведения являются функции exit() для положительного прерывания и abort() для отрицательного, что отражено в DSL.\nПерехват прерывааний Именованные прерывания потока выполнения можно использовать только внутри именованных блоков кода, что контроллируется во время компиляции программы на уровне исходного кода.\nДля не именованных прерываний такое ограничение отсуствует, поэтому более точным аналогом не именованного прерывания будет не return или break, а throw, т.к. эти операторы не только прерывают выполнение последовательности команд в любом блоке кода и возвращают результат, но их еще и можно “ловить”.\nДля перехвата не именованных прерываний используются блоки кода с соответствующей семантикой, {+ … +} - блок кода, который перехватывает положительные прерывания и {- … -} - блок кода, который перехватывает отрицательные прерывания, созданные операторами --, и блок кода {* … *}, который перехватывает сразу оба типа прерываний.\nПринципиальное отличие блоков кода для перехвата прерываний от именованных блоков кода состоит в типе возвращаемого значения. Если именованные блоки кода возвращают значение, то при перехвате прервывания, возвращается непосредственно само прерывание, а не возращаемое с его помощью значение.\nНапример, возврат из нескольких вложенных функций без необходимости обрабатывать результат возврата в каждой из них. В этом примере функция Test перехватывает “положительные” прерывания из вложенных функций:\nLevel2(arg) := { if($arg==2) { ++ \"Level - 2\" ++; }; \"Level2 - DONE\"; }; Level1(arg) := { if($arg==1) { ++ \"Level - 1\" ++; }; Level2($arg); }; Test(arg) := * {+ if($arg \u003e= 0) { Level1($arg); } $arg; +}; Test(2); # Вернет \"Level — 2\" возврат из вложенной функции Level2 Test(1); # Вернет \"Level — 1\" возврат из вложенной функции Level1 Test(0); # Вернет \"Level2 - DONE\" возврат из вложенной функции Level2 Test(-2); # Вернет -2 — возврат из функции Test Обработка ошибок Оба варианта прерываний равнозначны и “отрицательное” прерывание для возврата ошибки используется только условно. Блоки кода с перехватом прерываний, совместно с оператором оценки выражения, можно использовать для обработки исключений в классическом стиле.\n[ {* # Перехват всех исключений на базовом синтаксисе op1; op2; ... *} ] ~\u003e { # Сопоставление по типу возвращенного значения [:ErrorType1] --\u003e { code }; [:ErrorType2, :ErrorType3] --\u003e { code }; [...] --\u003e { code default }; }; # Семантика с применением DSL @try { op1; op2; ... } @catch (...) { # Перехват всех исключений @case(:Error){ ... }; @default @forward; }; # Тоже самое, только для заданных типов @try { op1; op2; ... } @catch (:Type, :Type2, :Type3) { @case(:Type){ ... }; @case(:Type2, :Type3){ ... }; @default @forward; }; Расширенные варинаты прерывания выполнения Добавить реализациию для короутин после их полной реализации в clang (скорее всего на уровне аннотаций)\n@@ coroutine @@ ::= @@ __ANNOTATION_SET__(coroutine) @@; @@ co_yield(...) @@ ::= @@ __ANNOTATION_CHECK__(coroutine) @__FUNC_BLOCK__ :: -- @$... -- @@ co_await @@ ::= @@ __ANNOTATION_CHECK__(coroutine) @__FUNC_BLOCK__ :: +- @@ co_return(...) @@ ::= @@ __ANNOTATION_CHECK__(coroutine) @__FUNC_BLOCK__ :: ++ @$... ++ ns { @coroutine co_func(val):Int32 ::= { # Блок кода тела функции ... # Возврат и приостановка выполнения функции @__FUNC_BLOCK__ :: -- 0 --; # ns::co_func:: -- 0 --; # Или @co_yield(0); с ипользованием DSL # Приостановить и вернуть управление @__FUNC_BLOCK__ :: +-; # ns::co_func:: +-; # Или @co_await; с ипользованием DSL # Возврат и завершение функции @__FUNC_BLOCK__ :: ++ 0 ++; # ns::co_func:: ++ 0 ++; # Или @co_return(0); с ипользованием DSL }; }; Выражение co_yield возвращает значение вызывающей стороне и приостанавливает текущую сопрограмму: это общий строительный блок возобновляемых функций-генераторов.\nco_await +-\nУнарный оператор co_await приостанавливает сопрограмму и возвращает управление вызывающей стороне. Его операнд представляет собой выражение, которое либо (1) относится к типу класса, определяющему оператор-член co_await, либо может быть передано оператору, не являющемуся членом co_await, либо (2) может быть преобразовано в такой тип класса с помощью текущей сопрограммы.\nauto request = await socket.read(...); auto result = await db_client.do_query(prepare_request(request)); await socket.write(prepare_result(result)); socket.close(); request := (){ socket.read(...) }; auto result = (){ request, db_client.do_query(prepare_request(request)) }; (){ socket.write(prepare_result(result)) }; socket.close(); ","categories":"","description":"","excerpt":"Последовательность команд (блок кода) можно прервать в любом месте с …","ref":"/ru/docs/ops/throw/","tags":"","title":"Ввозврат, прерывания и обработка ошибок"},{"body":"New features and changes in the syntax of NewLang Reworked the definition of object types using prefix naming (sigils) Interrupting the execution flow and returning can now be done for named code blocks. Simplified the syntax for importing native variables and functions (C/C++) Stabilized the syntax for initializing tensor, dictionary, and function argument values with initial data. Added built-in macros for writing code using keywords in a DSL style New compiler features (nlc) Completely redesigned the macroprocessor. Reworked the compiler architecture with division into parser, macroprocessor, syntax analyzer, interpreter, and code generator. Miscellaneous The documentation website has been translated to Hugo and made bilingual. Instead of binary builds, a section Playground and example code has been added to the website for small experiments. Transition to clang-16 has been completed (transition to clang-17 and newer is planned after full implementation of coroutines and support for extended floating-point number formats). The number of project contributors has increased to more than one! ","categories":"","description":"","excerpt":"New features and changes in the syntax of NewLang Reworked the …","ref":"/blog/release-v0.4/","tags":"","title":"Release of the programming language NewLang 0.4"},{"body":"Новые возможности и изменения в синтаксисе NewLang Переработано определение типов объектов с помощью префикса имен (сигила) Прерывание потока выполнения и возврат теперь может выполняться для именованных блоков кода. Упрощен синтаксис импорта нативных переменных и функций (С/С++) Стабилизирован синтаксис для заполнение начальными данными значений тензоров, словарей и аргументов при вызове функций. Появились встроенные макросы для написания кода с использованием ключевых слов в стиле DSL Новые возможности компилятора (nlc) Полностью переделан макропроцессор. Переработана архитектура компилятора с разделением на парсер, макропроцессор, синтаксический анализатор, интерпретатор и генератор кода. Разное Сайт с документацией переведен на Hugo и сделан двуязычным. Вместо бинарных сборок на сайт добавлен раздел Playground and example code для небольших экспериментов. Выполнен переход на clang-16 (переход на clang-17 и старше планируется после полной реализации корутин и поддержки расширенных форматов чисел с плавающей запятой). Количество контрибуторов проекта стало больше одного! ","categories":"","description":"","excerpt":"Новые возможности и изменения в синтаксисе NewLang Переработано …","ref":"/ru/blog/release-v0.4/","tags":"","title":"Релиз языка программирования NewLang 0.4"},{"body":"\nНедавно прочитал на Хабре статью Свой язык, или как я устал от ассемблера и С, и невольно взглядом зацепился за один абзац:\nЯ решил не сильно париться, поэтому использовал библиотеку parglare. Она очень легкая и удобная, всем рекомендую. Для описания синтаксиса парсер принимает строку в соответствующем формате, использует регулярные выражения (не надо осуждать регулярки, они всесильны!).\nВ результате решил опубликовать статью на основе своих старых записей еще с тех времен, когда идея NewLang до конца еще не выкристаллизовалась, но уже хотелось писать реальный код и тестировать разные концепции.\nВедь в жизни практически любого программиста может наступить момент, когда ему в голову приходит светлая идея - разработать свой собственный язык программирования. Может быть и не ради захвата мира, наравне с C/C++, Python или хотя бы PHP, а в качестве личного пет-проекта, с которым он, длинными зимними вечерами будет оттачивать собственное мастерство.\nА так как у любого языка (не только программирования), все начинается с анализа его грамматики, то самой первой задачей создателя будет выбор инструментов для синтаксического анализа исходного текста.\nЭто история — заметки на память о муках выбора связки лексер-парсер для разбора грамматики NewLang. А так же попытка описать и систематизировать выводы об особенностях разных анализаторов с которыми пришлось поработать при выборе парсера для разбора грамматики у своего языка программирования.\nИспользуемые термины. Чтобы было понятно, о чем в дальнейшем пойдет речь.\nЛексер — компьютерная программа или библиотека, в задачи которой входит разделить входной поток данных на отдельные, не связанные между собой отдельные фрагменты, которые принято называть токенами или лексемами.\nПарсер — на основе последовательности токенов выполняется синтаксический анализ, например строит абстрактное синтаксическое дерево (AST).\nЗаход № 1 - Flex + Bison GitHub - westes/flex: The Fast Lexical Analyzer - scanner generator for lexing in C and C++ Bison - GNU Project - Free Software Foundation\nПосле прочтения умных книжек я начал с классики Flex + Bison. Это старые и давно отработанные приложения с широчайшими возможностями по настройке с помощью которых можно описать синтаксис и получить исходные файлы лексера и парсера для языка практически с любой грамматикой.\nК сожалению, у этих старичков очень большой порог входа и тяжелая наследственность. Чего только стоит определение собственного класса лексера через #define, а так же отсутствие нормальной поддержки С++. Вынужденные танцы с бубном для пасинга отдельной строки, когда не требуется анализировать файл целиком и прочие не всегда очевидные проблемы и разные не понятные условности.\nДругими словами, через несколько недель безуспешных мучений я решил посмотреть альтернативы, а так как начальный файл лексики после экспериментов с Flex + Bison кое-как уже был сделан, то следующая связка была Flex + lemon.\nЗаход № 2 - Flex + Lemon The Lemon LALR(1) Parser Generator\nТут все оказалось до примитивности просто и понятно. Реально очень быстрый старт с боевыми примерами, очень наглядный и понятный способ записи правил (по сравнению с Bison). Все хорошо кроме одного, хорошее быстро заканчивается, если приходится анализировать более одной строки.\nПо сути, Lemon с Bison, это как Инь и Янь. Lemon простой и удобный для работы с одной строкой (для этого он и создавался), а Bison супер-пупер-мега комбайн для парсинга файлов любых размеров.\nПоэтому, поиски связки лексер + парсер продолжились и после прочтения очередной статьи, что парсеры языков можно делать на регулярках, решил посмотреть, что есть в этом направлении:\nЗаход № 3 парсер на регулярках re2c Из описания re2c:\nПо сути, на этой штуке можно писать лексические анализаторы прямо на коленке за несколько минут.\n/*!re2c re2c:define:YYPEEK = \"*cursor\"; re2c:define:YYSKIP = \"++cursor;\"; re2c:define:YYBACKUP = \"marker = cursor;\"; re2c:define:YYRESTORE = \"cursor = marker;\"; re2c:define:YYBACKUPCTX = \"ctxmarker = cursor;\"; re2c:define:YYRESTORECTX = \"cursor = ctxmarker;\"; re2c:define:YYRESTORETAG = \"cursor = ${tag};\"; re2c:define:YYLESSTHAN = \"limit - cursor \u003c @@{len}\"; re2c:define:YYSTAGP = \"@@{tag} = cursor;\"; re2c:define:YYSTAGN = \"@@{tag} = NULL;\"; re2c:define:YYSHIFT = \"cursor += @@{shift};\"; re2c:define:YYSHIFTSTAG = \"@@{tag} += @@{shift};\"; */ Показалось, что это самый удобный способ указания шаблонов для парсера! Достаточно описать в комментариях нужные шаблоны, напустить на исходный файл компилятор регулярок и все готово! Но нет, действительно, это только показалось.\nВедь для простеньких парсеров или регулярных выражений re2c может быть и действительно хорош, но отлаживать синтаксис большого языка на регулярках слишком хлопотное занятие.\nПосле этого решил с ним не заморачиваться и посмотреть альтернативы классическим лексерам и парсерам.\nЗаход № 4 - flex (flexcpp) + bisoncpp Тогда как у традиционных flex + bison поддержка С++ реализована через одно место на уровне - работает и не трогай, то решил посмотреть их альтернативную реализация flexcpp + bisoncpp с нативной поддержкой С++.\nПервое впечатление было, то что доктор прописал!\nСинтаксис записи лексики хоть немного и отличается от классической, но это не принципиально. Зато есть нативная и логичная поддержка С++ без оберток и выкрутасов, и как дополнительный плюс - более удобный синтаксис указания правил в парсере. Но и тут не обошлось без шероховатостей.\nВ шаблонах правил bisoncpp не поддерживает юникод (хотя сам лексер-парсер с ним справляется на ура), и совсем не понятная ситуация с поддержкой. Как я понял, разработчиком является вроде бы один человек, но пообщаться с ним насчет ошибок при обработке русских символов так и не получилось.*\nПотом еще одно непонятное поведение вылезло в другом месте. В результате решил отказаться от недружелюбной поддержки и посмотреть, какие есть еще варианты парсеров.\n*) Через два года мой тикет был закрыт с комментарием, что поддерживаются только ascii символы.\nЗаход № 5 - неродной парсер ANTLR От использования ANTLR (от англ. ANother Tool for Language Recognition — «ещё одно средство распознавания языков») — генератора нисходящих анализаторов для формальных языков, я решил сразу отказать из-за того, что он написан на Java,.\nВ этом нет никаких религиозных предпочтений, так как я искал генератор парсеров, который можно было бы сделать встроенным прямо в среду выполнения, а в случае с ANTLR и JRE это было бы затруднительно.\nТаким образом я опять вернулся к старичкам Flex и Bison, с которых все и начиналось.\nЗаход № 6, последний - возвращение к Flex + Bison Все описанные выше эксперименты заняли в общем итоге несколько месяцев, в результате которых были написаны килобайты исходного кода и тестовых примеров, прочитано десятки статей и как результат - возврат к изначальной связке Flex + Bison, но уже с солидным багажом опыта в применении различных вариантов лексеров-парсеров.\nНо самое главное, с пониманием того, что же в результате хочется получить, и очень большой базой тестовых примеров синтаксиса.\nВыводы на память В итоге для себя решил следующее: если нужен простенький шаблонизатор, то идеальный вариант re2c (если почему-то не подходит regexp). Если требуется анализировать синтаксис сложнее обычных регулярок, но в одну строку, то идеальной будет связка flex+lemon, а если нужна серьезная артиллерия, то тут однозначно flex + bison.\nОт связки flexcpp + bisoncpp отказался совсем. Что с поддержкой — не понятно, синтаксис от классики отличается не очень сильно (хотя тоже нужно ломать голову), а обход выявленных косяков не стоят того синтаксического сахара.\nИ по итогам множества экспериментов с разными вариантами синтаксиса удалось сформулировать пару важных архитектурных моментов, которые могут очень сильно упростить жизнь создателям языком программирования:\nСтратегия обработки ошибок синтаксиса Обычно принято обрабатывать синтаксические ошибки непосредственно в парсере и для этого есть определенный резон — в этом случае нет необходимости в каких либо дальнейших действиях, нужна только полностью описанная корректная грамматика.\nНо если грамматика языка очень сложная (привет C++), и её описание становится сложной задачей, то можно отказался и от анализа ошибок синтаксиса непосредственно в парсере! То есть, лучше сделать максимально широкую лексику (даже с теми вариантами, которые являются для языка ошибочными), но ловить эти ошибки уже при анализе AST!\nВ этом случае, поддерживать описание грамматики языка становится значительно проще (меньше синтаксических правил, проще их формальное описание и т.д.), а самое главное, при описании грамматики не нужно думать про lval или rval, где можно указывать ссылку, а где нет — т. е. можно указывать все и везде, а вот анализ допустимости использования конкретных терминов будет выполняться позднее при анализе AST.\nОтказа от полного анализа грамматики языка на уровне лексера — парсера и перенос проверки корректности синтаксических конструкций на этап разбора синтаксического дерева позволяет в разы, если не на порядки сократить и значительно упростить описание грамматических правил!\nПодобное допущение очень полезно на начальном этапе создания языка (можно сосредоточиться на общей концепции, вместо постоянных правок в грамматике), а так же значительно упростить в будущем поддержку и/или расширение синтаксиса.\nМакросы и модификация грамматики в Runtime Какими бы мощными не были flex+bison, но у этой связки есть одна архитектурная проблема. Логика flex и bison построена на конечных автоматах и изменить грамматику языка во время выполнения приложения невозможно, тем более Bison сам вызывает лексер для получения очередной порции данных и ему очень непросто подсунуть измененные данные прямо во время работы. А так хотелось сделать возможность раскрытия макросов и модификации синтаксиса за один проход анализатора!\nДля этого пришлось переделать логику работы flex+bison, чтобы парсер получал данные из лексера не напрямую из yylex, а через функцию — прокси. Эта промежуточная функция, складывает считанные лексемы во внутренний буфер. Данные в буфере анализируется на предмет наличия макросов и только после их раскрытия, лексемы отдаются в парсер из вершины буфера по одной за раз. Подробнее о макросах NewLang можно почитать тут.\nСамое главное при разработке грамматики! Но самый важный совет мне подсказал друг, который некогда участвовал в проекте по разработке парсера для языка программирования. И в правильности его совета - пиши тесты для грамматики - я убеждался уже множество раз. Даже так, ПИШИ ТЕСТЫ ДЛЯ ГРАММАТИКИ.\nТесты для грамматики языка гораздо более важная вещь, чем любой из используемых инструментов. Только тесты позволяют убедиться в том, что новая фича в языке не сломала старые наработки. А если все же сломала, то в первую очередь нужно добавить новый тест, который бы фиксировал сломавшийся сценарий и только после этого можно будет со спокойной душой продолжать эксперименты с новыми грамматическими конструкциями.\nИ удачи всем языкописателям!\nСсылка на первую публикаци\n","categories":"","description":"","excerpt":"\nНедавно прочитал на Хабре статью Свой язык, или как я устал от …","ref":"/ru/blog/parser-nuances/","tags":"","title":"Нюансы разработки парсера для своего языка программирования"},{"body":" Attention!!!\nThis article contains a description of the NewLnag syntax of the previous version.\nPublication source https://habr.com/articles/720416/\nThis is a translation of my own article\nThe release of NewLang language with a brand new “feature” is coming, a remodeled version of the preprocessor that allows you to extend the language syntax to create different DSL dialects using macros.\nWhat is it about? DSL (Subject Oriented Language) is a programming language specialized for a specific application area. It is believed that the use of DSL significantly increases the level of abstractness of the code, and this allows to develop more quickly and efficiently and greatly simplifies the solution of many problems.\nConditionally, we can distinguish two approaches to DSL implementation: Development of independent syntax translators using lexer and parser generators to define the grammar of the target language through BNF (Backus–Naur form) and regular expressions (Lex, Yacc, ANTLR, etc.) and then compiling the resulting grammar into machine code. Development or integration of the DSL dialect into a general-purpose language (metalanguage), including the use of various libraries or special parsers / preprocessors. We will talk about the second option, namely the implementation of DSL on the basis of general-purpose languages (metalanguages) and the new implementation of macros in NewLang as the basis for DSL development.\nTwo extremes It probably makes sense to start by describing two extremes in the implementation of a DSL based on a general-purpose language (metalanguage):\nLimited grammar. If a programming language is limited to its own fixed grammar and does not allow for its expansion, when implementing DSL the developer will be forced to use the existing grammar, the rules for recording operations and generally all syntax will remain the same as in the implementation language. For example, when using C/C++ as a base language, or using various libraries and frameworks in other general-purpose programming languages.\nIn this case, the term “DSL” will simply be a set of domain-specific terms, overridden macros and/or operators, but the use of which will be restricted by the implementation language grammar.\nUnrestricted grammar. If a language (metalanguage) allows you to modify its own grammar (for example at the level of AST), then DSL will no longer be strictly bounded by the syntax of the underlying programming language, and as a result its grammar can be whatever you want. Up to the point that “for every new project you will have to learn a new language…”. This can be done by using specialized metalanguages (Lisp, ML, Haskell, Nemerle, Forth, Tcl, Rebol, etc.).\nI strongly recommend you to read an excellent article on metaprogramming by @NeoCode [Metaprogramming: what it is and what it should be] (https://habr.com/post/258667/).\nThe following implementation of macros is offered for discussion “There is no perfection in the world”, and after the release of NewLang 0.2, I received a lot of feedback (mostly negative), about the first version of macro implementation and DSL based on it. And those criticisms were often valid. So I decided to try to redesign the macros a bit, in hopes of getting a “middle ground” between the two extremes described above when describing the DSL.\nTerminology Used Macros in NewLang, are one or more terms that are replaced by another term or by an entire lexical construct (a sequence of tokens). Macros are both an extension of basic language syntax, when implementing DSL’s own dialects, and a syntax sugar.\nThe main feature of macros is that they allow expressions to be changed before they are evaluated at runtime. Macros are expanded at runtime lexer, which allows you to substitute any other terms with them and even modify the language syntax itself.\nThat’s why if you don’t specify a modifier before the NewLang object name (****macros, **$**local_variable or **@**module), the program will first search among macros, then among local variables and finally among modules (object from module). This allows you to use terms without modifiers to specify types of objects.\nMacro definitions The definition of macros uses exactly the same syntax as for other language objects (the operators “::=”, “=” or “:=” are used respectively to create a new object, assign a new value to an existing object or to create/assign a new value to an object regardless of its presence or absence).\nIn general, a macro definition consists of three parts \u003c macro name \u003e \u003c creating/assignment operator \u003e \u003c macro body \u003e and final semicolon “;*”.\nMacro body The macro body can be a correct language expression, a sequence of tokens (framed in double backslashes, i.e. \\\\ lexem1 lexem2 \\\\) or a plain text string (framed in triple backslashes, i.e. \\\\\\ text string \\\\\\).\nTo connect two tokens into one (analogous to the ## operation in the C/C++ preprocessor), used by analogy syntax ##. A similar operator is used to frame a lexeme in quotes #, for example, \\macro($arg) := \\\\\\ func_ \\## \\$arg(\\#arg) \\;, then a call to macro(arg) will be expanded to func_arg (\"arg\");\nMacro Name The macro name can be a single identifier with the macro prefix “\\” or a sequence of several lexem. If a sequence of lexem is used as the macro name there must be at least one identifier among them and there can be one or more templates.\nA template is a special identifier that can be replaced by any single term during matching. With the help of templates the search by pattern and replacement of the set sequences of lexemes on a body of a macro is made.\nTo specify a template, you need to put a dollar sign at the beginning of the identifier (which corresponds to the local variable name record), i.e. \\\\one_lexem\\\\, \\\\total three tokens\\\\ \\\\ lexem $template1 $template2 \\\\.\nMacros are considered identical if their identifiers are equal, the number of elements in their names is the same, and identifiers and templates are in the same places.\nMacro Arguments Terms or templates in a macro name can have arguments, which are specified in parentheses. The passed arguments in the body of macro are written in the disclosure space as a local variable name, but a backslash must be added before the name, i.e. \\$name.\nAn arbitrary number of parameters in a macro is marked with a triple colon “…”, and the place for inserting these arguments is marked with the token $…. If a macro has several identifiers with arguments, the place marked with the desired identifier to insert arguments from a marked identifier, for example, $name….\nTo insert the number of actually passed arguments, the lexeme $# is used, or with the marked identifier, for example, $#name.\n*Macros work with lexem that contain various information, including the data type if it is specified. But at the moment data types in macro arguments are not handled in any way, and this is one of the mandatory features that will be implemented in the future.\nExamples: \\macros1 := 123; \\macros2(arg) := { func( \\$arg ); func2(123);}; \\\\ macros of(...) tokens \\\\ := \\\\ call1(); call2( \\$... ); call3() \\\\; \\text_macros := \\\\\\ string for the lexer \\\\\\; # Ordinary macros (macro body is a valid expression) \\macro := replace(); \\macro2($arg) := { call( \\$arg ); call() }; # The function takes the number of arguments and the arguments themselves \\\\func name1(...)\\\\ := name2( \\$#, \\$name1... ); # macro body from a sequence of tokens \\if(...) := \\\\ [ \\$... ] --\u003e \\\\; # Expression may not be complete \\else := \\\\ ,[ _ ] --\u003e \\\\; # Expression may not be complete # Macro body from text string (like in C/C++ preprocessor) \\macro_str := \\\\\\ string - macro body \\\\\\; # String for the lexer \\macro($arg) := \\\\ func_ \\## \\#arg(\\#arg)\\\\; # macro(arg) -\u003e func_arg (\"arg\") What possibilities does this offer? You can define macros in the following combinations this way:\n№ Macro name Macro body ---------------------------------------------------------------- 1. \\identifier expression 2. \\identifier \\\\lexem1 lexeme2\\\\ 3. \\Identifier \\\\\\string for the lexer\\\\\\. 4. \\\\lexeme1 lexeme2\\\\ expression 5. \\\\lexeme1 lexeme2\\\\ \\\\lexeme1 lexeme2\\\\ 6. \\\\lexeme1 lexeme2\\\\ \\\\\\ line for the lexer \\\\\\ Each of the above combinations has its own properties and limitations: Classic replacement of one term with another term or integer expression. It is handled by lexer and parser once during definition. The expression in the macro body has to be correct in terms of syntax, and if there are errors in it, a message about this is generated immediately, while still defining the macro.\nClassical replacement of one term by sequences of tokens, including incomplete syntactic constructions. It is processed by the lexer once during macro definition. The body of the macro is parsed by the parser when it is used, so possible syntax errors will be noticed only when the macro is expanded.\nClassic replacement of a single term with a text string, which is fed to the lexer’s input. Only the macro name is once processed by the lexer when it is defined, allowing you to modify the macro body and change/combine/modify lexemes before feeding them into the analyzer. Syntax errors will be noticed only when the macro is expanded.\n4, 5 и 6. Replacing a sequence of several tokens (templates) with an expression, a sequence of tokens or a text string, respectively.\nPurpose and examples of use Macros are also used to convert the basic NewLang syntax into a more familiar keyword-based syntax, because such text is much easier to understand when reading the source code later.\nIf no modifier is specified before the name of NewLang object (**\\**macros, **$**local_variable or **@**module), then macros name is searched first, then the name of local variable and last, the name of module (module object). This makes it possible to define DSL syntax in the usual way without the obligatory prefixes for different types of objects.\nFor example, writing a conditional statement in the basic syntax NewLang:\n[condition] --\u003e { ... } [ condition2 ] --\u003e { ... } [ _ ] { ... }; # With macros \\if(...) := \\\\ [ \\$... ]--\u003e \\\\; \\elif(...) := \\\\ ,[ \\$... ]--\u003e \\\\; \\else := \\\\ ,[ _ ]--\u003e \\\\; # Turns into classical notation if( condition ){ ... } elif( condition2 ){ ... } else { ... }; Or loop to 5:\ncount := 1; [ 1 ] \u003c-\u003e { [ count\u003e5 ] --\u003e { ++ 42 ++; }; count += 1; }; will look more familiar with the use of appropriate macros:\n\\while(...) := \\\\ [ \\$... ] \u003c-\u003e \\\\; \\return(...) := ++ \\$... ++; \\true := 1; count := 1; while( true ) { if( count \u003e 5 ) { return 42; }; count += 1; }; Deleting macros To delete a macro, you have to assign it an empty sequence of tokens \\macro_str := \\\\\\\\;. You can use a special syntax to delete it: \\\\\\\\ name \\\\\\\\; or \\\\\\\\ \\\\two terms\\\\ \\\\\\\\;, i.e. specify the macro name between four backslashes.\nThe necessity to use a separate syntax construct to remove macros is caused by the fact that macro names are processed by the lexer even before the parsing stage in the parser.\nWhat’s the upside? You can dilute the basic language syntax with additional keywords and turn it into a familiar “keyword-based” syntax. Macros are defined according to the language’s vocabulary, and macros are treated as normal objects. Ease of source code analysis and debugging. You can make explicit use of DSL terms and metaprogramming techniques, for example, always prefix the macro name. That way the compiler will know very well that the macro needs to be expanded. Although you can modify the language syntax significantly at your own risk, you can only do so within certain constraints (AST cannot be modified directly), which does not allow you to go very far and, for example, crash or hang the compiler. In spite of very big possibilities to modify the syntax, you get a very simple, fast and unambiguous implementation. And this positively affects the speed of source code analysis, detection and processing of possible errors and simultaneously represents a reasonable compromise between the complexity of implementation of this functionality and possibilities of defining own DSL dialects. If desired, there is room to develop metaprogramming capabilities. In the future we could add pattern-matching (e.g. based on regular expressions), make string parametrization for generating syntax in the body of a macro, including in runtime, and many other different ways to elegantly shoot yourself or your comrade in the foot. Conclusion Any feedback on this macro implementation would be appreciated. And twice as grateful if, in addition to criticism, there are suggestions for its improvement and refinement, if any point has been missed.\n","categories":"","description":"A short lead description about this content page. Text here can also be **bold** or _italic_ and can even be split over multiple paragraphs.\n","excerpt":"A short lead description about this content page. Text here can also …","ref":"/blog/dsl-domain-specific-language-implementation-with-macros/","tags":"","title":"DSL (domain-specific language) implementation with macros"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nБлизится релиз языка NewLang с принципиальной новой «фишкой», переделанным вариантом препроцессора, который позволяет расширять синтаксиса языка для создания различных диалектов DSL за счет макросов.\nИ, как всегда, используя ранее найденный лайфхак Хабр — ума палата, хотелось бы получить от читателей обратную связь насчет предлагаемого ниже подхода, который планируется к реализации в новом препроцессоре NewLang.\nО чем идет речь? DSL (Предметно-ориентированный язык) - язык программирования, специализированный для конкретной области применения. Считается, что использование DSL существенно повышает уровень абстрактности кода, а это позволяет вести разработку более быстро и эффективно и существенно упрощает решение многих задач.\nУсловно, можно выделить два подхода к реализации DSL: Разработка независимых трансляторов синтаксиса с помощью генераторов лексеров и парсеров для определения грамматики целевого языка посредством БНФ и регулярных выражений (Lex, Yacc, ANTLR и т. д.) и последующей компиляцией полученной грамматики в машинный код. Разработка или встраивание диалекта DSL на языке (метаязыке) общего назначения, в том числе за счет применения различных библиотек или специальных парсеров / препроцессоров. Далее речь пойдет о втором варианте, а именно, о реализации DSL на базе языков (метаязыков) общего назначения и новом варианте реализации макросов в NewLang как основы для разработки DSL.\nДве крайности Наверно имеет смысл начать с описания о двух крайностях при реализации DSL на базе языка (метаязыка) общего назначения:\nОграниченная грамматика Если язык программирования ограничен собственной фиксированной грамматикой и не допускает её расширения, то при реализации DSL разработчик будет вынужден использовать уже существующую грамматику, правила записи операций и вообще весь синтаксис будет оставаться такими же, как в языке реализации. Например, при использовании в качестве базового языка С/С++ или применении различных библиотек и фреймворков в других языках программирования общего назначения.\nВ этом случае под термином “DSL” будет скрываться просто набор специфических терминов предметной области, переопределенных макросов и/или операторов, но использование которых будет ограничено грамматикой языка реализации.\nНеограниченная грамматика Если же язык (метаязык) позволяет модифицировать собственную грамматику (например на уровне AST), то DSL уже не будет жестко огранен синтаксисом базового языка программирования, и в результате его грамматика может быть какой угодно. Вплоть до того, что «для каждого нового проекта придется изучать новый язык… ». Это можно сделать с помощью использования специализированных метаязыков (Lisp, ML, Haskell, Nemerle, Forth, Tcl, Rebol и пр.)\nОчень рекомендую прочитать о метапрограммровании великолепную статью @NeoCode Метапрограммирование: какое оно есть и каким должно быть.\nДля обсуждения предлагается следующая реализация макросов «Нет в мире совершенства», и после выпуска релиза NewLang 0.2 я получил много отзывов (по большей части негативных), по поводу первого варианта реализации макросов и DSL на их основе. И если положить руку на сердце, эта критика часто была обоснованной. Поэтому я решил попробовать немного переделать макросы, в надежде получить «золотую середину» между двумя описанными выше крайностями при описании DSL.\nИспользуемая терминология Макросы в NewLang, это один или несколько терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем). Макросы являются одновременно и расширением базового синтаксиса языка, при реализации собственных диалектов DSL, и синтаксическим сахаром.\nГлавная особенность макросов в том, что они позволяют изменять выражения еще до их вычисления во время выполнения. Раскрытие макросов происходит во время работы лексера, что позволяет подменять ими любые другие термины и даже модифицировать сам синтаксис языка.\nПоэтому, если перед именем объекта NewLang модификатор не указывать (**\\**макрос, **$**локальная_переменная или **@**модуль), то сперва будет производиться поиск объекта среди макросов, потом среди локальных переменных и в последнюю очередь среди модулей (объектов модуля). За счет этого можно использовать термины без обязательных модификаторов для указания конкретных типов объектов.\nОпределение макросов Для определения макросов используется точно такой синтаксис, как и для других объектов языка (применяются операторы «::=», «=» или «:=», соответственно для создания нового объекта, присвоение нового значения уже существующему или для создания объекта / присвоения нового значения объекту не зависимо от его наличия или отсутствия).\nВ общем виде, определение макроса состоит из трех частей \u003cимя макроса\u003e \u003cоператор создания/присвоения\u003e \u003cтело макроса\u003e и завершающая точка с запятой “;”.\nТело макроса Телом макроса могут быть корректное выражение языка, последовательность лексем (которые заключается в двойные обратные слеши, т.е. \\\\лексема1 лексема1\\\\) или обычная текстовая строка (обрамленная в тройные обратные слеши, т.е. \\\\\\ текстовая строка \\\\\\).\nДля соединения двух лексем в одну (аналог операции ## в препроцессоре С/С++), используется по аналогии синтаксис ##. Похожий оператор применяется и для обрамления лексемы в кавычки #, например, \\macro($arg) := \\\\ func_ \\## \\#arg(\\#arg) \\\\;? тогда вызов macro(arg) будет преобразован в func_arg (\"arg\");\nИмя макроса Именем макроса может быть одиночный идентификатор с префиксом макроса “\\” или последовательность из нескольких лексем. Если в качестве имени макроса используется последовательность лексем, то среди них должен быть как минимум один идентификатор и может присутствовать один или несколько шаблонов.\nШаблон — это специальный идентификатор который при сопоставлении может заменяться любым одиночным термином. С помощью шаблонов производится поиск по образцу и замена заданных последовательностей лексем на тело макроса.\nДля указания шаблона в начале идентификатора нужно поставить знак доллара (что соответствует записи имени локальной переменой), т. е. \\\\одна_лексема\\\\, \\\\целых три лексемы\\\\ **\\\\**лексема $шаблон1 $шаблон2 \\\\.\nМакросы считаются одинаковыми, если их идентификаторы равны, количество элементов в их именах совпадает, а идентификаторы и шаблоны располагаются на тех же самых местах.\nАргументы макросов Термины или шаблоны в имени макроса могут иметь аргументы, которые указываются в круглых скобках. Переданные аргументы в теле макроса записываются в месте для раскрытия как имя локальной переменой, но перед именем нужно добавить обратный слеш, т.е. \\$name.\nПроизвольное количество параметров у макроса отмечается троеточием “…”, а место для вставки этих аргументов отмечается лексемой $…. Если у макроса есть несколько идентификаторов с аргументами, то для вставки аргументов из конкретного идентификатора используется лексема с указанием нужного идентификатора, например, $name….\nЧтобы вставить количество реально переданных аргументов используется лексема $#, или с указанием нужного идентификатора, например, $#name.\nМакросы работают с лексемами, которые содержат различную информацию, в том числе и о типе данных, если она указана. Но на текущий момент типы данных в аргументах макросов никак не обрабатываются и это одна из обязательных фич, которая будет реализована в будущем.\nПримеры: \\макрос1 := 123; \\макрос2(arg) := {func( \\$arg ); func2(123);}; \\\\макрос из(...) лексем\\\\ := \\\\ call1(); call2( \\$... ); call3() \\\\; \\текстовый_макрос := \\\\\\ строка для для лексера \\\\\\; # Обычные макросы (тело макроса корректное выражение) \\macro := replace(); \\macro2($arg) := { call( \\$arg ); call()}; # В функцию передается кол-во аргументов и сами аргументы \\\\func name1(...)\\\\ := name2( \\$#, \\$name1... ); # Тело макросов из последовательности лексем \\if(...) := \\\\ [ \\$... ] --\u003e \\\\; # Выражение может быть не полным \\else := \\\\ ,[ _ ] --\u003e \\\\; # Выражение может быть не полным # Тело макроса из текстовой строки (как в препроцессоре С/С++) \\macro_str := \\\\\\ строка - тело макроса \\\\\\; # Строка для лексера \\macro($arg) := \\\\\\ func_ \\## \\#arg(\\#arg)\\\\\\; # macro(arg) -\u003e func_arg (\"arg\") Какие возможности это дает? Таким образом можно определить макросы в следующих комбинациях:\n№ п/п Имя макроса Тело макроса ---------------------------------------------------------------- 1. \\идентификатор выражение 2. \\идентификатор \\\\лексема1 лексема2\\\\ 3. \\идентификатор \\\\\\строка для лексера\\\\\\ 4. \\\\лексема1 лексема2\\\\ выражение 5. \\\\лексема1 лексема2\\\\ \\\\лексема1 лексема2\\\\ 6. \\\\лексема1 лексема2\\\\ \\\\\\строка для лексера\\\\\\ Каждая из перечисленных выше комбинации имеет свои свойства и ограничения:\nКлассическая замена одного термина на другой термин или целое выражение. Однократно обрабатывается лексером и парсером при определении. Выражение в теле макроса должно быть корректным с точки зрения синтаксиса и при наличии в нем ошибок, сообщение об этом формируется сразу, еще при определении макроса.\nКлассическая замена одного термина на последовательности лексем, в том числе и не полные синтаксические конструкции. Однократно обрабатывается лексером при определении макроса. Тело макроса анализируется парсером при его использовании, поэтому возможные синтаксические ошибки будут замечены только при раскрытии макроса.\nКлассическая замена одного термина на текстовую строку, которая подается на вход лексера. Однократно обрабатывается лексером только имя макроса при его определении, что позволяет модифицировать тело макроса и изменять/комбинировать/модифицировать лексемы до их подачи в анализатор. Синтаксические ошибки будут замечены только при раскрытии макроса.\n4, 5 и 6. Замена последовательности из нескольких лексем (шаблонов) на выражение, последовательность лексем или текстовую строку соответственно.\nНазначение и примеры использования Макросы используются и для преобразования базового синтаксиса NewLang в более привычный синтаксис на основе ключевых слов, так как такой текст гораздо легче воспринимается при последующем чтении исходного кода.\nЕсли перед именем объекта NewLang модификатор не указан (**\\**макрос, **$**локальная_переменная или **@**модуль), то сперва ищется имя макроса, потом имя локальной переменной и в последнюю очередь имя модуля (объекта модуля). За счет этого получается определять синтаксис DSL в привычной записи без обязательных префиксов у разных типов объектов.\nНапример, запись условного оператора на основном синтаксисе NewLang:\n[condition] --\u003e { ... } [ condition2 ] --\u003e { ... } [ _ ] { ... }; # С помощью макросов \\if(...) := \\\\ [ \\$... ]--\u003e \\\\; \\elif(...) := \\\\ ,[ \\$... ]--\u003e \\\\; \\else := \\\\ ,[ _ ]--\u003e \\\\; # Превращается в классическую запись if( condition ){ ... } elif( condition2 ) { ... } else { ... }; Или цикл до 5:\ncount:=1; [ 1 ] \u003c-\u003e { [count\u003e5] --\u003e { ++ 42 ++; }; count+=1; }; будет выглядеть более привычно с использованием соответствующих макросов:\n\\while(...) := \\\\ [ \\$... ] \u003c-\u003e \\\\; \\return(...) := ++ \\$... ++; \\true := 1; count := 1; while( true ) { if( count \u003e 5 ) { return 42; }; count += 1; }; Удаление макросов Для удаления макроса нужно присвоить ему пустую последовательность лексем \\macro_str := \\\\\\\\;. Так же для удаления можно использовать специальный синтаксис: \\\\\\\\ name \\\\\\\\; или \\\\\\\\ \\\\два термина\\\\ \\\\\\\\;, т.е. указать имя макроса между четырьмя обратными слешами.\nНеобходимость использования отдельной синтаксической конструкции для удаления макросов вызвана тем, что имена макросов обрабатываются лексером еще до этапа анализа в парсере.\nВ чем профит? Базовый синтаксис языка можно разбавлять дополнительными ключевыми словами и превратить его в привычный «keyword-based». Определение макросов соответствует лексике языка, а сами макросы обрабатываются как обычные объекты. Простота анализа исходного кода и его отладки. Использование терминов DSL и приемов метапрограммирование можно сделать явным, например, всегда перед именем макроса указывать префикс. В этом случае компилятор будет однозначно знать, что требуется выполнить раскрытие макроса. Несмотря на то, что синтаксис языка на свой страх и риск можно значительно модифицировать, но это можно сделать только в рамках определенные ограничений (AST нельзя модифицировать напрямую), что не позволяется очень сильно разгуляться и, например, обрушить или подвесить компилятор. Несмотря на очень большие возможности по модификации синтаксиса, получается очень простая, быстрая и однозначная реализация. А это положительно сказывается на скорости анализа исходников, детектирования и обработки возможных ошибок и одновременно является разумным компромиссом между сложностью реализации данного функционала и возможностями определения собственных диалектов DSL. При желании есть куда развивать возможности метапрограммирования. В будущем можно добавить сопоставление шаблона с образцом (например, на основе регулярных выражений), сделать параметризацию строки для генерации синтаксиса в теле макроса, в том числе и в рантайме, и много других разных способов изящно выстрелить себе в ногу или ногу своего товарища. Заключение Буду благодарен за любую обратную связь по данной реализации макросов. И дважды благодарен, если кроме критики будут высказаны еще и предложения по её улучшению и доработкам, если какой-то момент был упущен.\nСсылка на первую публикаци\n","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/ru/blog/dsl-with-macros/","tags":"","title":"Вариант реализации DSL (domain-specific language) с помощью макросов"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nNewLang — это язык программирования высокого уровня общего назначения. Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан на строгой системе грамматических правил. За счет использования макросов, синтаксис языка легко расширяется до более привычного вида на основе ключевых слов.\nNewLang находится в процессе активного развития. Это третий публичный релиз в который добавлены новые существенные возможности по сравнению с предыдущей версией.\nЗачем нужен NewLang? У всех современных языков программирования происходит постоянное развитие (усложнение) синтаксиса по мере выхода новых версий. Это является своего рода платой за появление новых возможностей и воспринимается пользователями как естественное явление.\nНо одновременно является и серьезной проблемой, так как с выходом версий добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки и поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.\nУ NewLang сложность языковых конструкций ограничена естественным образом за счет разделения синтаксиса языка на две части - это упрощает его изучение и использование.\nОсновной синтаксис — для написания программ в объектно-ориентированном (императивном) и декларативном стилях, который основан не на зарезервированных ключевых словах, а на системе строгих грамматических правил. Имеется возможность расширения основного синтаксиса за счет использования макросов. Расширенный синтаксис — программные вставки на языке реализации (С/С++), когда основного синтаксиса становится недостаточно.\nЕще одно неудобство современных языков в том, что большинство из них были созданы до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек. Это же касается и вычислений с неограниченной точностью, которые так же требуют применения дополнительных библиотечных функций.\nУ NewLang тензорные вычисления и рациональные числа неограниченной точности доступны «из коробки». Они поддерживаются на уровне синтаксиса для записи литералов соответствующих типов, а простые арифметические типы данных являются скалярами (тензорами нулевой размерности). Реализация тензорных вычислений сделана на базе библиотеки libtorch, а рациональные числа с использованием OpenSSL.\nНовые глобальные фичи и изменения в синтаксисе: Простые чистые функции удалены Раньше я пытался использовать синтаксис предикатов из Пролога, в котором проверки условий записываются через запятую. Но эта идея оказалась провальной, а сами операторы просто ужасными (тестировал разные варианты, но каждый раз получал много отрицательных отзывов), поэтому сейчас решил полностью от них отказаться.\nОни получались не только сложными для восприятия, но и по факту не нужными, так как легко заменялись обычной функцией с комбинации обычных логических операций.\nЗафиксирован синтаксис операторов проверки условия и циклов. Изменен и упрощен синтаксис операторов проверки условия (импликации) и цикла, для которых оставлено только по одному варианту. Проверка условия записывается в виде оператора математического следования –\u003e, а цикл с помощью оператора \u003c-\u003e.\nНо для упрощения записи можно пользоваться макросами, тогда в этом случае операции проверки условий и циклы превращаются в классические\n\\if(...){ ... } \\elif(...) { ... } \\else { ... }; или\n\\while( ... ){ ... }; Конструкция else у операторов цикла Теперь оператор цикла while поддерживает конструкцию else, которая выполняется если условие входа в цикл не было выполнено. Это поведение отличается от аналогичных конструкций в языке Python, у которого секция else выполняется всегда, кроме прерывания цикла по break.\nВетка else у оператора цикла записывается так же как и ветка иначе в условном операторе, т. е.\n[ cond ] \u003c-\u003e { ... }, [_] --\u003e { ... }; Или тоже самое, но с использованием макросов:\n\\while(cond) { ... } \\else { ... }; Пространства имен В синтаксис NewLang добавлены пространства имен, в стиле очень похожим на С++. Имена разделяются двойным двоеточием, а для определение пространства имен, его нужно указать перед открывающейся фигурной скобкой.\nns { name { var := 0; # Имя переменной будет ns::name::var ::var := 1; # Переменная из глобального пространства имен } } Программные модули Реализована концепция программных модулей - которая повторяет концепцию иерархического расположения файлов в структуре каталогов файловой системы, как в языках Python и Java.\nИмя модуля начинается на префикс @, а структура каталогов указывается через точку. Причем концепции программных модулей и пространства имен объединены, и полное имя переменой из предыдущего абзаца будет @root.dir.module::ns::name::var, где root и dir это каталоги в файловой системе, а module — имя файла.\nОбъектно ориентированное программирование Реализована часть концепции ООП и добавлена поддержка определения классов и их наследование, которая сейчас выглядит следующим образом:\n:NewClass := :Class() { # Новый тип (класс) field := 1; method() := {}; }; obj := :NewClass(); # Экземпляр класса Неожиданно для самого себя понял, что имея полный набор вариантов проверок при создании объектов (::= - создать новый объект, := - создать новый или присвоить значение существующему, = - только присвоить значение, а если объект не существует будет ошибка), концепция переопределения наследуемых функций не требует вообще никаких ключевых слов:\n:NewClass2 := :NewClass() { # Новый класс на базе существующего field ::= 2; # Будет ошибка, т. к. поле field уже есть в базовом классе method() = {}; # Аналог override, т.к. method должен существовать в базовом классе }; Прерывания, возврат и обработка ошибок Изменена, а точнее полностью переделана идеология возвратов из функций и обработки ошибок. Теперь она чем-то похожа на подход, примененный в Ruby. Любая последовательность команд заключенные в фигурные скобки (в том числе тело функции), рассматривается как блок кода у которого нет специального оператора аналога return, который возвращает какое либо значение. Просто любой блок кода всегда возвращает последнее вычисленное значение (это чем то похоже на оператор «запятая» в языках C/C++).\nДля того, чтобы прервать выполнение кода используются две разные команды - прерывания, которые условно можно назвать положительным и отрицательным результатом. Что примерно соответствует семантике их записи. “Отрицательное” прерывание записывается в виде двух минусов, а “положительное” прерывание в виде двух плюсов, т.е. -- или ++.\nПо умолчанию данные операции возвращают пустое значение. Чтобы прерывание вернуло результат, возвращаемые данные нужно записывать между парой соответствующих символов, т.е. -- 100 --, что является близким аналогом оператора return 100; в других языках программирования, а ++«Строка»++ - аналогом return «Строка»;.\nХотя более точным аналогом этих операторов будет все таки не return, а throw, т.к. эти команды не только прерывают выполнение последовательности команд в блоке, но их еще можно «ловить». Для этого используется блок кода с соответствующей семантикой, {+ … +} - блок кода, который перехватывает положительные прерывания и {- … -} - блок кода, который перехватывает прерывания, созданные операторами –.\nПодобная концепция (в явном виде не разделять возвраты из функций и обработку исключений), хоть и выглядит немного необычной, но позволяет реализовывать несколько очень полезных финтов, которые сложно реализуемые в обычных языках программирования.\nНапример, возврат из нескольких вложенных функций без необходимости обрабатывать результат возврата каждой из них. В этом примере функция Test перехватывает “положительные” прерывания из вложенных функций:\nTest0(arg) := { \\if($arg==0) \\return(\"DONE - 0\"); «FAIL» }; Test1(arg) := { \\if($arg==1) \\return(\"DONE - 1\"); Test0($arg); }; Test(arg) := {+ \\if($arg \u003e= 0) Test1($arg); $arg; +}; Test(0); # Вернет «DONE — 0» возврат из вложенной функции Test0 Test(1); # Вернет «DONE — 1» возврат из вложенной функции Test1 Test(2); # Вернет «FAIL» возврат из вложенной функции Test0 Test(-2); # Вернет -2 — возврат из функции Test Есть еще блок {* … *}, который перехватывает оба типа прерываний. Такой блок кода поддерживает типизацию возвращаемого значения, что позволяет в явном виде указывать типы данных, которые нужно перехватывать. Например, {* ... *} :Type1 — будет перехвачено прерывание вида ++ :Type1 ++ или --:Type1--, что позволяет очень гибко формировать логику работы программы.\nБлоки кода с перехватом исключений также поддерживают оператор иначе (\\else) который, по аналогии с оператором \\else в циклах, выполняется только тогда, если прерывания не произошло.\nМожно указать сразу несколько типов, которые нужно перехватывать:\n{* .... *} \u003c:Type1, :Type2, :Type3\u003e; Бинарная сборка под Windws: В текущем релизе версия clang повышена 15, а вызовы нативных функций опять реализованы с помощью libffi, что в итоге позволило собрать бинарную сборку не только под Linux, но и под Windows. И теперь чтобы поиграться с REPL read-eval-print loop можно скачать уже готовый бинарник.\nПодробная информация о языке: Синтаксис NewLang Подробное описание типов данных Операторы и управляющие конструкции Вся документация по NewLang на одной странице Обратная связь Если у вас появятся предложения по развитию нового или улучшению уже существующего функционала NewLang, пишите.\nПримеры кода #!../output/nlc --eval # Определение функции hello hello(str) := { # Импорт стандартной C функции printf := :Pointer('printf(format:FmtChar, ...):Int32'); # Вызов C функции с проверкой типов аргументов по строке формата printf('%s', $str); # Возврат значения из функции hello $str; }; hello('Привет, мир!'); # Вызвать функцию\u003c/code\u003e Вывод (первая строка выводится с помощью printf, а вторая — возвращаемое значение функции hello):\nПривет, мир! Привет, мир! Пример скрипта для вычисления факториала 1000\n#!../output/nlc --eval fact := 1\\1; # Рациональное число без ограничения точности mult := 1000..1..-1?; # Сделать из диапазона итератор для множителей от 1000 до 2 [mult ?!] \u003c-\u003e { # Цикл, пока не закончатся данные итератора # Получить текущий множитель и перейти на следующий элемент итератора fact *= mult !; }; fact # Вывести итоговый результат Вывод:\n402387260077093773543702433923003985719374864210714632543799910429938512398629 020592044208486969404800479988610197196058631666872994808558901323829669944590 997424504087073759918823627727188732519779505950995276120874975462497043601418 278094646496291056393887437886487337119181045825783647849977012476632889835955 735432513185323958463075557409114262417474349347553428646576611667797396668820 291207379143853719588249808126867838374559731746136085379534524221586593201928 090878297308431392844403281231558611036976801357304216168747609675871348312025 478589320767169132448426236131412508780208000261683151027341827977704784635868 170164365024153691398281264810213092761244896359928705114964975419909342221566 832572080821333186116811553615836546984046708975602900950537616475847728421889 679646244945160765353408198901385442487984959953319101723355556602139450399736 280750137837615307127761926849034352625200015888535147331611702103968175921510 907788019393178114194545257223865541461062892187960223838971476088506276862967 146674697562911234082439208160153780889893964518263243671616762179168909779911 903754031274622289988005195444414282012187361745992642956581746628302955570299 024324153181617210465832036786906117260158783520751516284225540265170483304226 143974286933061690897968482590125458327168226458066526769958652682272807075781 391858178889652208164348344825993266043367660176999612831860788386150279465955 131156552036093988180612138558600301435694527224206344631797460594682573103790 084024432438465657245014402821885252470935190620929023136493273497565513958720 559654228749774011413346962715422845862377387538230483865688976461927383814900 140767310446640259899490222221765904339901886018566526485061799702356193897017 860040811889729918311021171229845901641921068884387121855646124960798722908519 296819372388642614839657382291123125024186649353143970137428531926649875337218 940694281434118520158014123344828015051399694290153483077644569099073152433278 288269864602789864321139083506217095002597389863554277196742822248757586765752 344220207573630569498825087968928162753848863396909959826280956121450994871701 244516461260379029309120889086942028510640182154399457156805941872748998094254 742173582401063677404595741785160829230135358081840096996372524230560855903700 624271243416909004153690105933983835777939410970027753472000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000\\1 Как посмотреть? Бинарная сборка и тесты под Windows Бинарная сборка и тесты под Ubuntu Для запуска бинарных сборок потребуются разделяемые библиотеки libLLVM-15 и libtorch (архив с библиотеками для Windows), (архив с библиотеками для Ubuntu). Так же все можно собрать напрямую из исходников по инструкции в репозитории ","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/ru/blog/release-v0.3/","tags":"","title":"Релиз языка программрования NewLang 0.3"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nNewLang - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения.\nОсновной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка).\nNewLang находится в процессе активного развития и это второй публичный релиз в котором добавлены существенные новые возможности и произошли некоторые изменения по сравнению с предыдущей версией.\nОсобенности языка: Возможность работы как в режиме интерпретатора, так и компилятора*. Динамическая и статическая типизация с возможностью указания типов в явном виде. Статическая типизация является условно строгой (автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных, например, целое число может быть автоматически преобразовано в вещественное или рациональное, но не наоборот). Автоматическое управление памятью. ООП в виде явного наследования классов и «утиная» типизация. На уровне синтаксиса поддержка нескольких типов функций (обычные и чистые функции без побочных эффектов). Необязательные и именованные параметры функций. Возможны вставки кода на языке реализации (С/С++)*. Простая интеграция с уже существующими программными библиотеками (в том числе импорт нативных переменных и функций из С/С++). Имеется REPL read-eval-print loop — «цикл: чтение — вычисление — вывод». Новые глобальные фичи: Добавлены макросы. Теперь можно делать собственные языковые диалекты и использовать более привычную запись алгоритмических конструкций с использование ключевых слов. Например, цикл [ cond ] \u003c-\u003e { тело цикла }; можно записать в более привычный нотации\n\\while (cond) { тело цикла }; Добавлены итераторы для перебора элементов словарей или для запросов к другим контейнерам (например, к базам данных). На уровне базового синтаксиса поддерживается фильтрация данный, включая функциональный аналог LINQ за счет применения функций обратного вызова в качестве условия фильтра. Добавлен новый тип данных — рациональные числа с неограниченной точностью. Они записываются в виде обыкновенной дроби, у которой разделитель бекслеш, например единицу можно записать 1\\1, а число 0.5 как 1\\2. Реализован оператор распаковки словаря … (многоточие), который можно использовать чтобы передать несколько аргументов при вызове функции или для присвоения значения сразу нескольким переменным. Теперь оператор присвоения поддерживает установку значений сразу нескольким переменным. С правой стороны от оператора присвоения может находится одно или несколько значений или оператор распаковки словаря. Причем словарь может быть указан и с левой стороны от оператора присвоения и таким образом можно записать самый простой способ перебора всех его элементов, когда в цикле первый элемент словаря сохраняется в переменную item, а из самого словаря удаляется: [ dict ] \u003c-\u003e { item, dict := ... dict; }; Изменения в синтаксисе: Изменена запись циклов. Вместо двух разных типов с предусловием и постусловие, теперь используется единая форма записи, а тип цикла определяется взаимным расположением условия и его тела. Изменены названия арифметических и некоторых других типов данных на более логичные. В именах арифметических типов теперь указан их размер (Int8, Int16 … Float32, Float64 и т.д.). Многострочные комментарии стали вложенными Подробная информация о языке: Основные правила синтаксиса: Встроенные типы данных: Операторы и управляющие конструкции: Примеры кода ``` #!../output/nlc --eval Определение функции hello hello(str) := {\n# Импорт стандартной C функции printf := :Pointer('printf(format:FmtChar, ...):Int32'); # Вызов C функции с проверкой типов аргументов по строке формата printf('%s', $str); # Возврат значения из функции hello $str; };\nhello(‘Привет, мир!’); # Вызвать функцию\nВывод (первая строка выводится с помощью printf, а вторая - возвращаемое значение функции hello): Привет, мир! Привет, мир! \u003cspoiler title=\"Пример скрипта для вычисления факториала 1000\"\u003e #!../output/nlc –eval\n@fact := 1\\1; # Рациональное число без ограничения точности @mult := 1000..1..-1?; # Сделать из диапазона итератор для множителей от 1000 до 2 [mult ?!] \u003c-\u003e { # Цикл, пока не закончатся данные итератора # Получить текущий множитель и перейти на следующий элемент итератора fact *= mult !; }; fact # Вывести итоговый результат\nВывод: 402387260077093773543702433923003985719374864210714632543799910429938512398629 020592044208486969404800479988610197196058631666872994808558901323829669944590 997424504087073759918823627727188732519779505950995276120874975462497043601418 278094646496291056393887437886487337119181045825783647849977012476632889835955 735432513185323958463075557409114262417474349347553428646576611667797396668820 291207379143853719588249808126867838374559731746136085379534524221586593201928 090878297308431392844403281231558611036976801357304216168747609675871348312025 478589320767169132448426236131412508780208000261683151027341827977704784635868 170164365024153691398281264810213092761244896359928705114964975419909342221566 832572080821333186116811553615836546984046708975602900950537616475847728421889 679646244945160765353408198901385442487984959953319101723355556602139450399736 280750137837615307127761926849034352625200015888535147331611702103968175921510 907788019393178114194545257223865541461062892187960223838971476088506276862967 146674697562911234082439208160153780889893964518263243671616762179168909779911 903754031274622289988005195444414282012187361745992642956581746628302955570299 024324153181617210465832036786906117260158783520751516284225540265170483304226 143974286933061690897968482590125458327168226458066526769958652682272807075781 391858178889652208164348344825993266043367660176999612831860788386150279465955 131156552036093988180612138558600301435694527224206344631797460594682573103790 084024432438465657245014402821885252470935190620929023136493273497565513958720 559654228749774011413346962715422845862377387538230483865688976461927383814900 140767310446640259899490222221765904339901886018566526485061799702356193897017 860040811889729918311021171229845901641921068884387121855646124960798722908519 296819372388642614839657382291123125024186649353143970137428531926649875337218 940694281434118520158014123344828015051399694290153483077644569099073152433278 288269864602789864321139083506217095002597389863554277196742822248757586765752 344220207573630569498825087968928162753848863396909959826280956121450994871701 244516461260379029309120889086942028510640182154399457156805941872748998094254 742173582401063677404595741785160829230135358081840096996372524230560855903700 624271243416909004153690105933983835777939410970027753472000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000\\1\n## Как посмотреть? - [Загрузить собранный REPL и тесты (пока только под Ubuntu)](https://github.com/rsashka/newlang/releases/download/v0.2.0/nlc_bin.tar.xz) - Для запуска бинарных файлов потребуются разделяемые библиотеки libLLVM-13 и libtorch: [архив только с нужными библиотеками](https://github.com/rsashka/newlang/releases/download/v0.2.0/nlc_so.tar.xz). - Так же все можно собрать напрямую из исходников по инструкции в [репозитории](https://github.com/rsashka/newlang) ","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/ru/blog/release-v0.2/","tags":"","title":"Релиз языка программрования NewLang 0.2"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nNewLang - это язык программирования высокого уровня, в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения.\nОсновной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка).\nНовое по сравнению с прошлым выпуском:\nРеализованы все основные алгоритмические конструкции: проверка условий, различные варианты циклов, сравнение по образцу, прерывание последовательности команд и возврат данных, обработка ошибок и т.д. Переработан основной синтаксис для отдельных языковых конструкций. Реализованы большинство операций с переменными, включая операторы раскрытие списков и тензоров. Серьезно переработана система встроенных типов, реализованы функции для их преобразования и для определения данных (последнее можно назвать data comprehensions). Добавлены новые тесты и пр. Зачем нужен NewLang? У всех современных языков программирования происходит постоянное развитие (читай усложнение) синтаксиса по мере выхода новых версий. Это является своего рода, платой за появление новых возможностей и воспринимается пользователями как естественное явление.\nНо одновременно является и серьезной проблемой, т.к. с выходом новых версий добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки и трудоемкости поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.\nУ NewLang сложность языковых конструкций естественно ограничена за счет разделения синтаксиса языка на две части, что упрощает его изучение и использование.\nОсновной синтаксис — для написания программ в объектно-ориентированном (императивном) и декларативном стилях, который основан не на зарезервированных ключевых словах, а на строгих грамматических правилах и Расширенный синтаксис — когда основного синтаксиса становится недостаточно, или требуется использовать языковую конструкцию языка реализации.\nЕще одно неудобство современных мейнстримовых языков, большинство из них были созданы до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек, а не встроены в основной синтаксис языка и систему базовых типов.\nУ NewLang тензорные вычисления доступны «из коробки» (используется библиотека libtorch), а обычные числа являются скалярами (тензорами нулевой размерности).\nСинтаксис NewLang При разработке синтаксиса я старался придерживаться уже сложившихся в IT индустрии правил, чтобы не генерировать множественных смыслов, которые будут зависеть от контекста.\nОсновы\nОператоры разделяются точкой с запятой «;». Отступы и переводы строк игнорируются (очень хотелось иметь возможность автоматического форматирование кода). Многострочные комментарии в исходном коде соответствуют стилю С/С++ и должны располагаться между символами /* и */. Вложенность многострочных комментариев не поддерживается. Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash. Последовательность команд, которая должна выполняться как единое целое, заключается в фигурные скобки «{}». Программные вставки расширенного синтаксиса на языке реализации заключается в фигурные скобки со знаком процента %{ /* тут может быть любой код на C/C++*/ %}, как в лексерах lex и flex. Создания объектов и присвоения новых значений Для создания объектов и присвоения им новых значений в NewLang используется сразу три разных оператора:\n::= используется только для создания новых объектов, а если объект с таким именем уже существует, то генерируется ошибка. := используется для тех же целей, но если объект с таким именем уже существует, то ошибки не происходит, а новое значение присваивается уже существующему объекту. = применяется только для присвоения значения уже существующим объектам, и если объект с указанным именем отсутствует, то тоже происходит ошибка выполнения. Использование трех разных операторов для создания/изменения объектов позволяет более гибко контролировать подобные операции и выявлять логические ошибки в коде на более раннем этапе.\nvar ::= 1.0; # Создать новую переменную var без указания типа var = 100; # Присвоить новое значение уже существующей переменной printf := @import('printf(format:Format, ...):Int'); /* Создать новый или переопределить объект printf, который будет результатом выполнения глобальной функции @import */ Идентификаторы объектов и модификаторы В качестве идентификаторов можно использовать буквы, цифры и знаки подчеркивания в любых комбинациях, при условии, что первый символ идентификатора не является цифрой.\nВ NewLang существует возможность указания области видимости и времени жизни объекта с помощью модификатора — специального символа перед именем переменной. Это может показаться немного похожим на венгерскую нотацию, но в отличие от нее, модификатор не имеет отношения к типу объекта и не является частью имени идентификатора. К тому же в качестве модификаторов используется строго определённые символы, назначение которых определено заранее.\n$ - в начале имени обозначает локальную переменную, время жизни которой ограничено текущей областью видимости и при её завершении локальная переменная уничтожается. @ - обозначает глобальную переменную, а сам объект сохраняет свое состояние даже после выхода из текущей области видимости. : - двоеточие вначале имени используется в качестве модификатора для указания типа. Семантика обращения к аргументам функций очень похоже на работу с аргументами в bash скриптах, где $1 или $arg — порядковый номер или имя аргумента (происходит обращение к локальным переменным в текущей области видимости).\nИспользование модификаторов является обязательным только в двух случаях: При создании нового типа данных, так как типы всегда создаются в глобальной области видимости, а их символьные имена должны быть уникальными. При обращении к объектам NewLang внутри программных вставок кода на языке реализации, так как они используется как маркеры при поиске идентификаторов NewLang в коде С/С++. В остальных случаях, для обращения к переменным указывать их модификаторы необязательно. И если при обращении к объекту модификатор не указан, то сперва ищется локальная переменная, а потом глобальная с таким же именем. Причем, локальная переменная будет перекрывать глобальную.\nТак же следует иметь в виду, что компилятор может генерировать код для прямого обращения к локальным объектам уже на этапе компиляции, тогда как для обращения к глобальным объектам, или если модификатор области видимости отсутствует, компилятор вынужден каждый раз встраивать runtime вызов функции поиска объекта в глобальной таблице символов.\nСистема типов Так как система типов языка динамическая, то явное указание типа не влияет на размер переменной и является только своего рода логическим ограничением на возможность присвоения переменной значения другого типа.\nИнформация о типах используется при проверке их совместимости, когда существующему объекту присваивается значение другого типа. Такая операция возможна только когда типы совместимы между собой и допускают автоматическое приведение. Это справедливо как во время парсинга/компиляции исходного теста, так и во время выполнения в режимах интерпретатора и/или скомпилированного файла.\nПростые типы Арифметические значения Арифметические типы данных являются тензорами — массивами чисел одного типа с произвольным количеством измерений и одинаковым размером столбцов в каждом. Единичное число тоже тензор нулевого размера.\nПоддерживаются только знаковые целые числа, т.к. в беззнаковых числах особая нужда отсутствует, а проблем с ними можно найти очень много на ровном месте.\nПроблемы беззнаковых чисел (из интернета):\nВо-первых, вычитание двух беззнаковых чисел, например 3 и 5. 3 минус 5 равно 4294967294, т.к. -2 не может быть представлено как беззнаковое число. Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных значений со знаком и без знака. С++ может свободно преобразовывать числа со знаком и без знака, но не проверяет диапазон, чтобы убедиться, что вы не переполняете свой тип данных. В C++ всё же есть несколько случаев, когда можно (или необходимо) использовать беззнаковые числа. Во-первых, числа без знака предпочтительнее при работе с битами. Во-вторых, использование беззнаковых чисел связанных с индексацией массивов.\nНо это не мой случай, так как индекс может быть отрицательным и даже не числом, а диапазоном или многоточием.\nЗ.Ы. И даже зная об этом, все равно умудрился недавно словить баг с отрицательными индексами у словарей!\nИмена встроенных арифметических типов говорят сами за себя: Char, Short, Int, Long, Float, Double, ComplexFloat, ComplexDouble. Отдельным типом идет логический тип Bool, который может принимать значения только 0 или 1 (false/true соответственно), и в зависимости от выполняемой операции может быть отнесен к целочисленным типам, так и не входить в их состав (данный подход интерпретации логического типа данных был взят из библиотеки Torch).\n// Treat bool as a distinct \"category,\" to be consistent with type promotion // rules (e.g. `bool_tensor + 5 -\u003e int64_tensor`). If `5` was in the same // category as `bool_tensor`, we would not promote. Differing categories // implies `bool_tensor += 5` is disallowed. // // NB: numpy distinguishes \"unsigned\" as a category to get the desired // `bool_tensor + 5 -\u003e int64_tensor` behavior. We don't, because: // * We don't want the performance hit of checking the runtime sign of Scalars. // * `uint8_tensor + 5 -\u003e int64_tensor` would be undesirable. В будущем планируется добавить классы чисел для длинной арифметики и дробей, для чего зарезервированы названия типов BigNum, Currency и Fraction.\nДоступ к элементам тензора происходит по целочисленному индексу, который начинается с 0. Для многомерного тензора, индексы элемента перечисляются в квадратных скобках через запятую. Поддерживается доступ к элементам через отрицательный индекс, который обрабатывается точно так же, как в Python (-1 последний элемент, -2 предпоследний и т.д.).\nЛитерал тензор в тексте программы записывается в квадратных скобках с обязательной завершающей запятой, т.е. [1, 2,] — это литерал одномерный тензор из двух чисел. После закрывающей скобки тип тензора может быть указан в явном виде. Если тип не указан, то он выводится автоматически на основании указанных данных и выбирается минимально возможный байтовый размер, который позволяет сохранить все значения без потери точности.\nПримеры:\n$var_char := 123; # Тип Char выводится автоматически $var_short := 1000; # Тип Short выводится автоматически $var_bool := [0, 1, 0, 1,]; # Тензор из 4 элементов. Тип Bool выводится автоматически $tensor[10,10]:Int := 1; # Тензор Int размером 2x2 инициализированный 1 $scalar := $tensor[5,5]; # Присвоить скаляру значение указанного элемента тензора Строки Поддерживаются два типа строк, StrWide — символьные (широкие) и StrChar — байтовые. Различия между ними заключается в типе единичного элемента. У символьных строк единичным элементом является широкий символ wchar_t, а у байтовой строки единичным элементом является один байт (точнее char, т.е. байт со знаком). Символьные строки литералы в исходном тексте записывается в «двойных кавычках», а байтовые строки в ‘одинарных кавычках’.\nКоличество элементов символьной строки возвращается в широких символах, а размер байтовой строки в байтах, поэтому и обращение к элементу строки по индексу происходит соответственно либо к символу, либо к байту.\nВажный момент. К любой переменной можно обратиться так же, как к функции (записав после её имени круглые скобки). Результатом этой операции будет создание копии/клона объекта. Причем некоторые типы (словари, классы и символьные строки) можно использовать в качестве шаблона при создании копии объекта с модифицированными свойствами, если новые и/или изменяемые значения указать в скобках, как аргументы при вызовах функций. Так, если при создании копии в скобках указать набор новых данных, то результирующая копия будет содержать уже измененные данные.\nНапример:\n$template := \"${name} $1\"; # Обычная строка $result := $template(\"шаблон\", name = \"Строка\"); # result = \"Строка шаблон\" Системные :Pointer - указатель на системную область памяти Так как любой программе приходится взаимодействовать с внешним миром, то по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип Pointer. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. Но можно вывести его значение, например для отладки.\n:Plain - указатель на представление данных в бинарном виде Для взаимодействия с внешними библиотеками требуется еще и обмен данными. И для этих целей служит тип данных Plain - который также является указателем, но на двоичное представление данных в единой области памяти. Конечно, если их можно представить в виде единого фрагмента.\nСоставные типы данных: Словарь Словарь (:Dictionary) — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии (он похож и на tuple и на структуру одновременно). Словари от тензоров отличаются тем, что являются только одномерными массивами, но каждый элемент может содержать произвольное количество элементов любого типа, в том числе и другие словари.\nДоступ к элементам словарей происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. Индекс также начинается с 0 и как у тензоров и тоже может быть отрицательным.\nЛитерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, т. е. (,) — пустой словарь, (1, 2= «2», name=3,).\nПеречисление, структура и объединение :Enum, :Struct и :Union — это такие же словари, только на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера.\nКлассы Класс (реализован частично) — тип данных, с помощью которого реализуется один из принципов ООП — наследование. При создании экземпляра класса создается новая переменная, у которой сохраняется информацию о своем родителе и которая наследует от него свойства и методы. Тип данных :Class аналогичен словарю, но все свойства обязаны иметь имена (хотя доступ к свойствам класса по индексу так же возможен).\nФункции Синтаксис NewLang поддерживать несколько типов функций (а в будущем и методов классов): обычные функции, чистые функции и простые чистые функции.\nДля всех типов функций поддерживаются аргументы по умолчанию. При создании функции, её аргументы указываются как в Python, т.е. вначале идут обязательные аргументы, потом аргументы со значениями по умолчанию, где имя аргумента отделяется от его значения по умолчанию знаком равно =. Если функция допускает обработку произвольного количества аргументов, то последним в списке параметров указывается многоточие … (три точки подряд) .\nОбычная функция Обычная функция — такие функции являются именно обычными функциями в понимании С/С++. Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д.\nВнутри обычной функции можно обращаться к локальным и глобальным объектам, и они могут содержаться вставки на языке реализации*, например, для вызова функций из внешних библиотек.\nВставки на языке реализации оформляются в виде %{ %} и могут содержать любой текст на С/С++, а прямо из него можно обращаться к локальным и глобальным объектам NewLang так же, как и в обычном синтаксисе, указывая первым символом имени соответствующий модификатор ($ для локальных объектов и @ для глобальных).\nТехнически, такая программная вставка просто переносится трансплайтером непосредственно в исходный текст генерируемого файла, а все идентификаторы NewLang специальным образом декорируются (добавляются специальные маркеры для их идентификации), после этого исходный текст подается на вход обычному компилятору С++. Для локальных объектов трансплайтер может генерировать код для прямого доступа к объекту на этапе компиляции, а для работы с глобальными объектами вынужден использовать runtime вызовы функции поиска в таблице символов.\n*) - Программные вставки на языке реализации обрабатываются только во время компиляции\nНапример:\nprint(str) := { %{ printf(\"%s\", static_cast\u003cconst char *\u003e($str)); /* Прямой вызов С функции */ %} }; Чистые функции Чистая функция — это тоже обычная функция, только в том смысле, какой в него вкладывает функциональное программирование. Создания чистой функции происходит с помощью оператора :-, а сам оператор заимствован из языка Пролог. У чистой функции отсутствует доступ к контексту и глобальным переменным, поэтому она может обрабатывать только те данные, которые были ей переданы в качестве аргументов.\nПрограммные вставки на языке реализации внутри чистых функций не запрещены и могут использоваться, например, для отладки. Но делается это на страх и риск разработчика. Именно он отвечает за их «чистоту», например при вызове функций из внешних библиотек.\nSum(arg1, arg2) :- {$arg1+$arg2;}; # Вернуть сумму аргументов Простые чистые функции Простые чистые функции — отдельный класс чистых функций, которые предназначены только для вычисления логического результата (т.е. они являются предикатами) и их отличает упрощенная формой записи. Тело простой чистой функции состоит из последовательности операторов, которые разделяются запятыми и заканчиваются, как и любое выражение, точкой с запятой. Все операторы простой чистой функции всегда приводятся к булевому значению, а итоговый результат функции вычисляется по одной из возможных логических операций: И, ИЛИ и исключающее ИЛИ.\nНапример:\nfunc_and(arg1, arg2) :\u0026\u0026= arg1==3, arg2 \u003e 0; # Простая чистая функция Логическое И func_or(arg1, arg2) :||= arg1==3, arg2 \u003e 0; # Простая чистая функция Логическое ИЛИ func_xor(arg1, arg2) :^^= arg1==3, arg2 \u003e 0; # Простая чистая функция Исключающее ИЛИ Специальные типы данных: Пусто (:None) :None (пусто) — не содержит значения (точнее имеет одно значение None) и совместим с любым другим типом данных. Указывается в тексте программы как один подчерк «_». None имеют не инициализированные переменные и при попытке чтения из такой переменной возникает ошибка.\nТип переменной может быть явно указан или выведен автоматически из присваиваемого значения. Присвоить новое значение уже инициализированной переменной можно только для совместимого типа, так как неявное преобразование типов не допускаются.\n$var := _; # Создать не инициализированную переменную $var2 := var; # Ошибка!!! Нельзя прочитать неинициализированную переменную var $var = 1000; # У переменной будет тип Short (минимальный размер для хранения значения) $var = 0,5; # Ошибка!!! Short ← Float не совместимы $var = _; # Очистить значение переменной $var = 0,5; # Теперь можно, т. к. None совместим с любым типом Диапазон (:Range) Диапазон — специальный тип данных, являющейся приблизительным аналогом типа «генератор» в Python. К диапазону можно обращаться как к итератору и он будет поочередно выдавать элементы в указанном интервале с заданным шагом. Диапазон в тексте программы указывается как два или три элемента через две точки, например 1..5 — диапазон от единицы до пяти с шагом по умолчанию 1. В качестве параметров диапазона можно указывать не только литералы, но и имена переменных. Например, 0,1..$stop..0,1 — диапазон от 0,1 до значения, указанного в переменной $stop с шагом 0,1.\nДиапазон для целых чисел можно использовать в качестве индекса у тензоров (точнее, у любых объектов, которые допускают доступ к своим элементам по индексу, т.е. тензоры, словари и текстовые строки). Фактический, это поведение аналогично slice в языке Python и array[1:5] в Python означает тоже самое, что и array[1..5] в NewLang.\nВ качестве индекса у тензоров еще можно указать произвольное количество измерений с помощью многоточия, т.е.\n$tensor[…, 0] = 0; # Обнулить все первые элементы в каждом измерении. Преобразование типов Явное приведение типов Несмотря на динамическую типизацию языка, если тип переменной указан явно, то автоматическое приведение типов не выполняется, и чтобы присвоить переменой значение не совместимого типа, требуется явное преобразование.\nТак как символьные названия типов относятся к деталям реализации, то явное преобразование в конкретный тип данных производится с помощью вызова функции с именем типа, т.е. :Bool(), :StrWide(), :Long() и т.д.\nДля преобразования любого типа данных в строку ещё можно использовать оператор конкатенации строк, которой преобразует любой тип данных в строковое представление. Но, так как строковых типов два (байтовые и широкие строки), то тип строки определяется первым аргументом в операторе конкатенации/сцепления ++. Также преобразовать любое значение в строковое можно с помощью строки-шаблона.\n\"\" ++ 123; # \"123\" - Строка широких символов '' ++ 123; # '123' - Байтовая строка val := 12345; # Число \"$1\"(val); # Будет строка \"12345\" Так как тензоры могут иметь больше одного значения, то и в качестве аргументов могут принимать их произвольное количество, а итоговым результатом будет тензор, в котором все переданные данные преобразованы к требуемому типу автоматически.\nПримеры:\n\u003e tstr := :Tensor(\"Тест\"); # Создать тензор из строки широких символов [1058, 1077, 1089, 1090,]:Int \u003e t2 := :Tensor[2,2](\"Тест\"); # Тоже самое, но тензор указанной размерности [ [1058, 1077,], [1089, 1090,], ]:Int \u003e :StrWide(tstr) # Создать символьную строку из тензора Тест \u003e :Double(t2) # Изменить тип данных тезора без изменения размерности [ [1058, 1077,], [1089, 1090,], ]:Double \u003e t3 := :Char[4]( t2 ) # Изменить размерность тензора и его тип (в данном случае с частичной потерей данных) [34, 53, 65, 66,]:Char \u003e:Tensor( (1,2,3,) ); # Тензор из словаря [1, 2, 3,]:Char \u003e:Tensor( 'first second' ) # Байтовая строка в тензор [102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char \u003e:Tensor( (first='first', space=32, second='second',) ) # Получаем тензор из словаря с такими же данными [102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char \u003e:Double[10,2]( 0, ...) # Тензор заданного формата с нулями, где многоточие повторяет последние указанные данные до получения тензора требуемого размера [ [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], ]:Double \u003e:Int[3,2]( ... rand() ...) # Тензор со случайными данными, где между многоточиями указана функция, которую следует вызывать каждый раз при получении нового элемента тензора # Пришлось придумывать новую конструкцию, т.к. многоточие перед именем, это оператор раскрытия словаря, а многоточие после имени, это повторение последнего значения до конца заданной размерности. [ [1804289383, 846930886,], [1681692777, 1714636915,], [1957747793, 424238335,], ]:Int \u003e:Int[5,2]( 0..10 ); # Создание тензора из диапазона [ [0, 1,], [2, 3,], [4, 5,], [6, 7,], [8, 9,], ]:Int \u003e:Tensor( 0..0.99..0.1 ); # Или даже так [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,]:Double Операторы и управляющие конструкции Операторы: Все операторы имеют парный аналог с присвоением значения:\n+ и += - сложение арифметических типов данных; - и -= - вычитание арифметических типов данных; / и /= - деление (результат число с плавающей точкой); // и //= - целочисленное деление с округлением к меньшему числу (как в Python); * и *= - умножение; ** и **= - возведение в степень (он же используется и для повторения текстовых строк); ++ и ++= - конкатенация строк с автоматическим приведением аргументов к стоковому типу (символ инкремента специально используется вместо одиночного плюса для того, чтобы в явном виде разделить конкатенацию строк и операторы арифметического сложения). Операторы сравнения: \u003c, \u003e, \u003c=, \u003e= - классические для сравнения скаляров == и != - операторы сравнения с автоматическим приведением совместимых типов для любых объектов === и !== - оператор точного сравнения для любых объектов (автоматического приведения типов не выполняется) Проверки типа (имени класса объекта): Для оператора проверки имени класса объекта используется символ тильда ~. Он немного похож на оператор instanceof в Java. Левым операндом должен быть проверяемый объект, а правым — проверяемый тип, который можно указать строкой литералом, переменной строкового типа или именем проверяемого класса непосредственно. Результатом операции будет истина, если правый операнд содержит название класса проверяемого объекта или он присутствует в иерархии наследования.\nname := \"class\"; # Строковая переменная с именем класса var ~ name; var ~ :class; # Имя типа var ~ \"class\"; # Строка литерал с именем типа Утиная типизация Оператор утиной типизации, два символа тильны ~~ — приблизительный аналог функции isinstance() в Python, который для простых типов сравнивает непосредственную совместимость типа левого операнда по отношению к правому. А для словарей и классов в левом операнде проверяется наличие всех имен полей, присутствующих у правого операнда, т.е.:\n(field1=«value», field2=2,) ~~ (); # Истина (т. е. левый операнд словарь) (field1=«value», field2=2,) ~~ (field1=_); # Тоже истина (т. к. поле field1 присутствует у левого операнда) (field1=«value», field2=2,) ~~ (not_found=_); # Ложь, т.к. поле not_found у левого операнда отсутствует Строгая утиная типизация ~~~ — для простых типов сравнивается идентичности типов без учета совместимости, а для составных типов происходит сравнение всех свойств с помощью оператора строгого равенства. Для данной операции, пустой тип совместим только с другим пустим типом.\nУправляющие конструкции К управляющим конструкциям языка NewLang относятся условный оператор, два вида циклов, оператор оценки выражения, оператор прерывания последовательности выполнения команд и перехват прерывания. Операторы проверки условий всегда указываются в квадратных скобках, а последовательность команд для выполнения - в фигурных.\nУсловный оператор В качестве оператора проверки условия используется синтаксическая конструкция, соответствующая по смыслу термину «следует», т.е. тире и угловая скобка -\u003e или с двумя тире для большей наглядности –\u003e. Такая запись условного оператора очень похожа на математическую и легко объединяется в последовательности для проверки множественных условий вида «else if».\nВ общем случае условный оператор имеет вид: [ условие ] -\u003e действие; или [ условие ] -\u003e {действие}; или [ условие1 || условие2 ] --\u003e {действие}, [_] --\u003e {действие иначе};\nДля наглядности записанный с отступами:\n[ условие1 ] -\u003e { действие1 }, [ условие2 ] -\u003e действие2, [ условие3 ] -\u003e действие3, [_] -\u003e {действие_иначе}; Оценка выражения Синтаксическая конструкция с помощью которой реализуется аналог оператора switch выглядит следующим образом:\n[ $var ] ==\u003e { [1] -\u003e { code }; # Выполнится проверка условия $var == 1 [1, 2] -\u003e { code }; # Выполнится проверка условия ($var == 1 || $var == 2) [_] -\u003e { code default }; # Ветка условия иначе }; Причем в качестве оператора для оценки могут быть использован любые имеющиеся операторы сравнения на равенство:\n==\u003e - проверка на равенство с приведением типов; ===\u003e - проверка на точное равенство; ~\u003e - проверка типа (имени класса); ~~\u003e - утиная типизация; ~~~\u003e - строгая утиная типизация. И если в качестве оператора сравнения использовать оператор утиной типизации, то оценка выражения превращается в классический Pattern Matching:\n$value := (f1=1, f2=\"2\",); [ $value ] ~~~\u003e { [ (f1=_, ), (f1=_, f2=0, ) ] -\u003e { code }; # Поле f2 отсутствует или число [(f1=_, f2=\"\",), (f1=_, f2='',)] -\u003e { code }; # Поле f2 строка [_] -\u003e { code default }; # Код по умолчанию }; Операторы циклов Для указания операторов циклов используются управляющие -» или –» (с двумя стрелками по направлению от проверки условия к телу цикла). И в зависимости от расположения условия и тела цикла, он может быть с предусловием (while) или постусловием (do while). Хотя пока эти синтаксические конструкции не “отлежались” и их можно считать временными из-за того, что их легко перепутать с условным оператором, и, возможно, имеет смысл заменить разные операторы цикла одной единственной конструкцией вида: \u003c–\u003e или «-», которая сильнее отличается от оператора следования.\nНо в настоящий момент циклы реализованы вот так:\n[условие while] -\u003e\u003e { тело цикла while }; { тело цикла do while } \u003c\u003c-- [условие do while]; Реализация цикла foreach на примере суммирования всех элементов словаря (или одномерного тензора):\nsumma := 0; dict := (1,2,3,4,5,); [ dict ] --\u003e\u003e { # Условие цикла, пока есть данные item, dict := ... dict; # Результат оператора раскрытия словаря - первый его элемент перемещается в item summa += item; # Вычисление суммы всех элементов словаря }; Операторы прерывания (возврата) В качестве оператора прерывания/возврата используется два символа минус –. Оператор позволяет прервать выполнение последовательности команд и/или вернуть данные из текущей функции/блока кода и является самым близким аналогом оператора return и throw одновременно. Для того чтобы вернуть данные, их необходимо указать между двумя операторами прерывания, т.е. --100--; # Вернуть указанное значение. Если возвращаемое значение не указано явно, то будет возвращено значение None.\nСледование (блок кода/лямбда функция) Алгоритмическая конструкция, которая отвечает последовательное выполнение нескольких команд/операторов и возвращающая результат выполнения последнего из них. Также, результатом выполнения может быть значение, которое возвращается с помощью оператора прерывания (возврата). Это очень похоже на классическую лямбда функцию, только она выполняется сразу во время определения, а в переменную сохраняется уже результат её выполнения.\nСледование без перехвата прерывания оформляется в виде последовательности обычных и фигурных скобок, т.е. (){ run code }; или тоже самое, но сохраняет результата выполнения в переменной: $result := (){ run(); code() };. Но если внутри такой функции будет выполнен оператор прерывания, то она никогда вернет управления и не сохранит возвращаемое значение в переменой $result!\nЧтобы перехватывать прерывания, в том числе и возвращаемые значения, необходимо использовать конструкция следования с перехватом прерываний, которая оформляется в виде последовательности обычных и двойных фигурных скобок, т.е. $error := (){{ run(); error();code() }};. Такая конструкция перехватывает все возвраты и прерывания, если они возникают во время выполнения последовательности команд. В этом случае любой результат будет сохранен в переменной $error как при нормальном завершении, так и в случае возникновения ошибки.\nДля более тонкой настройки перехвата прерываний следует использовать типизированную конструкцию, когда в явном виде указывается, какие типы прерываний следует перехватывать. $runtime := (){{ run(); error(); code() }}:ErrorRuntime;. Такая конструкция вернет результат только в случае успешного завершения (когда с помощью оператора прерывания возвращается не типизированное значение, например, --\"Строка\"--;), или при создании прерывания с указанием конкретного типа –:ErrorRuntime(“Описание ошибки”)–;. А вот при возникновении любого другого типизированного прерывания, значение перехвачено не будет и все отработает как самый первый вариант, т.е. без перехвата прерывания и без сохранения возвращаемого значения в переменную.\nСтратегия обработки ошибок Обработка ошибок состоит из комбинации двух элементов: оператора прерывания выполнения с указанием типа возвращаемого значения и алгоритмической конструкции следование с возможностью перехвата прерывания заданного типа.\nЭто немного отличается от классического варианта обработки исключений, который в обычных языках программирования обычно оформляется ключевыми словами try… catch… finally с различными вариациями. Ведь основная цель подобных синтаксических конструкций — выделить участок кода, где возможно возникновение ошибки, перехватить и обработать правильный тип данных (исключений), т.к. NewLang не делает различий между операторами возврата и генерации исключения.\nПодход к обработке исключений следующий: Программный код, который может привести к ошибке, заключается в двойные фигурные скобки, а результат выполнения такого блока кода присваивается переменной. После этого анализируется возвращенное значение, например, оператором сравнения по образцу:\n$result := (){{ # начало аналога блока try $value := call_or_exception1(); [условие1] -\u003e { -- :Error -- }; [условие2] -\u003e { -- $value -- }; $value := call_or_exception2(); }}; # конец аналога блока try [$result] ~\u003e { # Для сравнения по образцу использовать оператор проверки типа (имени класса) [:ErrorParser] -\u003e {Код обработки ошибок парсера}; [:ErrorRunTime] -\u003e {Код обработки ошибок времени выполнения}; [:Error] -\u003e { Код обработки остальных ошибок }; [_] -\u003e { Обработка нормальных данных $value без ошибок }; }; Сборка REPL из исходников (пока только под Linux) Подготовка репозитория Скачать исходники Скачать и развернуть архив libtorch в каталоге contrib (PyTorch Build: Stable (1.10.*) -\u003e Your OS: Linux -\u003e Package: LibTorch -\u003e Language: C++ / Java -\u003e Compute Platform: CPU -\u003e Download here (cxx11 ABI): libtorch-cxx11-abi-shared-with-deps-1.10.2+cpu.zip) Активировать и скачать исходники субмодулей (git submodule init \u0026\u0026 git submodule update) В каталоге contrib запустить файл build.sh для сборки библиотеки libffi В каталоге core запустить файл compile_syntax.sh для генерации файлов парсера и лексического анализатора. Также может потребоваться установка утилит flex и bison. Если что, у меня установлены flex 2.6.4 и bison (GNU Bison) 3.7.4 Собрать Юнит-тесты (newlang_test): в каталоге core выполнить команду make CONF=UnitTest* Интерпретатор (nlc): в каталоге core выполнить команду make CONF=Debug* *) - Сборка проекта выполняется обычной утилитой make, но сборочные файлы генерируются автоматически в давно устаревшей версии NetBeans 8.2, т.к. это единственная универсальная среда разработки с поддержкой Makefile “из коробки”, тогда как в текущей версии Apache NetBeans полноценная поддержка разработки на С/С++ вообще отсутствует. Начал постепенный переход на использование редактора VSCodium (аналога VSCode, в котором вычищена телеметрия от Microsoft) и генерацию скриптов сборки с помощью сmake, но этот процесс пока не завершен.\nПланы на будущее Текущая версия языка значительно обогатилась возможностями, но все еще является тестовой платформой для проверки декларируемых концепций и основного синтаксиса. Если говорить о планах, то в настоящий момент роадмап развития NewLang следующий:\nРеализовать макросы для более привычного использования языка (за счет использования DSL); Добавить в арифметические типы длинные числа и дроби; Сделать какую-нибудь логическую игру (крестики нолики, судоку или что-то похожее) с алгоритмическим выбором следующего хода и его вычислением с помощью машинного обучения; Написать еще больше разных примеров для оценки синтаксиса; Зафиксировать синтаксис с учетом полученного опыта и обратной связи; Восстановить работоспособность компилятора для генерации исполняемых файлов; Сделать очередную большую чистку кода; Переработать и задокументировать получившуюся семантику языка с учетом всех возможностей и выпустить первую полнофункциональную версию NewLang. ","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/ru/blog/release-v0.1/","tags":"","title":"Релиз языка программрования NewLang"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nБолее года назад я начал публикацию статей с описанием особенностей нового языка программирования. С тех пор утекло много воды, было протестировано множество идей, в итоге несколько раз все поменялось кардинальным образом и сейчас представляю на суд читателей описание предфинальной версии языка и его особенностей.\nДанная статья предназначена в первую очередь для проверки основных концепций нового языка программирования, а также для получения обратной связи от читателей Хабра. Ведь согласно наблюдению Хабр-ума палата, не замыленный взгляд со стороны очень сильно помогает в проработке новых идей.\nЭтот проект очень долго был без собственного названия и в публикациях назывался просто и абстрактно “новый язык”. Но после нескольких статей, временное название “новый язык” постепенно превратилось в имя собственное NewLang, которое я и решил в конечном итоге оставить (что еще раз подтверждает поговорку, что нет ничего более постоянного, чем что-то временное).\nNewLang - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения.\nОсновной особенностью языка является легкий, логичный и непротиворечивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка). Основные свойства и особенности языка:\nВозможность работы как в режиме интерпретатора, так и компилятора. Динамическая и статическая типизация с возможностью указания типов в явном виде. Статическая типизация является условно строгой (автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных, например, целое число может быть автоматически преобразовано в вещественное, но не наоборот) Автоматическое управление памятью. ООП в виде явного наследования классов и утиная типизация. На уровне синтаксиса поддержка нескольких типов функций (обычные и чистые функции без побочных эффектов). Необязательные и именованные параметры функций. Возможны вставки кода на языке реализации (С/С++). Простая интеграция с уже существующими программными библиотеками (в том числе импорт нативных переменных и функций из С/С++). Имеется REPL read-eval-print loop — «цикл: чтение — вычисление — вывод». Зачем нужен NewLang? У всех современных языков программирования происходит постоянное развитие (читай усложнение) синтаксиса по мере выхода новых версий. Это является своего рода, платой за появление новых возможностей и воспринимается пользователями как естественное явление.\nНо одновременно является и серьезной проблемой, т.к. с выходом новых версий добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки и трудоемкости поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов.\nУ NewLang сложность языковых конструкций естественно ограничена за счет разделения синтаксиса языка на две части, что упрощает его изучение и использование. Основной синтаксис — для написания программ в объектно-ориентированном (императивном) и декларативном стилях, который основан не на зарезервированных ключевых словах, а на строгих грамматических правилах и Расширенный синтаксис — когда основного синтаксиса становится недостаточно, или требуется использовать языковую конструкцию языка реализации.\nЕще одно неудобство современных мейнстримовых языков, большинство из них были созданы до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек, а не встроены в основной синтаксис языка и систему базовых типов. У NewLang тензорные вычисления доступны «из коробки» (используется библиотека libtorch), а арифметические типы данных являются скалярами (тензорами нулевой размерности).\nОсновной синтаксис Основной синтаксис NewLang - простой и логичный за счет того, что он построен исключительно на грамматических правилах и не использует каких либо зарезервированных ключевых слов, а все буквенно-символьные последовательности рассматриваются как идентификаторы в которых можно использовать любые не-ASCII символы.\nИдеализированная цель отказа от ключевых слов, приблизить чтение исходного текста программы к чтению обычного текста за счет использования знаков препинания при описании логики работы алгоритма.\nКонечно запятая человек может вычленять ключевые управляющие слова языка и слеш или учитывать форматирование программы запятая чтобы на их основе понимать синтаксические конструкции запятая хотя при обычном чтении мы привыкли опираться именно на семантику знаков препинания точка мы конечно можем писать знаки препинания и обычным текстом точка но согласитесь запятая что тогда открытая скобка например запятая вот такой вот текст закрытая скобка будет очень не удобно читать точка\nНазвания встроенных типов или имена служебных функций системной библиотеки определяются конкретной реализацией языка, поэтому не являются зарезервированными ключевыми словами и при необходимости могут быть переопределены, например, для создания собственного, предметно-ориентированного диалекта (DSL - domain-specific language), если в этом возникнет необходимость. Но сама структура программы и логика выполняемого алгоритма все равно останутся понятны всем, кто знаком с правилами основного синтаксиса NewLang.\nПример скрипта Hello world! на NewLang\n#!./nlc --eval # Определение функции hello hello(str) := { printf := @import('printf(format:Format, ...):Int'); # Импорт стандартной C функции printf('%s\\n', $str); # Вызов C функции с проверкой типов аргументов по строке формата }; hello('Привет, мир!'); # Вызвать функцию Вывод: Привет, мир!\nРасширенный синтаксис Расширенный синтаксис — это возможность вставить в текст программы NewLang исходный код на языке реализации. Сейчас это С/С++, что позволяет использовать любые возможности этого мощного языка программирования.\nОбработка расширенного синтаксиса происходит на этапе компиляции приложения, а взаимодействие между основным и расширенным синтаксисами происходит за счет совместного использования идентификаторов, которое полностью прозрачно для пользователя и подчиняется единым грамматическим правилам основного синтаксиса.\nЕще немного примеров: Любая последовательность вычислений возвращает результат выполнения последнего оператора. Поэтому выполнение одной команды или последовательности команд всегда возвращает какой-либо результат, а оператор возврата из функции необязателен, так как результатом будет значение последнего вычисленного выражения.\nСоздание переменных\nscalar := 42 42 tensor := [1,2,3,4,5,] # Тип тензора выводится автоматически [1, 2, 3, 4, 5,]:Char str := '$1 string' $1 string Арифметические операции\ntensor * 2 [2, 4, 6, 8, 10,]:Short tensor * 20 [20, 40, 60, 80, 100,]:Short tensor * 0.5 [0.5, 1, 1.5, 2, 2.5,]:Double tensor / 2 # Результат деления — число с плавающей точкой [0.5, 1, 1.5, 2, 2.5,]:Double tensor // 2 # Целочисленное деление без остатка [0, 1, 1, 2, 2,]:Char\u003c/source\u003e tensor % 2 # Целочисленный остаток от деления [1, 0, 1, 0, 1,]:Char\u003c/source\u003e Строковые операции\nstr = 'сцепеление строк ' ++ str; сцепеление строк $1 string str('строка как шаблон'); сцепеление строк строка как шаблон string Преобразование тензоров В эпоху машинного обучения тензоры являются основными элементами вычислений, поэтому для конвертирования данных в тензоры используется отдельная синтаксическая конструкция, состоящая из двойных квадратных скобок [[ данные ]]. Подробнее про особенности преобразования типов можно прочитать далее.\ntstr := [[\"Тест\"]] # Создать тензор из строки широких символов [1058, 1077, 1089, 1090,]:Int t2 := [[ \"Тест\" ]]:Int[2,2] # Тоже самое, но тензор двухмерный [ [1058, 1077,], [1089, 1090,], ]:Int\u003c/source\u003e StrWide(tstr) # Конвертировать тензор обратно в строку Тест Double(t2) # Изменить тип данных тезора [ [1058, 1077,], [1089, 1090,], ]:Double t3 := [[ t2 ]]:Char[4] # Преобразовать тип данных тензора и его размерность [34, 53, 65, 66,]:Char Синтаксис NewLang: При разработке синтаксиса я старался придерживаться уже сложившихся правил, чтобы не создавать множественных смыслов, зависящих от контекста. И одновременно «объять необъятное»\nОсновы Операторы разделяются точкой с запятой «;». Отступы и переводы строк игнорируются (очень хотелось иметь возможность автоматического форматирование кода). Многострочные комментарии в исходном коде соответствуют стилю С/С++ и должны располагаться между символами /* и */. Вложенность многострочных комментариев не поддерживается. Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash. Последовательность выполняемых команд, которая должна выполняться как единое целое, заключается в фигурные скобки «{}». Программные вставки расширенного синтаксиса на языке реализации заключается в фигурные скобки со знаком процента %{ /* тут может быть любой код на C/C++*/ %}. Создания объектов и присвоения новых значений Для создания объектов и присвоения им новых значений в NewLang используется сразу три разных оператора.\nОператор «::=» используется только для создания новых объектов, а если объект с таким именем уже существует, то генерируется ошибка.\nОператор «:=» используется для тех же целей, но если объект с таким именем уже существует, то ошибки не происходит, а новое значение присваивается уже существующему объекту.\nИ последний оператор «=» применяется только для присвоения значения уже существующим объектам, и если объект с указанным именем отсутствует, то тоже происходит ошибка.\nИспользование трех разных операторов для создания/изменения объектов позволяет более гибко контролировать подобные операции и выявлять логические ошибки в коде на более раннем этапе.\nvar ::= 1.0; # Создать новую переменную var без указания типа var = 100; # Присвоить новое значение уже существующей переменной printf := @import('printf(format:Format, ...):Int'); /* Создать новый или переопределить объект printf, который будет результатом выполнения глобальной функции @import */ Идентификаторы объектов и модификаторы В качестве идентификаторов можно использовать буквы, цифры и знаки подчеркивания в любых комбинациях, при условии, что первый символ идентификатора не является цифрой.\nВ NewLang существует возможность указания области видимости и времени жизни объекта с помощью модификатора — специального символа перед именем переменной. Это может показаться немного похожим на венгерскую нотацию, но в отличие от нее, модификатор не имеет отношения к типу объекта и не является частью имени идентификатора. К тому же в качестве модификаторов используется строго определённые символы, назначение которых определено заранее.\nТак, символ «$» в начале имени обозначает локальную переменную, время жизни которой ограничено текущей областью видимости и при её завершении локальная переменная уничтожается. Символ «@» обозначает глобальную переменную, а сам объект сохраняет свое состояние даже после выхода из текущей области видимости. Так же обозначаются и имена типов данных, например, при создания новых типов, а в качестве модификатора используется символа двоеточия «:»\nСемантика обращения к аргументам функций очень похоже на работу с аргументами в bash скриптах, где $1 или $arg — порядковый номер или имя аргумента (происходит обращение к локальным переменным в текущей области видимости).\nИспользование модификаторов является обязательным только в двух случаях: - При создании нового типа данных, так как типы всегда создаются в глобальной области видимости, а их символьные имена должны быть уникальными - При обращении к объектам NewLang внутри программных вставок кода на языке реализации, так как они используется как маркеры при поиске идентификаторов NewLang в коде С/С++.\nВ остальных случаях, для обращения к переменным указывать их модификаторы не обязательно. И если при обращении к объекту модификатор не указан, то сперва ищется локальная переменная, а потом глобальная с таким же именем. Причем, локальная переменная будет перекрывать глобальную.\nТак же следует иметь в виду, что компилятор может генерировать код для прямого обращения к локальным объектам уже на этапе компиляции, тогда как для обращения к глобальным объектам, или если модификатор области видимости отсутствует, компилятор вынужден каждый раз встраивать runtime вызов функции поиска объекта в таблице символов.\nСистема типов Так как система типов языка динамическая, то явное указание типа не влияет на размер переменной и является только своего рода логическим ограничением на возможность присвоения переменной значения другого типа.\nИнформация о типах используется при проверке их совместимости, когда существующему объекту присваивается значение другого типа. Такая операция возможна только когда типы совместимы между собой и допускают автоматическое приведение. Это справедливо как во время парсинга/компиляции исходного теста, так и во время выполнения в режимах интерпретатора и/или скомпилированного файла.\nАрифметические типы: Арифметические типы данных являются тензорами - массивами чисел одного типа с произвольным количеством измерений и одинаковым размером столбцов в каждом. Единичное число тоже тензор нулевого размера.\nПоддерживаются только знаковые целые числа, т.к. в беззнаковых числах особая нужда отсутствует, а проблем с ними можно найти очень много на ровном месте.\nПроблемы беззнаковых чисел (из интернета)\nВо-первых, вычитание двух беззнаковых чисел, например 3 и 5. 3 минус 5 равно 4294967294, т.к. -2 не может быть представлено как беззнаковое число. Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных значений со знаком и без знака. С++ может свободно преобразовывать числа со знаком и без знака, но не проверяет диапазон, чтобы убедиться, что вы не переполняете свой тип данных.\nВ C++ всё же есть несколько случаев, когда можно (или необходимо) использовать беззнаковые числа. Во-первых, числа без знака предпочтительнее при работе с битами. Во-вторых, использование беззнаковых чисел связаных с индексацией массивов.\nНо это мой случай, так как индекс может быть отрицательным и даже не числом, а диапазоном или многоточием. З.Ы. И даже зная об этом, все равно умудрился недавно словить баг с отрицательными индексами у словарей!\nИмена встроенных арифметических типов говорят сами за себя: Char, Short, Int, Long, Float, Double, ComplexFloat, ComplexDouble. Отдельным типом идет логический тип Bool, который может принимать значения только 0 или 1 (false/true соответственно), и в зависимости от выполняемой операции может быть отнесен к целочисленным типам, так и не входить в их состав.\n(данный подход интерпретации логического типа данных был взят из библиотеки Torch)\n// Treat bool as a distinct \"category,\" to be consistent with type promotion // rules (e.g. `bool_tensor + 5 -\u003e int64_tensor`). If `5` was in the same // category as `bool_tensor`, we would not promote. Differing categories // implies `bool_tensor += 5` is disallowed. // // NB: numpy distinguishes \"unsigned\" as a category to get the desired // `bool_tensor + 5 -\u003e int64_tensor` behavior. We don't, because: // * We don't want the performance hit of checking the runtime sign of Scalars. // * `uint8_tensor + 5 -\u003e int64_tensor` would be undesirable. В будущем планируется добавить классы чисел для длинной арифметики и дробей, для чего зарезервированы названия типов BigNum, Currency и Fraction.\nДоступ к элементам тензора происходит по целочисленному индексу, который начинается с 0. Для многомерного тензора, индексы элемента перечисляются в квадратных скобках через запятую. Поддерживается доступ к элементам через отрицательный индекс, который обрабатывается точно так же, как в Python (-1 последний элемент, -2 предпоследний и т.д.).\nЛитерал тензор в тексте программы записывается в квадратных скобках с обязательной завершающей запятой, т.е. [1, 2,] - это литерал одномерный тензор из двух чисел. После закрывающей скобки тип тензора может быть указан в явном виде. Если тип не указан, то он выводится автоматически на основании указанных данных и выбирается минимально возможный байтовый размер, который позволяет сохранить все значения без потери точности.\nПримеры:\n$var_char := 123; # Тип Char выводится автоматически $var_short := 1000; # Тип Short выводится автоматически $var_bool := [0, 1, 0, 1,]; # Тензор из 4 элементов. Тип Bool выводится автоматически $tensor[10,10]:Int := 1; # Тензор Int размером 2x2 инициализированный 1 $scalar := $tensor[5,5]; # Присвоить скаляру значение указанного элемента тензора Строковые типы данных: Поддерживаются два типа строк, StrWide - символьные (широкие) и StrChar — байтовые. Различия между ними заключается в типе единичного элемента. У символьных строк единичным элементом является широкий символ wchar_t, а у байтовой строки единичным элементом является один байт (точнее char, т. е. байт со знаком). Символьные строки литералы в исходном тексте записывается в «двойных кавычках», а байтовые строки в ‘одинарных кавычках’.\nКоличество элементов символьной строки возвращается в широких символах, а размер байтовой строки в байтах, поэтому и обращение к элементу строки по индексу происходит соответственно либо к символу, либо к байту.\nВажный момент. К любой переменной можно обратиться так же, как к функции (записав после её имени круглые скобки). Результатом этой операции будет создание копии/клона объекта. Причем некоторые типы (словари, классы и символьные строки) можно использовать в качестве шаблона при создании копии объекта с модифицированными свойствами, если новые и/или изменяемые значения указать в скобках, как аргументы при вызовах функций. Так, если при создании копии в скобках указать набор новых данных, то результирующая копия будет содержать уже измененные данные.\nНапример:\n$template := \"${name} $1\"; # Обычная строка $result := $template(\"шаблон\", name = \"Строка\"); # result = \"Строка шаблон\" Составные типы данных: Словарь Словарь — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии (он похож и на tuple и на структуру одновременно). Словари от тензоров отличаются тем, что являются только одномерными массивами, но каждый элемент может содержать произвольное количество элементов любого типа, в том числе и другие словари.\nДоступ к элементам словарей происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. Индекс также начинается с 0 и как у тензоров, тоже может быть отрицательным.\nЛитерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, т.е. (,) - пустой словарь, (1, 2= «2», name=3,).\nПеречисление Перечисление - это не отдельный тип данных, а обычный словарь, у которого все элементы имеют уникальные имена и целочисленные значение, которое явно указывается при определении или вычисляется автоматически (на единицу больше предыдущего элемента). У перечислений тип значения указывается сразу после закрывающей скобки через двоеточие (ONE=1, TWO=, THREE=): Int.\nКлассы Класс (реализовано частично) - тип данных, с помощью которого реализуется один из принципов ООП - наследование. При создании экземпляра класса создается новая переменная, у которой сохраняется информацию о своем родителе и которая наследует от него свойства и методы. Тип данных «класс» аналогичен словарю, но все свойства обязаны иметь имена (хотя доступ к свойствам класса по индексу так же возможен). Литерал с типом «Класс» в тексте программы записывается в круглых скобках без завершающей запятой, т. е. () - пустой класс, (1, 2= «2», name=3).\nПока остальные детали классов до конца не реализованы, поэтому описывать их не буду, т. к. в итоговом варианте синтаксис классов и определения их методов могут поменяться.\nФункции Синтаксис NewLang поддерживать несколько типов функций (а в будущем и методов классов): обычные функции, чистые функции и простые чистые функции.\nДля всех типов функций поддерживаются аргументы по умолчанию. При создании функции, её аргументы указываются как в Питоне, т.е. вначале идут обязательные аргументы, потом аргументы со значениями по умолчанию, где имя аргумента отделяется от его значения по умолчанию знаком равно «=». Если функция допускает обработку произвольного количества аргументов, то последним в списке параметров указывается многоточие.\nОбычная функция Обычная функция — такие функции являются именно обычными функциями в понимании С/С++. Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д.\nВнутри обычной функции можно обращаться к локальным и глобальным объектам, и они могут содержаться вставки на языке реализации, например, для вызова функций из внешних библиотек.\nВставки на языке реализации оформляются в виде %{ %} и могут содержать любой текст на С/С++, а прямо из него можно обращаться к локальным и глобальным объектам NewLang так же, как и в обычном синтаксисе, указывая первым символом имени соответствующий модификатор ($ для локальных объектов и @ для глобальных).\nТехнически, такая программная вставка просто переносится трансплайтером непосредственно в исходный текст генерируемого файла, а все идентификаторы NewLang специальным образом декорируются (добавляются специальные маркеры для их идентификации), после этого исходный текст подается на вход обычному компилятору С++. Для локальных объектов трансплайтер может генерировать код для прямого доступа к объекту на этапе компиляции, а для работы с глобальными объектами вынужден использовать runtime вызовы функции поиска в таблице символов.\nНапример:\nprint(str) := { %{ printf(\"%s\", static_cast\u003cconst char *\u003e($str)); /* Прямой вызов С функции */ %} }; Чистые функции Чистая функция - это тоже обычная функция, только в том смысле, какой в него вкладывает функциональное программирование. Создания чистой функции происходит с помощью оператора «:-». У чистой функции отсутствует доступ к контексту и глобальным объектам, поэтому она может обрабатывать только те данные, которые были ей переданы в качестве аргументов.\nПрограммные вставки на языке реализации внутри чистых функций не запрещены и могут использоваться, например, для отладки. Но делается это на страх и риск разработчика. Именно он отвечает за их «чистоту», например при вызове функций из внешних библиотек.\nSum(arg1, arg2) :- {$arg1+$arg2;}; # Вернуть сумму аргументов Так как в языке отсутствует оператор возврата данных из текущего блока выполнения (аналог оператора return \u003cданные\u003e), то возвращаемым значением функции / блока кода всегда является результат выполнения последней операции.\nПростые чистые функции Простые чистые функции — отдельный класс чистых функций, которые предназначены только для вычисления логического результата (т.е. они являются предикатами) и их отличает упрощенная формой записи. Тело простой чистой функции состоит из последовательности операторов, которые разделяются запятыми и заканчиваются, как и любое выражение, точкой с запятой. Все операторы простой чистой функции всегда приводятся к булевому значению, а итоговый результат функции вычисляется по одной из возможных логических операций: И, ИЛИ и исключающее ИЛИ.\nНапример:\nfunc_and(arg1, arg2) \u0026\u0026= arg1==3, arg2 \u003e 0; # Простая чистая функция Логическое И func_or(arg1, arg2) ||= arg1==3, arg2 \u003e 0; # Простая чистая функция Логическое ИЛИ func_xor(arg1, arg2) ^^= arg1==3, arg2 \u003e 0; # Простая чистая функция Исключающее ИЛИ Специальные типы данных: None None (пустой тип) — не содержит значения (точнее имеет одно значение None) и совместим с любым другим типом данных. Указывается в тексте программы как один подчерк «_». Значение None имеют не инициализированные переменные и при попытке чтения из такой переменной возникает ошибка.\nТип переменной может быть явно указан или выведен автоматически из присваиваемого значения. Присвоить новое значение уже инициализированной переменной можно только для совместимого типа, так как неявное преобразование типов не допускаются.\n$var := _; # Создать переменную со значением None $var2 := var; # Ошибка!!! Нельзя прочитать неинициализированную переменную var $var = 1000; # У переменной будет тип Short (минимальный размер для хранения значения) $var = 0,5; # Ошибка!!! Short ← Float не совместимы $var = _; # Очистить значение переменной $var = 0,5; # Теперь можно, т. к. None совместим с любым типом Диапазон (Range) Диапазон (реализовано частично) — специальный тип данных, являющейся приблизительным аналогом типа «генератор» в Python. К диапазону можно обращаться как к итератору и он будет поочередно выдавать элементы в указанном интервале с заданным шагом. Диапазон в тексте программы указывается как два или три элемента через две точки, например 1..5 — диапазон от единицы до пяти с шагом по умолчанию 1. В качестве параметров диапазона можно указывать не только литералы, но и имена переменных. Например, 0,1..$stop..0,1 — диапазон от значения 0,1 до значения, указанного в переменной $stop с шагом 0,1.\nДиапазон для целых чисел можно использовать в качестве индекса у тензоров (точнее, у любых объектов, которые допускают доступ к своим элементам по индексу, т.е. тензоры, словари и текстовые строки). Фактический, это поведение аналогично slice в языке Python и array[1:5] в Python означает тоже самое, что и array[1..5] в NewLang.\nВ качестве индекса у тензоров еще можно указать произвольное количество измерений с помощью многоточия, т.е.\n$tensor[…, 0] = 0; # Обнулить все первые элементы в каждом измерении. Итераторы Итераторы (в разработке) - самый сложный и неоднозначный тип данных для работы с элементами коллекций.\nДля работы с итераторами зарезервированы символы “!” и “?”, но сами итераторы пока не реализованы.\nПреобразование типов Явное приведение типов Несмотря на динамическую типизацию языка, если тип переменной указан явно, то автоматическое приведение типов не выполняется, и чтобы присвоить переменой значение не совместимого типа, требуется явное преобразование.\nТак как символьные названия типов относятся к деталям реализации, то явное преобразование в конкретный тип данных производится с помощью вызова функции с системным именем, т. е. Bool(), StrWide(), Long и т. д. Причем у тензоров при таком преобразовании изменяется только тип данных, но размерность тензора не меняется.\nДля преобразования любого типа данных в строку ещё можно использовать оператор конкатенации строк, которой преобразует любой тип данных в строковое представление. Но так как строковых типов два (байтовые и широкие строки), то тип строки определяется первым аргументом в операторе конкатенации, т. е.\n\"\" ++ 123 # \"123\" - Строка широких символов '' ++ 123 # '123' - Байтовая строка Или преобразовать любое значение в строковое с помощью строки-шаблона: val := 12345; \"$1\"(val) # Будет строка \"12345\" Tensor comprehensions В эпоху машинного обучения тензоры являются основным элементом вычислений, поэтому для конвертирования данных в тензоры используется отдельная синтаксическая конструкция, состоящая из двойных квадратных скобок [[ данные ]]. Фактически это оператор и функция времени выполнения в зависимости от указанных между двойные квадратными скобками выражения.\nЧтобы преобразовать любую переменную в тензор (с учетом допустимости такого преобразования), её достаточно указать между двойными квадратными скобками. Выражение [[ varibale ]] - преобразует переменную varibale в одномерный тензор с автоматическим выводом типа данных. Для преобразования в одномерный тензор конкретного типа используется выражение [[ varibale ]]:Type, где _Type- - любой из арифметических типов.\nЕсли требуется преобразовать переменную не в одномерный тензор, а в тензор конкретного типа и заданной размерности, то это делается выражением [[ varibale ]]:Type[2,2], которая вернет тензор с размерностью 2х2 и типом Type у элементов.\nВнутри двойных квадратных скобок может быть не только любое выражение, но и литерал или диапазон. В этом случае, они также раскрываются в тензор по таким же правилам.\nВ будущем планирую добавить возможность указания сразу нескольких значений через запятую для их объединения в один тензор.\nПримеры:\n\u003e[[(1,2,3)]] # Тензор из словаря [1, 2, 3,]:Char \u003e[['first second']] # Байтовая строка в тензор [102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char \u003e [[(first='first', space=32, second='second')]] # Получаем тензор из словаря с такими же данными [102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char \u003e[[ 0 ... ]]:Double[10,2] # Тензор заданного формата с нулями [ [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], ]:Double \u003e[[ rand() ... ]]: Int[3,2] # Тензор со случайными данными [ [1804289383, 846930886,], [1681692777, 1714636915,], [1957747793, 424238335,], ]:Int \u003e[[ 0..10 ]]: Int[5,2] # Тензор из диапзона [ [0, 1,], [2, 3,], [4, 5,], [6, 7,], [8, 9,], ]:Int \u003e[[ 0..0.99..0.1 ]] # Или даже так [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,]:Double\u003c/source\u003e Операторы и управляющие конструкции Операторы: Все операторы имеют парный оператор с присвоением значения.\n+ и += сложение арифметических типов данных и -= вычитание арифметических типов данных / и /= деление (результат число с плавающей точкой) // и //= целочисленное деление с округлением к меньшему числу (как в Python) и *= умножение ** и **= возведение в степень (он же используется и для повторения текстовых строк) ++ и ++= конкатенация строк с автоматическим приведением аргументов к стоковому типу (символ инкремента специально используется вместо одиночного плюса для того, чтобы в явном виде разделить конкатенацию строк и операторы арифметического сложения) Операторы сравнения: \u003c, \u003e, \u003c=, \u003e= классические для сравнения скаляров ==, != операторы сравнения с автоматическим приведением совместимых типов для любых объектов ===, !== оператор точного сравнения для любых объектов (автоматического приведения типов не выполняется)s Проверки типов (в разработке): Проверка имени класса «~» - немного похож на оператор instanceof в Java. Левым оператором должен быть проверяемый объект, а правым оператором - название типа, строка литерал или объект строкового типа с именем класса. Результатом операции будет истина, если правый операнд содержит название класса проверяемого объекта или он присутствует в иерархии наследования у проверяемого класса.\nname := \"class\"; # Строка с именем класса var ~ :class; var ~ \"class\"; var ~ name; (field1=«value», field2=2, field3=«33»,) ~~ (); # Истина (т. е. левый операнд словарь) (field1=«value», field2=2, field3=«33»,) ~~ (field1=_); # Тоже истина (т. к. поле field1 присутствует у левого операнда) Утиная типизация «~~» - приблизительный аналог функции isinstance() в Python, который для простых типов сравнивает совместимость типа левого операнда по отношению к правому, а для словарей и классов в левом операнде проверяется наличие всех имен полей, присутствующих у правого операнда. т. е.\n(field1=«value», field2=2, field3=«33»,) ~~ (); # Истина (т. е. левый операнд словарь) (field1=«value», field2=2, field3=«33»,) ~~ (field1=_); # Тоже истина (т. к. поле field1 присутствует у левого операнда) Строгая утиная типизация «~~~» - для простых типов сравнивается идентичности типов без учета совместимости, а для составных типов происходит строгое сравнение всех свойств. Для данной операции, пустой тип совместим только с другим пустим типом!\nУправляющие конструкции (в разработке) Условный оператор В качестве оператора проверки условия используется синтаксическая конструкция, соответствующая по смыслу термину «следует», т.е. тире и угловая скобка «-\u003e». Такая запись условного оператора очень похожа на математическую и легко объединяется в последовательности для проверки множественных условий вида «else if».\nВ общем случае условный оператор имеет вид:\nусловие -\u003e действие; или (условие) -\u003e {действие}; или (условие1 || условие2) -\u003e {действие} -\u003e {действие иначе}; Или расширенный вариант «else if», для наглядности записанный с отступами:\n(условие1) -\u003e {действие1} (условие2) -\u003e {действие2} (условие3) -\u003e {действие3} -\u003e {действие_иначе}; Операторы циклов (в планах) Операторы циклов пока в разработке , т. к. плотно связаны с итераторами.\nПока планирую для циклов использовать конструкции: (условие) \u003c–\u003e {тело цикла};\nИли так: (условие) -» {тело цикла};\nИ хотя синтаксис мне не очень нравится, но я решил пока не ломать над этим голову и планирую попробовать несколько вариантов оформления циклов.\nОператоры прерывания потока выполнения команд (реализовано частично) Оператором прерывания потока выполнения команд и возврата из текущей функции, т.е. самым близким аналогом оператора return\nявляется оператор два символа минус «–». Но в отличие от классического return, оператор возврата не возвращает значения, т.к. значение из любой функции или блока кода возвращается всегда и им является результат выполнения самой последней операции (или None, если такая операция отсутствует).\nПока не придумал, как оформлять оператор прерывания потока выполнения в случае ошибки (при его выполнении будет происходить генерация исключения), поэтому, если будут предложения, пишите в комментариях к статье (и про оформление циклов тоже).\nОбработка ошибок (в планах) В самом начале работ я ориентировался на классический вариант обработки исключений, который в обычных языках программирования обычно оформляется ключевыми словами try .. catch .. finally с различными вариациями. Но в условиях жестких ограничений на синтаксис языка, и невозможности использовать ключевые слова, комбинировать символы для указания разных типов блоков при обработке исключений, было бы крайне сомнительной затеей. Ведь основная цель разработки NewLang — простота и понятность кода, а тут с самого начала могут появиться комбинации скобочек, стрелочек, палочек и других подобных символов.\nИ тут в голову пришла очень простая мысль. А ненужно повторять логику обработки ошибок из классических языков программирования! Ведь основная цель подобных синтаксических конструкций - выделить участок кода где возможно возникновение ошибки, перехватить и обработать правильный тип исключения. Ведь классические языки программирования изначально были жестко привязаны к машинному представлению данных в оперативной памяти компьютера и тип данных для них играл принципиально важное значение. Но это не является ограничением для языков с динамической типизацией!\nПоэтому, подход к обработке исключений планируется следующий: Программный код, который может привести к ошибке, заключается в двойные фигурные скобки {{ любой код или вызов одиночной функции }}, а результат выполнения такого блока кода присваивается переменной. После этого анализируется возвращенное значение и тип исключения может обрабатываться обычным условным оператором.\nНаверно, это проще показать на примере:\n$error := {{ # начало блока try call_or_exception1(); call_or_exception2(); }}; # конец блока try # Обычные условные операторы вместо типизированных блоков catch ($error ~ :type1)-\u003e{ код обработки ошибки 1} ($error ~ :type2)-\u003e{ код обработки ошибки 2}; Самое удивительное, что при таком подходе значительно упрощается и семантика блоков try … finally, которые вообще становятся не нужны.\nИсходный код на Java:\ntry { try { throw new Exception(\"a\"); } finally { throw new IOException(\"b\"); } } catch (IOException ex) { System.err.println(ex.getMessage()); } catch (Exception ex) { System.err.println(ex.getMessage()); } Эквивалентный ему на NewLang:\n$catch := {{ $finally := {{ Error1(\"1\"); }}; Error2(\"2\"); # Строка выполнится даже при возникновении исключении Error1 $finally;\t# Error1 вернется, если не будет Error2 }} ($catch ~ :Error1) -\u003e printf(«%s», $catch) ($catch ~ :Error2) -\u003e printf(«%s», $catch); Как все это попробовать? Сейчас сборка проекта реализована только под Linux и если кроме текстового описания захочется в живую поэкспериментировать на своей машине, то придется собрать интерпретатор из исходников самостоятельно.\nТак как текущий вариант предназначен первую очередь для отработки концепции, то часть из описанных возможностей пока не реализована (алгоритмические конструкции, наследование классов, итераторы, некоторые операции и т. д).\nНо можно поиграться с созданием переменных, вызовом функций и выполнением арифметических операций над данными, чтобы оценить синтаксис, основанный на правилах, и может быть, предложить свои собственные мысли и доработки для его улучшения.\nСборка REPL из исходников (пока только под Linux) Подготовка репозитория Скачать исходники Скачать и развернуть архив libtorch в каталоге contrib (PyTorch Build: Stable (1.10.*) -\u003e Your OS: Linux -\u003e Package: LibTorch -\u003e Language: C++ / Java -\u003e Compute Platform: CPU -\u003e Download here (cxx11 ABI): libtorch-cxx11-abi-shared-with-deps-1.10.2+cpu.zip) Активировать и скачать исходники субмодулей (git submodule init \u0026\u0026 git submodule update) В каталоге contrib запустить файл build.sh для сборки библиотеки libffi В каталоге core запустить файл compile_syntax.sh для генерации файлов парсера и лексического анализатора. Может потребоваться установка утилит flex и bison. Если что, у меня установлены flex 2.6.4 и bison (GNU Bison) 3.7.4 Собрать Юнит-тесты (newlang_test): в каталоге core выполнить команду make CONF=UnitTest Интерпретатор (nlc): в каталоге core выполнить команду make CONF=Debug Утилита nlc (NewLangCompiler) В текущее время nlc поддерживать работу только в режиме интерпретатора (несмотря на название). Для тестирования и простой проверки компилятор не нужен, хотя на первых порах я делал именно его. Но трудоемкость работ по постоянной переделке под новый синтаксис оказалась очень высокой, поэтому на время первичной отладки языковых конструкций было принято волевое решение ограничиться интерпретатором, как более простым и быстрым способом проверки различных гипотез, а разработку настоящего компилятора (в виде трансплайтера на язык С++), отложить до окончательной проработки синтаксиса.\nПланы на будущее Естественное, одна статья и несколько маленьких примеров не дают исчерпывающей информации о возможностях языка. Да и сами возможности пока не раскрыты в полной мере. Ведь текущая версия, это скорее тестовая платформа для проверки декларируемых концепций и основного синтаксиса.\nПока остаются не реализованными некоторые из заявленных возможностей и очень важных хотелок. Но протестировать основной подход можно уже сейчас, и я буду благодарен за любую обратную связь и предложения.\nЕсли говорить о планах (естественно, в будущих версиях что-то может добавиться или измениться порядок их реализации), но в настоящий момент роадмап развития NewLang мне видится следующим образом:\nДоделать стандартные управляющие конструкции, обработку ошибок и итераторы. Доработать систему типов с учетом множественного наследования классов. Реализовать длинную арифметику и дроби. Сделать какую нибудь логическую игру (крестики нолики, судоку или что-то похожее) с алгоритмическим выбором следующего хода и его вычислением с помощью машинного обучения. Написать много разных примеров для оценки синтаксиса. Доработать синтаксис с учетом полученного опыта и обратной связи. Восстановить работоспособность компилятора для генерации исполняемых файлов. Сделать очередную большую чистку кода. Переработать и задокументировать получившуюся семантику языка с учетом всех возможностей и выпустить первую полнофункциональную версию NewLang. Ссылка на первую публикаци\n","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/ru/blog/newlang/","tags":"","title":"Новый язык программирования"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nПри разработке своего собственного языка программирования автор должен определиться, какими свойствами его язык должен обладать, ведь в конечном итоге именно это и будет определять назначение языка и особенности его использования. Причем некоторые свойства настолько сильно влияют на итоговую концепцию языка и его синтаксис, что впоследствии их изменение невозможно в принципе, либо новый синтаксис получается очень запутанным и непонятным. Наверно из-за этого многие свойства языков программирования рассматриваются и изучаются как взаимоисключающие.\nДо недавнего времени я считал, что императивная и декларативная парадигмы написания программ являются антагонистами и взаимоисключающими понятиями. Ведь выбор стиля написания кода, изначально определяется автором языка еще на стадии его проектирования и оказывает влияние на все последующие аспекты.\nНо сейчас я думаю, что это не верно. Императивный и декларативный стили программирования не являются взаимоисключающими, а писать программы только в одной из указанных парадигм подталкивают правила синтаксиса, реализованные в языке!\nДругими словами, использовать только императивную или только декларативную парадигмы разработчик вынужден не потому, что он не умеет или не хочет писать код по другому, а из-за того, что все более-менее мейнстримные языки программирования ориентированы на использование только одной парадигмы. И выбор только одной парадигмы написания кода, это ограничение, которое навязано программистам создателями языка. Ведь если они изначально ориентировались только на одну концепцию разработки кода, то и разрабатывали синтаксис языка в соответствии с этой парадигмой.\nДанная статья — размышление о совместимости декларативной и императивной парадигм программирования и возможности их одновременного использования в рамках одного языка программирования одновременно.\nЧто такое “Декларативное программирование”? Вначале мне захотелось разобраться, а существуют ли чисто декларативные языки программирования? Такие, которые могут полностью обходятся без императивных конструкций?\nНо чуть не споткнулся уже в самом начале, т.к. даже само определение «декларативное программировании», в вики описывается следующим образом:\nДекларати́вное программи́рование — парадигма программирования, в которой задаётся спецификация решения задачи, то есть описывается, что представляет собой проблема и ожидаемый результат. Противоположностью декларативного является императивное программирование, описывающее на том или ином уровне детализации, как решить задачу и представить результат.\nУже в изначальном определении закладывается противопоставление парадигм, а дальше идут рассуждения о «направлении» программирования. И хоть вики сама и не является авторитетным источником информации, но даже такая заготовка статьи смогла показать направление поиска ответов на первый поставленный вопрос.\nИ заставил задуматься один абзац в конце статьи следующего содержания:\n«Чисто декларативные» компьютерные языки зачастую неполны по Тьюрингу — так как теоретически не всегда возможно порождение исполняемого кода по декларативному описанию. Это иногда приводит к спорам о корректности термина «декларативное программирование» (менее спорным является «декларативное описание решения» или, что то же самое, «декларативное описание задачи»).\nСудя по наличию такой оговорки, ставится под сомнение наличие «чисто декларативных» языков. И как только пришлось задуматься над это мыслью, то сразу стало очевидным, что какой бы декларативный язык программирования не существовал, то в нем должна быть как минимум одна императивная конструкция, которая будет запускать поиск решения! Ведь любой синоним слова «выполнить» или «запустить» по определению будет императивом!\nНапример в языке Prolog, который обычно и приводят в качестве примера декларативного языка программирования, “замаскированным” императивным оператором является знак вопроса. Он кажется естественным и логичным, как же без него? Но по своей сути, это императивная конструкция!\nТоже самое касается и языка SQL. Он тоже как бы декларативный, но неожиданно все его команды являются императивными по сути. SELECT, CREATE, ALTER, DROP, INSERT, UPDATE, DELETE и т. д., а декларативными являются только описания условий их выполнения!\nВ результате, у меня так и не получилось найти чисто-декларативный язык программирования без императивных операторов (может быть, Вики права и такого языка программирования и вовсе не существует?).\nА что отличает декларативные языки программирования от императивных? Согласно определению, декларативными языками программирования их называют из-за возможности записать некие условия в декларативном стиле. Но кроме этого, в декларативных языках как правило присутствует и некий внутренний механизм поиска решений. Подобный “вычислитель” есть и в SQL и Prolog и во многих других декларативных языках.\nИнтересно, а является ли внутренняя система поиска решений обязательным признаком декларативного стиля программирования или это только особенность конкретного языка программирования, которая не зависит от декларативного стиля написания кода?\nЧтобы проверить данные предположения, можно было попробовать написать классическую декларативную программу на императивном языке, у которого отсутствует внутренний механизм поиска решений.\nА заодно, таким образом можно будет и изучить вопрос, получится ли написать программу в декларативном стиле используя обычный императивный язык программирования?\nДля примера, решил попробовать повторить уже классическую программу в декларативном стиле на Прологе.\nparent(\"Tom\",\"Jake\"). parent(\"Janna\",\"Jake\"). parent(\"Tom\",\"Tim\"). male(\"Tom\"). male(\"Tim\"). male(\"Jake\"). female(\"Janna\"). brother(X,Y):-parent(Z,X),parent(Z,Y),male(X),male(Y),X\\=Y. ? brother Получилась вот такая функционально - эквивалентная программа на С++, которая максимально приближена по стилю к декларативному прототипу:\nenum sex_ { male, female }; struct human; typedef std::vector\u003chuman *\u003e parent_; struct human { const char *name; sex_ sex; parent_ parent; }; human Tom{\"Tom\", male,{}}; human Janna{\"Janna\", female,{}}; human Jake{\"Jake\", male,{\u0026Tom, \u0026Janna}}; human Tim{\"Tim\", male,{\u0026Tom}}; std::vector\u003chuman *\u003e humans{\u0026Tom, \u0026Janna, \u0026Jake, \u0026Tim}; auto brothers = [](human * a, human * b) { auto intersec = [](parent_ \u0026a, parent_ \u0026 b) { for (auto elem_a : a) { for (auto elem_b : b) { if(elem_a \u0026\u0026 elem_b \u0026\u0026 elem_a == elem_b) { return true; } } } return false; }; return a \u0026\u0026 b \u0026\u0026 a != b \u0026\u0026 a-\u003esex == male \u0026\u0026 b-\u003esex == male \u0026\u0026 (intersec(a-\u003eparent, b-\u003eparent)); }; for (auto a : humans) { for (auto b : humans) { if(brothers(a, b)) { std::cout \u003c\u003c a-\u003ename \u003c\u003c \" and \" \u003c\u003c b-\u003ename \u003c\u003c \"\\n\"; } } } Конечно, текст на С++ получается значительно многословней, чем вариант на Прологе, но по сути, это почти дословное повторение декларативного стиля написания кода. Тем более, не стоит забывать про рассуждения в начале статьи об изначальном выборе концепции при создании языка и “принуждении” программистов пользоваться только одной, изначально выбранной парадигмой разработки.\nТаким образом, можно с высокой долей уверенности утверждать, что теоретически можно писать код одновременно в разных стилях.\nНо что тогда мешает в рамках одного языка программирования писать с использованием императивного и декларативного стиля? Неужели только убежденность создателей языков в том, что императивный и декларативный стили программирования являются взаимоисключающими? И только из-за этого получаются языки программирования, синтаксис которых подходит для использования одной единственной парадигмы?\nНо если это так, то что мешает попробовать разработать синтаксис языка программирования, в котором можно было бы использовать сразу императивный и декларативный стили программирования одновременно?\nЧто мешает совместить императивный и декларативный стили написания в рамках одной программы? В любой компьютерной программе всегда существует разделение кода на описание данных и на языковые конструкции для их обработки, т.е. фактически это разделение на данные и на функции. Мне кажется, что основная сложность, которая не дает использовать разные стили программирования в рамках одного языка, это необходимость разделять описываемые сущности на «данные» и «управляющие конструкции». Ведь это свойство (необходимость разделения сущностей на “данные” и “функции”), является неотъемлемой частью любого языка программирования.\nЭто не удивительно, ведь на заре становления ИТ индустрии, создатели первых языков программирования ориентировались исключительно на императивный стиль, потому что назначением любого компилятора было - преобразовать исходный текст программы в машинные инструкции. И на примерах модульного, структурного и объекто-ориентированного подходах показана и доказана необходимость оформления исполняемого кода в выделенные процедуры с последующей их группировкой в модули и классы.\nА декларативный стиль написания программ стал появляться только после создания высокоуровневых языков программирования. И основная цель создания данных языков сместилась на поиск решения конечного пользователя, а не на упрощение генерации бинарных файлов с машинными инструкциями. Если внимательно посмотреть на приведенные выше примеры кода, то можно заметить, что в них определения данных и операторы для их обработки идут вперемешку, (для примера на С++ это определение лямбд функции), что кардинально отличается от императивного подхода.\nТак может быть, основная особенность декларативного стиля как раз и заключается в том, что в нем не разделяются «данные» и «действия над данными»? Или как вариант, можно не указывать выполняемые действия над данными вовсе (как в некоторых SQL конструкциях)?\nМожет быть как раз именно эта особенность (возможность последовательной записи программного кода в соответствии с собственными логическими рассуждениями, в которых могут перемежаться «данные» и «функции», как это происходит при человеческом мыслительном процессе), не дает в полной мере реализовать возможность совмещения императивных и декларативных стилей программирования?\nИ если это так, тогда можно попробовать разработать такой синтаксис, который будет поддерживать определение как данных, так и декларацию функций в рамках единого потока языковых конструкций!\nПроверка гипотезы в новом языке программирования Для поверки данного предположения, я решил добавить в свой новый язык программирования (синтаксис которого допускает определение функций в одном потоке с описанием обрабатываемых данных), недостающие алгоритмические конструкции, которые позволяли бы реализовать императивный стиль программирования, несмотря на изначальную ориентацию только на декларативную парадигму.\nПравда с учетом изначальных ограничений синтаксиса нового языка (запрет на применение операторов в виде зарезервированных ключевых слов), в качестве оператора проверки условия была выбрана синтаксическая конструкция, соответствующая по смыслу термину «следует», т.е. тире и угловая скобка «-\u003e».\nВ результате, условный оператор получился практически математический, который легко объединяется в последовательности для реализации проверки множественных условий вида «else if». А для объединения сразу нескольких логического операторов между собой и для отделения их от последующего действия, операторы проверки условия можно заключать в круглые скобки.\nВ общем случае условный оператор в новом языке программирования имеет вид:\nусловие -\u003e действие; или (условие) -\u003e {действие}; или (условие1 || условие2) -\u003e {действие} -\u003e {действие иначе}; Или расширенный вариант, для наглядности записанный с отступами:\n(условие1) -\u003e {действие1} (условие2) -\u003e {действие2} (условие3) -\u003e {действие3} -\u003e {действие_иначе}; Тогда и операторы циклов можно будет записать практически аналогично, только выбрав в качестве оператора, не оператор следования, а следование с возвратом (раз уж нужно указывать циклическое действие).\nЦикл пока:\n(условие) \u003c-\u003e {тело цикла}; счетный цикл для работы с итератором:\n(счетчик_или_данные!)? \u003c-\u003e {тело цикла}; В этом случае, решение тестового примера декларативной программы на Прологе можно будет легко оформить, как в императивном, так и в декларативном стилях одновременно!\nм := \"муж.\"; ж := \"жен.\"; human @= term(пол=, parent=[,]); Tom @= human(пол=м); Janna @= human(пол=ж); Jake @= human(м, [\u0026Tom, \u0026Janna,]); Tim @= human(пол=м, parent=[\u0026Tom,]); brother(h1, h2) \u0026\u0026= $h1!=$h2, $h1.пол==м, $h2.пол==м, $h1.parent \u0026 $h2.parent; // Оператор «\u0026» побитовое «И» для чисел или операция пересечения для множеств // Запись алгоритма поиска решения в императивном стиле (h1=human!, h2=human!)? \u003c-\u003e { (brother(h1, h2)) -\u003e { @print($h1, $h2, «\\n»); } }; // Краткая запись алгоритма поиска решения в императивном стиле (h1=human!, h2=human!)? \u003c-\u003e brother($h1, $h2) -\u003e @print($h1, $h2, «\\n»); // Запись поиска решения в декларативном стиле brother(human!, human!)?; Примерно это и требовалось показать!\nЗ.Ы. Я почти закончил эксперименты с синтаксисом языка. И теперь, после добавления в него недостающих алгоритмический конструкций (ветвления и циклов), планирую, что следующая статья о новом языке программирования будет посвящена описанию его полного синтаксиса и публикации исходников прототипа компилятора для возможности поиграться на реальных примерах.\nЗ.З.Ы В комментариях @gbg привел очень простой ответ на один из поднятых вопросов. Причем в более элегантном виде и без написания кода!\nНу и пять копеечек про ООП. Как ни странно:\nВ нем таки есть декларативная часть, все эти pubic, private, virtual, etc Эта декларативная часть, внезапно, элегантно позволяет реализовывать декомпозицию и управление сложностью. При наличии перегрузок, можно поиграть в алгебраическое мышление, рассматривая взаимодействие двух объектов как бинарную операцию. Ух ты, ООП - это обкатанная практикой технология, которая совмещает декларатив с императивом и вроде позволяет освоившим ее вкусно кушать и мягко спать!\nСсылка на первую публикаци\n","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/ru/blog/prog-styles-same-time/","tags":"","title":"Можно ли использовать декларативный и императивный стили написания программ одновременно?"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nХочу представить на обсуждение читателей немного необычный концепт языка программирования, в котором отсутствует проблема, присущая практически всем промышленным языкам - постоянное увеличение сложности синтаксиса языка из-за его естественного развития по мере выхода новых версий и добавления новых фич. Эта проблема описана в статье “Простое сложное программирование” и Какая “идеальная” цель развития у языков программирования?\nПосле нескольких экспериментов с синтаксисом, хочется проверить выработанную идею на широкой аудитории Хабра, которая как нельзя лучше подходит для этих целей.\nОсобенности языка:\nНизкий порог входа и естественное ограничение уровня сложности в течение длительного времени даже при условии постоянного развития самого языка. Возможность писать код программы как в декларативной, так и в императивной парадигме с использованием процедурного, модульного и объектно-ориентированного подхода. Ну и в соответствии с собственным наблюдением Хабр — ума палата, буду рад любым комментариям и предложениям, которые помогут протестировать или улучшить предлагаемое решение.\nВведение Первой необычной особенностью языка является полное отсутствие зарезервированных ключевых слов. Точнее, планируется использовать только одно единственное ключевое слово (название языка), которое может быть как главной точкой входа в приложение, так и способом доступа к настройкам языка под конкретную предметную область, например при необходимости реализации DSL парадигмы.\nВ настоящий момент название языка не выбрано, поэтому для примеров используется просто слово lang, которое в будущем будет изменено.\nДанная особенность (отсутствие зарезервированных ключевых слов) реализуется за счет того, грамматика языка основана на использовании общеупотребительных символов и классических знаков препинания, а все остальные букво-символьные последовательности при парсинге программы рассматриваются как “токены”.\nКомпилятор языка реализуется как transpiler - преобразование исходного кода программы, написанной на одном языке программирования, в эквивалентный исходный код на другом языке. Первые эксперименты с синтаксисом я начинал на Python, но после осознания необходимости разработки не только интерпретатора, но и компилятора непосредственно в исполняемый код, решил остановиться на C++. Хотя в принципе, язык реализации может быть любым.\nИспользование транспиляции при реализации компилятора решает сразу множество очевидных и не очень задач. Сразу отпадает необходимость разрабатывать низкоуровневый компилятор в исполняемый процессорный код, а в моем случае основным бонусом такого подхода становится возможность использования императивной парадигмы программирования за счет вставок кода непосредственно в исходный код приложения на языке реализации.\nИ именно этот момент позволяет естественно разделить декларативный и императивный способ написания программы. В этом случае в декларативной парадигме реализуется только одна из трех базовых управляющих конструкций, необходимых и достаточных при реализации любого алгоритма — следование.\nДругими словами, в декларативном стиле описывается только последовательность операций, которые следуют одна за другой, но отсутствует возможность запрограммировать циклы или ветвление (переходы) по условию. Из-за этого в декларативном стиле можно записать только следующие типы языковых конструкций:\nкомментарий определение переменной и присвоение ей значения создание объекта и назначение его свойствам значений по умолчанию создание функции (метода для всего класса объектов) вызов функции или итератора непосредственная вставка кода на языке реализации Так как цель текущей публикации - протестировать общую концепцию, то начну сразу с примеров без длинного описания подробностей, а некоторые нюансы буду комментировать по ходу дела. Тем более, самая главная цель “низкий порог входа” само собой подразумевает возможность самостоятельно разобраться в синтаксисе. Тем не менее, совсем без знаний языка реализации не обойтись и начальные знания в программировании на С/С++ все равно необходимы.\n“Привет, мир!” в императивной парадигме Определение обычной функции выполняется с помощью оператора присвоения “:=”, а программный код на языке реализации (в данном случае на C++) заключается в фигурные скобки. Простой пример вывода строки на экран выглядит примерно так:\nprint(str=\"\") := { printf(\"%s\", static_cast\u003cchar *\u003e($str)); } Функция print с аргументом по умолчанию в виде пустой строки внутри себя вызывает обычный printf из стандартной библиотеки.\nСоответственно “Привет, мир!” в императивной парадигме программирования будет выглядеть тривиально:\n#!/bin/lang print(str=\"\") := { printf(\"%s\", static_cast\u003cchar *\u003e($str)); }; @print(\"Привет, мир!\\n\"); Из примера видно, что обращение к аргументам внутри С++ кода происходит с использованием символа $, который указывается вначале именованного аргумента. Кроме этого, для доступа к аргументам функции можно обращаться по их порядковым номерам начиная с первого ($1, $2, $3 и т. д.). Зарезервированный аргумент $0 содержит сам объект, метод которого вызывается или nullptr, если функция не принадлежит объекту.\nОбычные функции являются именно обычными функциями в понимании С/С++. Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д. Технически, код такой функции парсится на предмет замены использованных аргументов, специальным образом декорируется её имя и добавляются специальные маркеры для идентификации содержимого. После этого исходный текст готов для сборки обычным С++ компилятором для превращения в динамическую библиотеку и после её загрузки функцию можно будет вызвать в любой момент (для вызова функции перед её именем необходимо указать символ \"@\").\nНепосредственное выполнение файла в режиме интерпретатора происходит в два этапа. На первом этапе из текста программы генерируется временный С++ файл с исходным кодом всех функций, этот файл компилируется gcc и собирается динамическая библиотека.\nНа втором этапе, собранная динамическая библиотека загружается средой выполнения, а исходный текст программы начинает последовательно выполнятся интерпретатором (все строки, за исключением определений функций).\nЕсть еще вариант, когда вместо интерпретации кода программы, генерируется С++ файл не только для функций, но и для основной части приложения. Тогда на выходе компилятора будет уже обычный бинарный файл, хотя в том случае оперативно поправить текст программы уже не получится.\nЛогическое программирование в декларативной парадигме Так как самым известным языком логического программирования в декларативном стиле считается Prolog, поэтому приведу простой пример программы Brother (поиска братьев) на Прологе и эквивалентный ему код на новом языке.\nProlog:\nmale(\"Tom\"). male(\"Tim\"). male(\"Jake\"). female(\"Janna\"). parent(\"Tom\",\"Jake\"). parent(\"Janna\",\"Jake\"). parent(\"Tom\",\"Tim\"). brother(X,Y):- parent(Z,X),parent(Z,Y),male(X),male(Y),X\\=Y. Вывод: (Jake, Tim) (Tim, Jake)\nТот же самый пример:\n#!/bin/lang human:=@term(sex=,parent=); Tom:=@human(male); Janna:=@human(female); Jake:=@human(male, (Tom, Janna,)); Tim:=@human(sex=male, parent=(Tom,)); human::brother(test=human!) \u0026\u0026= $0!=$test, $0.sex==male, @intersec($0.parent, $test.parent); human.brother? Вывод: [Tim.brother(Jake), Jake.brother(Tim),]\nНадеюсь, что синтаксис интуитивно понятен, особенно при наличии эквивалентного кода на Прологе, но на всякий случай поясню отдельные моменты.\nhuman:=@term(sex=,parent=); В этой строке создается объект с именем “human” и двумя свойствами “sex” и “parent”, значения которых по умолчанию не определены, а родителем является системный объект “term”. Использование символа \"@\" в начале термина обозначает вызов существующей функции с параметрами, указанными в скобках. В данном случае вызывается конструктор системного объекта “term”, а возвращаемым результатом является новый термин “human”, который можно воспринимать как один экземпляр класса, так и как имя целого класса, если он будет выступать в качестве родителя для других объектов.\nTom:=@human(male); Janna:=@human(female); Jake:=@human(male, (Tom, Janna,)); Tim:=@human(parent=(Tom,), sex=male); Первые две строки создают объекты “Tom” и “Janna”, у которых свойство “sex” установлено в значения “male” и “female” соответственно. А в последней строке при создании объекта Tim значения свойств задается с указанием их имени.\nКонструкции (Tom, Janna,) и (Tom,), это определение константного литерала с типом словарь, которые присваиваются указанным свойствам.\nЧтобы определение словаря не путать с указанием аргументов при вызове функции, в нем содержится обязательная финальная запятая перед закрывающей скобкой. Это правило (финальная запятая перед закрывающей скобкой) действует и при определении литерала массива, только для записи которого используются скобки не круглые, а квадратные (например [,] - пустой массив). Основным отличием словаря от массива, заключаются в способах доступа к их элементам. Для доступа к элементу массива используется целочисленный индекс, а в словаре может быть использован как индекс, так и имя элемента при его наличии. Между словарем и массивом есть еще отличия, но сейчас они не принципиальны.\nИ предпоследняя строка в примере:\nhuman::brother(test=human !) \u0026\u0026= $0 != $test, $0.sex==male, @intersec($0.parent, $test.parent);\nэто определение простой чистой функции “brother” для всех объектов, производных от “human”. Данная функция принимает один именованный аргумент “test”, значением по умолчанию которого является итератор объектов класса “human”.\nОператор \u0026\u0026= означает определение простой чистой функции, т. е. функции без внешних зависимостей, которая не имеет доступа к глобальному контексту, а результат выполнения которой является логическое значение, которое вычисляется по схеме логическое И для всех условий, указанных в теле функции через запятую.\nВыполнение и вывод результата выполнения программы происходит в строке human.brother?\nВосклицательный и вопросительный знаки обозначают итератор. Итератор “!” возвращает один текущий элемент из коллекции и передвигает указатель на следующий, а итератор “?” возвращает сразу всю коллекцию объектов целиком.\nДругими словами при выполнении строки программы human.brother ? происходит последовательный перебор всей коллекции объектов типа “human”, где у каждого объекта выполняется функция “brother” с аргументами по умолчанию. А так как в качестве аргумента по умолчанию указан итератор human !, то в качестве аргумента последовательно предается каждый из элементов указанного класса. По сути, при выполнении этой строки происходит полный перебор всех возможных комбинаций объектов класса “human” каждый с каждым.\nБолее подробное описание работы итератора и причина выбора такого синтаксиса опубликовано в отдельной статье Лаконичный итератор для декларативного синтаксиса\nРезультат выполнения будет состоять из тех пар объектов, для которых функция “brother” вернет истину, т.е. результат выполнения будет массив из двух пар объектов [Tim.brother(Jake), Jake.brother(Tim),].\nФормулировка проверяемой концепции Тестируемая концепция заключается в следующем. Синтаксис языка программирования состоит как бы из двух частей, каждая из которых является относительно независимой и в тоже время они связаны между собой.\nПервая часть сложная — предназначена для описания алгоритмов в императивном стиле на обычном языке программирования, поэтому внутри функций разработчику доступны все возможности языка реализации.\nВторая часть простая (по сравнению с первой) — предназначена только для логического описания задачи в декларативном стиле. Именно эта часть используется для начального уровня использования, а естественное ограничение только на последовательное выполнение операторов (т.е. отсутствие циклов и ветвлений) не доставляет чрезмерных сложностей в понимании исходного текста программы даже в будущем по мере развития языка.\nСвязь между двумя вариантами синтаксиса прозрачна и реализуется за счет совместного использования переменных и функций, декларация и обращение к которым происходит в едином стиле в обоих случаях за счет унификации синтаксиса на уровне использования знаков препинания.\nСейчас я специально не привожу полного синтаксиса и подробного описания остальных возможностей языка, т.к. компилятор пока не готов для публичной презентации. Но буду крайне благодарен за любой отклик или дельные предложения в отношении предложенной концепции.\nОсобенно это касается возможных конфликтов по синтаксису в представленных примерах.\n","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/ru/blog/unusual-prog/","tags":"","title":"Необычная концепция синтаксиса языка программирования"},{"body":"\nВ очередной раз увидел на Хабре статью про сложное дело под названием «программирование». И то, что программирование действительно является делом не простым воспринимается как факт и обычно не требует какого либо подтверждения.\nНо понятие «сложность» сродни термину «куча». Для кого-то и пять кокосов это не куча, а кого-то съел один и «больше не хочется» - значит для него и единственного кокоса будет много.\nТак и со сложностью ПО. Вроде бы увеличение сложности является для всех очевидным и наблюдается во всех сферах применения IT технологий, да и сами языки программирования по мере своего развития становятся все сложнее, а вот оценивать «сложность» с помощью численных метрик — дело заведомо неблагодарное, но и «нельзя управлять тем, что невозможно измерить …».\nОбычно разговоры о «сложности» включают в себя только оценочные суждения без какой либо численной оценки. А так как лично меня интересует вопрос сложности языков программирования, то я решил посчитать сложность реализации компилятора gcc в каких нибудь условных попугаях. Вдруг можно будет увидеть какие нибудь закономерности?\nВыбор «попугаев» для измерения Я не стал придумывать свои или вычислять эмпирические метрики программного кода, и в качестве «попугая» решил взять самую простую метрику SLOC (англ. Source Lines of Code) — количество строк исходного текста компилятора, которая очень легко вычисляется.\nПравда, с её помощью можно будет оценивать сложность языка только при следующем допущении — сложность языка должна находиться в прямой зависимости от сложности его реализации, если для простых синтаксических конструкций будет требовать меньше кода, чем для более сложных.\nКонечно, использование метрики «количество строк исходного кода» имеет и свои недостатки, т.к. она сильно зависит от используемого языка программирования, стиля оформления исходного кода и в общем случае не позволяет сравнивать несколько разных проектов между собой.\nНо для численной оценки сложности кода в рамках одного проекта, метрика SLOC подходит хорошо.\nМетодика подсчета SLOC Изначально попробовал использовать простой bash скрипт с поиском по маске и подсчетом числа строк в файлах исходника через wc -l. Но через некоторое время стало понятно, что приходится изобретать очередной велосипед.\nПоэтому решил взять уже готовый. После быстрого поиска остановился на утилите SLOCCount, которая умеет анализировать почти три десятка типов исходников.\nСписок типов файлов для автоматического анализа 1. Ada (.ada, .ads, .adb) 2. Assembly (.s, .S, .asm) 3. awk (.awk) 4. Bourne shell and variants (.sh) 5. C (.c) 6. C++ (.C, .cpp, .cxx, .cc) 7. C shell (.csh) 8. COBOL (.cob, .cbl) as of version 2.10 9. C# (.cs) as of version 2.11 10. Expect (.exp) 11. Fortran (.f) 12. Haskell (.hs) as of version 2.11 13. Java (.java) 14. lex/flex (.l) 15. LISP/Scheme (.el, .scm, .lsp, .jl) 16. Makefile (makefile) — not normally shown. 17. Modula-3 (.m3, .i3) as of version 2.07 18. Objective-C (.m) 19. Pascal (.p, .pas) 20. Perl (.pl, .pm, .perl) 21. PHP (.php, .php[3456], .inc) as of version 2.05 22. Python (.py) 23. Ruby (.rb) as of version 2.09 24. sed (.sed) 25. SQL (.sql) — not normally shown. 26. TCL (.tcl, .tk, .itk) 27. Yacc/Bison (.y) \u003c/code\u003e Причем, считает не просто количество строк исходного текста, но и умеет игнорировать комментарии, исключает из подсчета дубли файлов (сравнивает их хеш суммы), а также выводит расчетную трудоемкость, примерную оценку стоимости разработки анализируемого проекта и другие характеристики.\nМеня изначально интересовал объем исходников на С/С++ и может быть еще на Ассемблере, если таких файлов окажется достаточно много. Но после начала работы очень обрадовался, что не стал изобретать велосипед, а взял готовую тулзу, т.к. она отдельно считала статистику исходных файлов синтаксического анализатора Yacc/Bison (.y), который и определяет фактическую сложность парсера (читай сложность синтаксиса языка программирования).\nСтарые исходники gcc брал с https://gcc.gnu.org/mirrors.html, но перед запуском анализатора удалил каталоги других компиляторов (ada, fortran, java и т.д.), чтобы они не попадали в итоговую статистику.\nРезультаты в попугаях Итоговая статистика\nОбъем кода синтаксического анализатора Yacc/Bison\nОбъем общей которой базы GCC (только для языков C и C++)\nВыводы К сожалению, синтаксический анализатор Yacc/Bison использовался только до 3 версии, а после его использование свелось на нет. Поэтому оценить сложность синтаксиса С/С++ с помощью объема кода парсера можно лишь примерно до 1996-98 года, после чего его стали постепенно выпиливать, т.е. чуть менее, чем за десять лет. Но даже за этот период объем кодовой базы синтаксического анализатора вырос двукратно, что примерно соответствует по времени реализации стандарта C99.\nНо даже если не учитывать код синтаксического анализатора, то объем общей кодовой базы так же коррелирует с внедрением новых стандартов C++: C99, С11 и C14.\nНа графике не видно выраженного пика для С+17 и следующих версий, но предполагаю, что при текущем объеме кодой базы (более 4 миллионов строк только С и С++ кода), несколько тысяч строк, необходимых для поддержки синтаксических конструкций новых стандартов просто незаметно.\nВывод первый - очевидный. Рост сложности инструментов разработки Фактически на примере проекта GCC можно видеть постоянный и неотвратимый рост сложности рабочих инструментов программистов.\nИ как бы не говорили о деградации разработки в статье “Хорошие времена рождают слабаков”, о системном кризисе программного обеспечения, который носит поколенческом характер, но мне кажется тут дело немного в другом.\nОбновление персонала и как следствие — необходимость обучения новых сотрудников старым наработкам, тут дело не сколько в передаче знаний, сколько в возможности эти знания усваивать.\nПричем возможность усвоения знаний для разных поколений будет разная, но не из-за того, что предыдущее поколение было умнее, а у нового поколения не хватает толку в этом разобрать. Просто изменяется окружение и усложняются рабочие инструменты, по сравнению с теми, которые были в ходу у предыдущего поколения.\nВывод второй — порог входа Представьте, что нужно «сделать свой сайт». Естественно нужно определить, какую CMS для него использовать и какой брать хостинг. И если с хостингом вопрос решается очень просто, конечно же в TimeWeb, да еще и с бонусом по ссылке, то при выборе CMS приходится подумать.\nИ если для простых сайтов существуют и простые решения, то для тех, кто не ищет легких путей существует CMS Drupal, который примечателен тем, что имеет фантастически высокий порог входа для начала использования.\nЭто я к чему? При использовании любого инструмента, как и языка программирования, существует некий минимальный уровень комфортного использования. Причем этот уровень прямо пропорционально связан с размером той целевой аудитории, для которой он предназначен. Точнее, размер возможной аудитории определяется в том числе и требованиями к уровню начальных знаний и квалификации потенциального пользователя.\nИтоговый вывод — не утешительный Если рассматривать увеличение сложности только самого ПО, то это одно дело. Вот к примеру:\nСтатистика ядра Linux с вики\n17 сентября 1991: Linux версии 0.01 (10 239 строк кода). 14 марта 1994: Linux версии 1.0.0 (176 250 строк кода). Март 1995: Linux версии 1.2.0 (310 950 строк кода). 9 июня 1996: Linux версии 2.0.0 (777 956 строк кода). 25 января 1999: Linux версии 2.2.0, изначально довольно недоработанный (1 800 847 строк кода). 4 января 2001: Linux версии 2.4.0 (3 377 902 строки кода). 18 декабря 2003: Linux версии 2.6.0 (5 929 913 строк кода). 23 марта 2009: Linux версии 2.6.29, временный символ Linux — тасманский дьявол Tuz (11 010 647 строк кода). 22 июля 2011: релиз Linux 3.0 (14,6 млн строк кода). 24 октября 2011: релиз Linux 3.1. 15 января 2012: релиз Linux 3.3 преодолел отметку в 15 млн строк кода. 23 февраля 2015: первый релиз-кандидат Linux 4.0 (более 19 млн строк кода). 7 января 2019: первый релиз-кандидат Linux 5.0 (более 26 млн строк кода). А что делать, если сложность программного обеспечения накладывается на тенденцию постоянного усложнения самих рабочих инструментов? Ведь постоянное развитие языков программирования неизбежно повышает порог входа для всех начинающих и только усугубляет проблему сложности разработки ПО.\nДругими словами, не зависимо от того, как хорошо документирован код и как полно он покрыт тестами, через некоторое время устаревают используемые инструменты, завершаются жизненные циклы внешних зависимостей, и самое главное, приходят новые люди взамен тех, кто разработал или сумел разобраться в системе.\nИ у новых людей возникает необходимость разбираться в системе с самого начала, но в других начальных условиях. И из-за этого, сложность изучения системы для всех новых людей будет выше просто по факту того, что изменились внешние условия и усложнились рабочие инструменты, которыми приходится использовать новым сотрудникам.\nПонятно, что чем дальше, тем проще уже не будет. Ведь область IT , это среда с самой высокой конкуренцией. И как уж тут не вспомнить Льюиса Кэррола, что его крылатое выражение\nНужно бежать со всех ног, чтобы только оставаться на месте, а чтобы куда-то попасть, надо бежать как минимум вдвое быстрее!\nВедь это относится не только к Алисе в стране чудес, но и ко всем информационным технологиям в целом!\nПервоначальная публикация\n","categories":"","description":"","excerpt":"\nВ очередной раз увидел на Хабре статью про сложное дело под названием …","ref":"/ru/blog/complex-prog/","tags":"","title":"Простое сложное программирование"},{"body":"\nС постоянной периодичностью появляется информация о выходе новой версии того или иного языка программирования. И с каждой новой версией расширяются его возможности, добавляются новые синтаксические конструкции или иные улучшения.\nИ это очень сильно напоминает развитие технологий, как и в любой другой области техники. Когда с очередным этапом совершенствуются создаваемые творения. Быстрее, выше, сильнее … и одновременно значительно сложнее.\nОб этой проблеме меня заставила задуматься первоапрельская статья «Доказательное программирование».\nПонятно, что дата публикации статьи говорит сама за себя. Тем не менее, новые стандарты С++, постоянно выходящие спецификации Java или новый синтаксис у PHP 8, невольно заставляют задуматься, а в нужную ли сторону идет развитие языков программирования? Ведь большинство нововведений добавляют сложность в основной рабочий инструмент и решая одни проблемы, неявно добавляя множество других.\nА что должно быть в конце прогресса у развития такой дисциплины как программирование? Или хотя бы у одного конкретного языка? Ради достижения какой конечной «идеальной» цели разрабатываются новые стандарты языков программирования?\nЕсли фантазировать об идеальной конечной цели развития, например транспорта, то это будет мгновенное перемещение на любое расстояние с произвольной полезной нагрузкой и нулевым потреблением энергии.\nИли, например, какая может быть идеальная цель у медицины? Бедные не болели, а богатые не выздоравливали, вероятно, лечение любых болезней и биологическое бессмертие.\nКонечно, «идеальная» цель это очень упрощенное понятие. Фактически, «идеальная» это синоним «недостижимая», т.к. она всегда будет упираться необходимость соблюдать компромисс между различными взаимно-исключающими граничными условиями.\nНо сравнивать разработку средств программирования с процессом развития в других технических дисциплинах напрямую нельзя. Ведь при создание конечного продукта в любой технической области, все сложные производственные операции, которые требуют непосредственного участия человека, практически всегда можно разделить на отдельные, более простые части или этапы.\nЭто делается, в том числе и для того, чтобы сложность одной выполняемой операции не была запредельной для исполнителя. Но как это можно сделать при разработке программного обеспечения?\nВ данном случае, я имею ввиду конечную ограниченность возможностей одного конкретного человека в противовес возможностям разделения технологических процессов на отдельные этапы, каждый из которых может выполняться совершенно разными людьми (как пример, это обычный конвеер с его разделением труда на элементарные операции или узкая специализация врачей-специалистов в одной конкретной области).\nВедь даже сложно себе представить фантастическую организацию труда программистов в виде конвеера:\nПервый разработчик пишет только интерфейсы функций и их вызовы, после чего передает код второму сотруднику. Второй пишет в тексте программы только условия проверки и безусловные переходы и передает текст третьему. Третий отвечает за написание циклов и общее форматирование кода и т.д. и результате ожидаемо получится полный бред. Из-за этого индустрия разработки ПО вынуждена идти по экстенсивному пути развития (т.е. за счет увеличения используемых в производстве ресурсов). Современные промышленные языки программирования имеют очень богатые возможности по разделению кода приложения на отдельные функции/модули/компоненты, что позволяет вести разработку сложного программного продукта сразу множеству сотрудников одновременно.\nНо и такое развитие имеет естественное ограничение. И этим ограничением является сам человек, так как каждый разработчик должен знать и уметь пользоваться своим рабочим инструментом, т.е. языком программирования.\nЕсли взять приведенную выше аналогию с конвеером, то в ней каждый рабочий должен был бы досконально знать большую часть используемых станков и инструментов на всем заводе, независимо от того, какую одну конкретную операцию он выполняет на своем рабочем месте.\nВедь парадокс развития языков программирования заключается в том, что добавляя новые возможности и синтаксические конструкции, мы усложняем рабочий инструмент, предназначенный как для совместного, так и для индивидуального использования!\nИ получается, что одновременно с процессом постоянного наращивания возможностей средств разработки идет и обратный процесс — увеличение сложности разработки кода отдельно взятым разработчиком. Фактически, это и есть то самое взаимоисключающее непреодолимое противоречие.\nМожет быть именно поэтому невозможно найти «серебряную пулю», которая бы повышала производительность труда одного программиста? Ведь внимание и возможности человека не безграничны. И любые новшества и улучшения рабочего инструмента программиста вынужденно толкают всю IT индустрию на экстенсивный путь развития.\nВозможно следует разрабатывать принципиально новые подходы, а не гнаться за синтаксическим сахаром в языках программирования из прошлого века? Или и вовсе не париться, продолжать пользоваться тем, что есть, а теория дедушки Дарвина все сама расставит по своим местам?\nПервоначальная публикация\n","categories":"","description":"","excerpt":"\nС постоянной периодичностью появляется информация о выходе новой …","ref":"/ru/blog/lang-final/","tags":"","title":"Какая «идеальная» цель развития у языков программирования?"},{"body":"\nНекоторое время назад я писал про «Интернациональное программирование на естественных языках», в которой попытался представить достойную цель для абстрактного языка программирования, попробовав примерить на него роль связующего звена между миром программистов с компьютерами и не программистов.\nНо в результате оказалось, что это не нужно в принципе, т.к. «не программистам» просто не требуется учиться писать программы. А если иногда такое желание и возникает, то вполне хватает обычных формализованных языков программирования, которых уже сейчас насчитывается наверно более десяти тысяч.\nА пользователи, как программисты, так и не программисты, просто хотят решать возникающие перед ними задачи. И хотя задачи бывают совершенно разные, но если способ (алгоритм) её решения известен, то выбрать язык для её решения не составит никакого труда.\nЗа исключением одного класса задач. Задач, решение которых нельзя описать в виде алгоритма. Но можно указать некие критерии, которым должно удовлетворять искомое решение.\nЯ имею ввиду логические языки программирования и Пролог, как самый яркий представитель этого класса.\nЕще помню воспоминание из юности, когда удалось достать дискету с этим языком. Ух, с каким задором горели мои глаза, когда мне казалось, ну вот, еще чуть-чуть и будет создана система с базой знаний, у которой и можно будет получить заветный ответ 42 на любой вопрос.\nТак почему этого так и не случилось? В чем проблема Пролога, да и любой системы / языка программирования, назначение которых анализировать факты и искать ответы на вопросы?\nЭта проблема называется «Комбинаторный взрыв» - экспоненциальная (или более) зависимость времени работы алгоритма от количества входных данных. И есть как минимум два решения этой проблемы.\nПодходы к написанию программ Прежде чем переходить к частностям, следует сказать пару слов про парадигмы программирования. Обычно противопоставляют между собой два разных стиля в написании программ: императивный и декларативный.\nИмперативный — это классический вариант написания программы, при котором программист сам задает шаги алгоритма для получения конечного результата. А сам текст программы состоит из последовательности команд, которые читают, сохраняют и обрабатывают данные или вызывают другие команды.\nДекларативный — в этом стиле программист описывает условия задачи и правила для получения требуемого результата, но не требуется детально описывать все шаги работы алгоритма, оставляя их на усмотрения компьютера.\nИменно к декларативному стилю относится язык Пролог, да и все остальные логические языки программирования. К декларативному стилю написания программ следует относить и язык структурированных запросов (SQL).\nИ проблема под называнием «комбинаторный взрыв» сильнее всего оказывает негативное влияние как раз на подобные языки. Ведь в императивном подходе программист сам отвечает за последовательность выполняемых команд, и если он запрограммировал алгоритм полного перебора всех возможных вариантов решений, то он сам себе злобный Буратино.\nДругое дело, программирование в декларативном стиле. Разработчик хоть и может указать ограничения, которые следует применять при поиске решения, но это возможно только в том случае, когда известен алгоритм решения задачи. Но если алгоритм решения известен, то проще использовать императивный стиль, как раз и реализуя этот алгоритм!\nПоэтому основное применения языков программирования в декларативном стиле — отказаться от необходимости описания четкого алгоритма поиска решения, отдав это компьютеру на откуп. Для которого самое простое решение «в лоб» - полный перебор возможных вариантов.\nИменно в этом случае и начинается экспоненциальный рост времени выполнения алгоритма. И начиная с определенного порога, время ожидания ответа становится неприемлемым для реального использования. Это и означает «Комбинаторный взрыв», резкий («взрывной») рост времени выполнения алгоритма при увеличении размера входных данных.\nПроблема поиска решений В языке Пролог эта проблема решалась за счет использования механизма отката и отсечений. Иногда еще уточняли про «красное» и «зеленое» отсечение решений. Но в любом случае, это были алгоритмические механизмы для ограничения количества размера дерева возможных решений, а необходимость их применения все равно остается на программисте.\nНо чтобы их правильно реализовывать, нужно знать алгоритм решения, что опять возвращает нас к утверждению о том, что если известен алгоритм, то и программировать его удобнее в императивном стиле.\nА если полный алгоритм решения задачи не известен (или не подходит, например из-за большого времени для его работы), то в результате остается либо увеличивать производительность системы, чтобы сократить время выполнения алгоритма, либо искать другое решение, в том числе, сокращая вычислительную сложность поиска решений, например, исключая заведомо не подходящие данные, чтобы уменьшить возможные комбинации их перебора.\nМасштабирование производительности Увеличение производительности тоже бывает разным и работает не во всех случаях. Вертикальное масштабирование производительности одного узла вычислительной среды имеет свой естественный предел. И даже многократное увеличение скорости работы компьютера может лишь отдалить порог терпения пользователя при ожидании получения результата, но не в состоянии принципиально решить саму проблему.\nДругое дело горизонтальное масштабирование, при котором выполнение алгоритма запускается на отдельных узлах, которые параллельно решают одну и ту же задачу. Такой способ масштабирования позволяет уже значительно сократить время получения итогового результата для сложных вычислительных задач. И хотя это способ является решением «в лоб», но успехи в области data science доказывают успешность такого подхода.\nКонечно, у горизонтального масштабирования тоже есть подводные камни. В первую очередь, сам алгоритм должен допускать возможность параллельного выполнения независимо от других узлов. Также требуется автоматизация управления заданиями, самими вычислительными узлами, да и всей системой в целом.\nТут частично может помочь парадигма функционального программирования, которая ограничивает результат вычисления функций только входными параметрами и результатом выполнения других функций, но сам результат не зависит от состояния системы или иных внешних данных.\nПоиск обобщенного решения Вторым способом решения решения проблемы комбинаторного взрыва является уменьшение вычислительной сложности решения. Тут имеется ввиду не выбор другого алгоритма или решение задачи в символьном виде. Если такое возможно, то все опять сразу сведется к императивному стилю программированию.\nЯ имею ввиду возможность поиска самого алгоритма решения. Точнее не совсем алгоритма, а возможность применения к входным данным различные методы отбора, чтобы исключить необходимость их полного перебора. По сути, это сводится к применению различных методов и механизмов обработки входных данных с учетом различных закономерностей.\nЭто возможно как алгоритмическими методами (откат и отсечение в Прологе), так и с применением машинного обучения, которое очень хорошо справляется с поиском различных закономерностей.\nЕстественно, такой способ подходит не для всех классов задач. Он не подходит для выявления ВСЕХ возможных решений. Но там где это не требуется, подобные способы уменьшения вычислительной сложности имеют право на существование.\nНапример, не требуется искать все возможные лекарства от конкретной болезни, достаточно одного, с учетом определенных ограничений, которое гарантированно подействует.\nК тому же, даже при нахождении частных решений, всегда существует шанс, что с их помощью получится увидеть не очевидные на первый взгляд закономерности, которые помогут показать новые пути алгоритмического уменьшения вычислительной сложности основной задачи.\nОбласть не решаемых задач Как вы считает, а реально ли создать язык логического программирования, который бы сам умел автоматизировать поиск решений для задач подобных классов? Или хотя бы имел в своем арсенале встроенные механизмы для автоматизации подобной деятельности?\nРезультаты опроса из оригинальной публикации - 57.47% Ха-ха! То, что хочет автор и называется искусственным интеллектом (50 голосов) - 27.59% Поиск решений нельзя автоматизировать (24 голоса) - 19.54% Это уже есть и все давно придумано (17 голосов) - 9.2% Такой язык не нужен, т.к. нейросети могут всё (8 голосов) - 3.45% Свой вариант написал в комменатрии (3 голоса) Проголосовали 87 пользователей. Воздержались 62 пользователя.\n","categories":"","description":"","excerpt":"\nНекоторое время назад я писал про «Интернациональное программирование …","ref":"/ru/blog/logic-prog/","tags":"","title":"Проблема логических языков программирования"},{"body":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag предыдущей версии.\nАктуальную версию синтаксиса языка можно посмотреть тут.\nВ последнее время часто попадаются на глаза статьи о новых языках программирования, а так же различные рейтинги и прогнозы, связанные с популярностью компьютерных языков.\nЗаявляют о себе и новые инструментальные средства, которые в своей работе используют собственные форматы описания конфигурационных файлов или последовательности выполняемых команд, которые так же очень сильно приближает их к понятию «язык программирования».\nЦель написания данной статьи — формулировка ожиданий и возможной реализации абстрактного языка программирования, который может стать универсальным инструментом для общения между компьютером и человеком.\nО программистах Если начинать с самого начала, то когда-то давно я слышал перефразированное высказывание, «каждый программист должен написать свою базу данных, текстовый редактор и язык программирования». И если первые две вещи я уже давным давно написал, то с языком программирования пока не сложилось.\nВедь как обычно создаются языки программирования?\nУ каждого программиста всегда есть какой-то своей предыдущий опыт:\nзнания одного или нескольких языков программирования (как же без этого) негативный опыт от их использования (в противном случае, если все устраивает, то зачем придумывать что-то новое?) желания получить новые возможности (когда в существующих языках чего-то не хватает) А перед тем, как описывать синтаксис, выбирать ключевые слова и начинать основную работу: лексер, парсер, базовые библиотеки, нужно дать ответ на основные вопросы:\nКомпилятор/интерпретатор/транспилятор(transpiler)? Статическая или динамическая типизация? Ручное управление памятью или автоматическое со сборщиком мусора? Модель программирования: ООП, функциональное, структурное или что-то новое? Разрешены ли вставки из других языков программирования и т. д.? У меня, наверно, как и у большинства читателей, присутствует опыт использования нескольких языков программирования. Поэтому давно сложилось практика, что для решения задачи лучше взять известный язык или даже выучить новый, вместо того, чтобы начинать писать собственный.\nТем более, что не хочется придумывать еще один язык просто ради галочки или ради самого языка. Я считаю, что цель его создания должна быть за пределами потребностей самого разработчика.\nИ мне кажется, что удалось определить область, для которой разработка языка программирования может быть востребованной, а потраченные на него усилия могут принести реальную пользу.\nО не программистах Эта область — программирование для «не программистов» на «естественном» языке. Я специально взял слова «не программистов» и «естественном» в кавычки, т.к. эти термины являются очень условными.\nВедь если не программист начинает программировать, то сам того не осознавая, он автоматически становится программистом ;-). А «естественным» язык программирования быть не может по определению. Точнее для компьютеров скорее всего «естественным» будет язык Assembler или набор машинных команд.\nПоэтому, цель максимум — приблизить язык программирования к естественному человеческому языку.\nЭто не только сделает чтение текста программы более понятным для не профессионалов, но и позволит начинать составлять программы просто освоив письменную речь, используя самый минимум основных правил.\nНо в подобной формулировке кроется очень большая проблема!\nЛюбой язык программирования является интернациональным, т.к. его синтаксис не зависит от естественного языка, на котором общается программист.\nА если текст программы будет на “естественном” языке, то она станет понятной только для знающих этот язык, одновременно становясь непонятной для всех остальных.\nВ качестве иллюстрации: раз или два. Если пофантазировать насчет хотелок к такому языку, то видятся следующие требования и ограничения:\nТак как каждый пользователь является носителем своего родного естественного языка (или даже нескольких), то жестко задавать ключевые слова невозможно, из чего следует, что основой такого языка должны стать только правила пунктуации, но никак не лексика или грамматика. Компилятор/транслятор должен уметь преобразовывать исходный текст программы не только в машинный код для компьютера, но в другой вариант “естественного” языка, чтобы пользователь мог работать с исходным текстом на известном ему “естественном” языке. Очень хочется видеть в новом языке толерантность терпимость к очепяткам. Подобная «фича» присутствует в письме на естественном языке, и несмотря на наличие опечаток, практически всегда сохраняется смысл. Естественно, в данном случае не стоит доходить до фанатизма. Компилятор не читает мысли и не может в действительности «понять», что имел ввиду пользователь, и все же довольно часто можно игнорировать опечатки в тексте программы исходя из контекста (пусть и с выводом предупреждающих сообщений). Тем не менее, такой язык должен оставаться именно языком программирования со всеми возможностями создания программ любого уровня сложности, включая функциональное и объектно-ориентированное программирование и однозначное понимание написанного.\nО гипотетическом языке Если взять за основу правила письменной речи, то основные соглашения и пунктуация для нового языка могут выглядеть примерно так:\nЛюбой текст состоит из предложений и комментариев. Предложения обрабатываются, а комментарии игнорируются. Предложение состоит из последовательности терминов, литералов и символов, разделенных пробелами и знаками препинания и завершается символом конца предложения. Термин — слитно написанная последовательность букв, цифр и символов “:” и “_”. Литерал — константы, включаемые непосредственно в текст программы, тип которой определяется однозначно. Это символьные строки в кавычках, целые и вещественные числа, и некоторые специальные форматы (время, дата). Символы — все остальное символы, которые не относятся к знакам препинания, пробельным символам, цифрам и буквам. Знаки препинания — символы пунктуации, имеющие специальное значение при разборе текста программы: «.»,«;»,«!»,«?»,«…» — конец предложения. «=» — присвоение значения. \"\" (кавычки) — определение символьной строки. «()» - передача параметров/аргументов или группировка операторов для определения приоритета выполнения операций. «[]» - массив или обращение к элементу массива. «{}» - включение в текст исходного кода программы на обычном языке программирования. «$» — системная переменная. «@» — системная функция. «,» (запятая) — перечисление. «:» (двоеточие) — список или логическая связь. Если с символом присвоения, кавычками, круглыми и квадратными скобками все должно быть более-менее понятно, т.к. их назначение соответствует аналогичному в подавляющем большинстве языков программирования, то про назначение остальных символов (фигурных скобок, двоеточия, запятой и системных функций/переменной), следует немного пояснить.\nРаз цель гипотетического языка программирования все же написание программ, то необходимо предусмотреть возможность делать вставки обычного программного кода без учета всех возможностей и неоднозначностей, которые присущи любому естественному языку.\nТак же эта возможность требуется для реализации низкоуровневых функций и для взаимодействия с внешними библиотеками.\nПри создании подобных вставок и могут использоваться фигурные скобки, весь текст между которыми будет вставляться в итоговый файл практически без обработки.\nДля похожих целей служат и символы «$» — системная переменная и «@» — системная функция. Если такой символ поставить в начале слова, тогда он станет обозначать объект с соответствующим назначением. Например «@exit» — будет означать функцию, а «$var» — переменную с соответствующими именами, а сами объекты станут доступны как в обычном коде, так и в программных вставках внутри фигурных скобок.\nАналогичным образом организуется и доступ к отдельным полям/методам объектов: «объект@метод» или «объект$поле».\nСимвол запятая «,» применяется для указание последовательности равноправных логических блоков в одном предложении или для создания списков.\nСимвол двоеточия «:» используется для создания списков и для обозначения логической связи между двумя частями слова/текста, в том числе для указания полного пути модуля.\nНапример, создание списка:\nВ_строку: элемент 1, элемент 2, последний элемент.\nФорматированный_список: - элемент 1; - элемент 2; - последний элемент. Логическое следствие/указание связи:\nmodule:calc //термин «calc», который находится в модуле «module» super:module:example$var //переменная «$var» которая находится в указанной иерархии. Как можно заметить, использование знаков препинания взято из их прямого назначения, принятого в письменной речи, что должно обеспечить определенный компромисс между синтаксисом в стандартных языках программирования и письмом на естественном языке.\nО компьютерах Так как речь идет все же о языке программирования, то не обойтись без стандартных алгоритмических конструкций: следования, ветвления и циклов.\nСледование легко описывается обычными правилам письма на естественном языке. В случае последовательного выполнения в одном предложении, операции и вызовы функций записываются последовательно через запятую. Если они располагаются в разных предложениях, то они записываются так же друг за другом. Причем форматирование по абзацам служит только для лучшего восприятия текста и логического разделения отдельных фрагментов.\nПри создании условных и циклических управляющих конструкций уже потребуются ключевые слова. Но так как согласно исходным пожеланиям к языку, резервировать обычные термины для записи алгоритмических конструкций нельзя, то перед ключевыми словами достаточно указывать символ системной функции, что позволит отличить обычный термин от ключевого (управляющего) слова.\nЕстественно, при программировании, данными терминами хоть и можно будет пользоваться, но делать это совсем не обязательно. Так как при настройке под конкретный естественный язык, системным функциям и ключевым словам нужно обязательно присвоить конкретные термины и пользоваться уже ими, например:\nперейти = @goto, метка = @label, продолжить = @continue, прервать=@break и т.д. И последняя по очереди, но наверно самая важная по сути конструкция: передача параметров при вызовах функций. Если стремиться к полностью естественному синтаксису, тогда мы получим тот самый естественный язык, который очень сложно анализировать.\nТем не менее, мне кажется, что можно скомбинировать оба два подхода, если отказаться от обязательного использования круглых скобок, там, где это допустимо по синтаксису.\nКомпьютерный: функция(параметр1, функция2(), параметр3=значение). Естественный: функция параметр1 функция2 параметр3=значение. Но:\nКомпьютерный: функция( функция2(параметр) ). Естественный: функция функция2(параметр). Или так: функция (функция2 параметр). Другими словами, для естественного порядка указания аргументов, скобки для функций и запятые между параметрами могут быть опущены. Хотя их использование должно определяться в первую очередь целевым естественным языком, а не синтаксисом.\nО возражениях Предвижу обоснованные возражения против использования подобного языка со стороны программистов. Программа на нем по любому получится значительно многословнее, чем с использованием строгого формального синтаксиса обычных компьютерных языков.\nПоэтому напомню про его обязательное свойство - умение преобразовывать текст программы с одного языка на другой. Это позволяет писать программы как с использованием строго формального синтаксиса без использования переопеределенных терминов на естественном языке, так и преобразовывать исходный текст в “естественный” язык для “не программиста”.\nСсылка на первую публикаци\n","categories":"","description":"","excerpt":"\nВнимание!!!\nДанная статья содержит описание синтаксиса NewLnag …","ref":"/ru/blog/inter-prog/","tags":"","title":"Интернациональное программирование на естественных языках"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/categories/","tags":"","title":"Categories"},{"body":"","categories":"","description":"","excerpt":"","ref":"/categories/","tags":"","title":"Categories"},{"body":" Welcome to the NewLang project website! Documentation Articles Playground GitHub NewLang — NewLang is a general-purpose high-level programming language with a syntax based on a strict system of grammatical rules. But with the help of preprocessor macros, the syntax is turned into DSL based on keywords..\nTensor calculations and rationals of unlimited precision are supported at the level of language syntax and basic data types without the use of additional libraries.\nThe ownership-based memory management model does not require the use of a garbage collector and eliminates major errors at the stage of compiling the source code of the program.\nThe main properties and features: the ability to work both in interpreter and compiler mode* dynamic and static typing with the ability to specify types explicitly static typing is conditionally strong (there is no automatic type casting, but conversion between some data types is allowed. For example, an integer can be automatically converted to real or rational, but not vice versa) automatic memory management without garbage collector* bject-oriented programming in the form of explicit class inheritance and \"duck typing\"* several types of functions (regular and pure functions without side effects) are supported at the syntax level of the language optional and named function arguments direct insertion of C/C++ code is possible* easy integration with existing software libraries (including import of native variables, functions and classes* from C/C++). there is a REPL (read-eval-print loop) symbolic calculations** *) These features are planned for implementation when the compiler is created. **) Symbolic calculations are supported at the syntax level, but not implemented. Why do we need NewLang? All modern programming languages have a constant development (complication) of syntax as new versions are released.\nThis is a kind of payment for the emergence of new features and is perceived by users as a natural process. But at the same time it is also a serious problem, since with the release of versions new keywords and syntactic constructions are added, which inevitably raises the entry threshold for new users. Another consequence of this process is the constant increase in the complexity of developing and supporting already created software products, when the old code is being finalized using the already new standards. NewLang naturally limits the complexity of language constructs by splitting the syntax of the language into two parts, making it easier to learn and use. Basic syntax - for writing programs in object-oriented (imperative) and declarative styles, which is based not on reserved keywords, but on a system of strict grammar rules. It is possible to extend the basic syntax through the use of macros.\nExtended syntax - program inserts in the implementation language (C / C ++), when the main syntax becomes insufficient. Another disadvantage of modern languages is that most of them were created before the era of machine learning, therefore, tensor calculations are performed in the form of separate libraries.\nThe same applies to calculations with unlimited precision, which also require the use of additional library functions. NewLang has tensor calculus and unlimited-precision rationals out of the box.\nThey are supported at the syntax level for writing literals of the corresponding types, and simple arithmetic data types are scalars (tensors of dimension zero).\nThe implementation of tensor calculations is based on the library libtorch, and rational numbers using OpenSSL. Hello world script example in NewLang #!../output/nlc printf('Hello, world!'); Output: Hello, world! 14 An example of calculating factorial 40 on NewLang (base syntax) #!../output/nlc ### Example of calculating factorial of 40 using basic syntax fact := 1\\1; # Rational number 1 (no precision limit) mult := 40..1..-1?; # Iterator from range for factors from 40 to 2 [mult ?!] \u003c-\u003e { # Loop until the iterator data runs out fact *= mult !; # Get the current multiplier and move to the next iterator element }; @assert(fact == 815915283247897734345611269596115894272000000000\\1); fact # Return final result Output: 815915283247897734345611269596115894272000000000\\1 Same code using DSL syntax #!../output/nlc ### Example of calculating factorial 40 using DSL syntax fact := 1\\1; # Rational number 1 (no precision limit) mult := @iter( 40..1..-1 ); # Iterator from range for factors from 40 to 2 @while( @curr(mult)) { # Loop until the iterator data runs out fact *= @next(mult); # Get the current multiplier and move to the next iterator element }; @assert(fact == 815915283247897734345611269596115894272000000000\\1); fact # Return final result Output: 815915283247897734345611269596115894272000000000\\1 More code examples Syntax description All documentation Articles ","categories":"","description":"","excerpt":" Welcome to the NewLang project website! Documentation Articles …","ref":"/","tags":"","title":"NewLang"},{"body":" Добро пожаловать на сайт проекта NewLang! Документация Статьи Playground GitHub NewLang — это язык программирования высокого уровня общего назначения c базовым синтаксисом на основе грамматических правил. С помощью макросов препроцесора, базовый синтаксис легко преобразуется в DSL на основе ключевых слов.\nТензорные вычисления и рациональные числа не ограниченной точности поддерживаются на уровне синтаксиса языка и базовых типов данных без использования дополнительных библиотек.\nМодель управления памятью на основе владения не трубет использования сборщика мусора и исключет основные ошибки еще на этапе компиляции исходного текста программы.\nОсновные свойства и особенности языка: возможность работы как в режиме интерпретатора, так и компилятора* динамическая и статическая типизация с возможностью указания типов в явном виде статическая типизация является условно-строгой (автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных. Например, целое число может быть автоматически преобразовано в вещественное или рациональное, но не наоборот) автоматическое управление памятью без сборщика мусора на основе владения* ООП* в виде явного наследования классов и «утиная типизация» на уровне синтаксиса поддерживается несколько типов функций (обычные и чистые функции без побочных эффектов) необязательные и именованные параметры функций простая интеграция с уже существующими программными библиотеками (в том числе импорт нативных переменных, функций и классов* из С/С++.) имеется REPL (read-eval-print loop — «цикл: чтение — вычисление — вывод») символьные вычисления** *) Данные возможности запланированы к реализации **) Символьные вычисления поддерживаются на уровне синтаксиса, но не реализованы Зачем нужен NewLang? У всех современных языков программирования происходит постоянное развитие (усложнение) синтаксиса по мере выхода новых версий.\nЭто является своего рода платой за появление новых возможностей языка и воспринимается пользователями как естественное явление. Но одновременно является и серьезной проблемой, так как с выходом новых версий языка в него добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для всех новых пользователей. Еще одним следствием этого процесса становится постоянное увеличение сложности разработки и поддержки уже созданных программных продуктов, когда старый программный код дорабатывается с применением уже новых стандартов и постоянным увеличением старого легаси кода. У NewLang сложность языковых конструкций ограничена естественным образом за счет разделения синтаксиса языка на несколько частей, что упрощает его изучение и использование. Основной (базовый) синтаксис — на системе строгих грамматических правил. Синтаксис DSL (domain-specific language) — хотя базовый синтаксис самодостаточен и полснотью покрывает все возможные сценарии использования, но его применение разработчиками напрямую не всегда эффекстивно с точки зрения последующего чтения исходноиков. Поэтому более правильным вариантом написания исходного кода программы будет применение предметно-ориентированного языка, который реализуется с помощью макросов препроцессора и превращает базовый синтаксис на основе грамматических правил в синтаксис на основе ключевых слов. Расширенный синтаксис — программные вставки на языке реализации (С/С++), когда основного или DSL синтаксиса становится недостаточно. Еще одно неудобство современных языков в том, что большинство из них были созданы еще до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек. Это же касается и вычислений с неограниченной точностью, которые также требуют использования дополнительных библиотечных функций. У NewLang тензорные вычисления и рациональные числа неограниченной точности доступны «из коробки». Они поддерживаются на уровне синтаксиса для удобной записи литералов, а простые арифметические типы данных являются скалярами (тензорами нулевой размерности). Реализация тензорных вычислений сделана на базе библиотеки libtorch, а рациональные числа с использованием OpenSSL. Пример скрипта Hello world! на NewLang #!../output/nlc --eval hello(str) := { # Импорт и вызов функции printf стандартной библиотеки printf(format:FmtChar, ...):Int32 := %printf...; printf('call: %s', $str); $str; }; hello('Привет, мир!'); Вывод: call: Привет, мир! Привет, мир! Пример вычисления факториала 40 на NewLang (базовый синтаксис) #!../output/nlc --eval fact := 1\\1; # Рациональное число 1 (без ограничения точности) mult := 40..1..-1?; # Итератор из диапазона для множителей от 40 до 2 [mult ?!] \u003c-\u003e { # Цикл, пока не закончатся данные итератора fact *= mult !; # Получить текущий множитель и перейти на следующий элемент итератора }; fact # Вывести итоговый результат Вывод: 815915283247897734345611269596115894272000000000\\1 Тот же код с использованием DSL синтаксиса #!../output/nlc --eval fact := 1\\1; mult := iter( 40..1..-1 ); while( curr(mult) ) { fact *= next(mult); }; fact; Вывод: 815915283247897734345611269596115894272000000000\\1 Еще примеры кода Описание синтаксиса Вся документация Статьи ","categories":"","description":"","excerpt":" Добро пожаловать на сайт проекта NewLang! Документация Статьи …","ref":"/ru/","tags":"","title":"NewLang"},{"body":"","categories":"","description":"","excerpt":"","ref":"/search/","tags":"","title":"Search Results"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/search/","tags":"","title":"Search Results"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/tags/","tags":"","title":"Tags"},{"body":"","categories":"","description":"","excerpt":"","ref":"/tags/","tags":"","title":"Tags"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/tags/%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B/","tags":"","title":"Итераторы"},{"body":"","categories":"","description":"","excerpt":"","ref":"/tags/%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D1%82%D0%BE%D1%80%D1%8B/","tags":"","title":"Итераторы"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/tags/%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8/","tags":"","title":"Коллекции"},{"body":"","categories":"","description":"","excerpt":"","ref":"/tags/%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8/","tags":"","title":"Коллекции"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/tags/%D0%BE%D0%BE%D0%BF/","tags":"","title":"ООП"},{"body":"","categories":"","description":"","excerpt":"","ref":"/tags/%D0%BE%D0%BE%D0%BF/","tags":"","title":"ООП"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/tags/%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B/","tags":"","title":"Системые Типы"},{"body":"","categories":"","description":"","excerpt":"","ref":"/tags/%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B/","tags":"","title":"Системые Типы"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/tags/%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B8/","tags":"","title":"Строки"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/tags/%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85/","tags":"","title":"Типы Данных"},{"body":"","categories":"","description":"","excerpt":"","ref":"/tags/%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85/","tags":"","title":"Типы Данных"},{"body":"","categories":"","description":"","excerpt":"","ref":"/ru/tags/%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8/","tags":"","title":"Функции"},{"body":"","categories":"","description":"","excerpt":"","ref":"/tags/%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8/","tags":"","title":"Функции"}] \ No newline at end of file diff --git a/docs/playground/_print/index.html b/docs/playground/_print/index.html index 869292ee..b8a62b0e 100644 --- a/docs/playground/_print/index.html +++ b/docs/playground/_print/index.html @@ -91,8 +91,7 @@ </header> <div class="container-fluid td-default td-outer"> <main role="main" class="td-main"> - <p>Примеры программ на NewLang</p> -<style> + <style> .rownr {width: 5%; overflow-y: hidden; background-color: rgb(105,105,105); color: white; text-align: right; vertical-align:top; resize: none;} .txt {width: 90%; overflow-x: scroll; resize: none; font-family: monospace;} @@ -100,6 +99,9 @@ .error {background-color: rgb(255, 180, 180); } .pgbox {margin-top: 4rem;} </style> +<p> +<br> +</p> <div class="pgbox"> <select class="c10" style="width: 95%;" onchange="SelectExample(this);" id="example_list"> <option selected="selected" value="" id="example_start">Select an exmaple...</option> @@ -145,18 +147,6 @@ </div> <script> -if(window.location.search){ - const params = new Proxy(new URLSearchParams(window.location.search), { - get: (searchParams, prop) => searchParams.get(prop), - }); - // Get the value of "src" in eg "https://example.com/?src=source" - if(params.src){ - document.getElementById('playground').value = unescape(params.src); - } - //alert(escape('#!../output/nlc \n\nprint(\'Hello, world!\\n\');\n')); - // %23%21../output/nlc%20%0A%0Aprint%28%27Hello%2C%20world%21%5Cn%27%29%3B%0A -} - locations =[ "", "#!../output/nlc \n\nprint('Hello, world!\\n');\n", "#!../output/nlc \n\nfact := 1\\1; # Rational value support bigint\nmult := @iter(1000..1..-1); # Iterator from range\n@while( @curr(mult) ) {\n fact *= @next(mult);\n};\n\n# Check factorial 1000!\n@assert( fact == 402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\\1 );\n\n# Return result\nfact", @@ -165,14 +155,17 @@ "#!../output/nlc --eval\n\n# Create a tensor and fill it with values. \n# The last value is repeated up to the required tensor size\ntensor := :Single[2,5](-1, 0, 1, 2, 3, ... );\nprint('1: tensor = %s\\n', :StrChar(tensor));\n\nmult := tensor * 10;\nprint('2: tensor *= 10 -> %s\\n', :StrChar(mult));\n\nmult += 11;\nprint('3: tensor += 11 -> %s\\n', :StrChar(mult));\n\n# Import srand function and init random generator\nsrand(seed:Int32):None := %srand ...;\nsrand(100);\n\n# Import rand function to get random values\nrnd():Int32 := %rand ...;\nprint('4: %d, %d, %d, %d\\n', rnd(), rnd(), rnd(), rnd());\n\n# Create a tensor where the rand function is called for every element except the first\nmatrix := :Tensor[10,10]( 0, 42, ... rnd() ...);\nprint('5: matrix = %s\\n', :StrChar(matrix));\n\nmatrix //= 42;\nprint('6: matrix %%= 2 -> %s\\n', :StrChar(matrix));\nprint('7: matrix %%= 2 -> %s\\n', :StrChar(:Bool(matrix)));\n", ]; -function SelectExample(sel){ - - srcLocation = locations[sel.selectedIndex]; - if (srcLocation != undefined && srcLocation != "") { - obj = document.getElementById('playground'); - obj.value = locations[sel.selectedIndex]; - input_changed(obj); - } +function SelectExample(sel){ + obj = document.getElementById('playground'); + if(Number.isInteger(sel) && locations[sel]){ + obj.value = locations[sel]; + } else { + srcLocation = locations[sel.selectedIndex]; + if (srcLocation != undefined && srcLocation != "") { + obj.value = locations[sel.selectedIndex]; + } + } + input_changed(obj); } @@ -327,7 +320,7 @@ clearInterval(downloadTimer); document.getElementById('progress').style.display = "none"; document.getElementById('playground_out').classList.add("error"); - alert("Request failed!"); + alert("Request failed!\n\nCheck the connection protocol!\n\nThe site should open using the regular HTTP protocol without using SSL! Because browsers typically block unsecured connections on HTTPS pages."); }; xhr.ontimeout = (e) => { @@ -336,6 +329,22 @@ alert("Run query timeout!"); }; } + + +if(window.location.search){ + const params = new Proxy(new URLSearchParams(window.location.search), { + get: (searchParams, prop) => searchParams.get(prop), + }); + // Get the value of "src" in eg "https://example.com/?src=source" + if(params.id){ + SelectExample(parseInt(params.id)); + } else if(params.src){ + document.getElementById('playground').value = unescape(params.src); + } + //alert(escape('#!../output/nlc \n\nprint(\'Hello, world!\\n\');\n')); + // %23%21../output/nlc%20%0A%0Aprint%28%27Hello%2C%20world%21%5Cn%27%29%3B%0A +} + </script> </main> <footer class="td-footer row d-print-none"> diff --git a/docs/playground/index.html b/docs/playground/index.html index d36cbc9d..94ab0408 100644 --- a/docs/playground/index.html +++ b/docs/playground/index.html @@ -91,8 +91,7 @@ </header> <div class="container-fluid td-default td-outer"> <main role="main" class="td-main"> - <p>Примеры программ на NewLang</p> -<style> + <style> .rownr {width: 5%; overflow-y: hidden; background-color: rgb(105,105,105); color: white; text-align: right; vertical-align:top; resize: none;} .txt {width: 90%; overflow-x: scroll; resize: none; font-family: monospace;} @@ -100,6 +99,9 @@ .error {background-color: rgb(255, 180, 180); } .pgbox {margin-top: 4rem;} </style> +<p> +<br> +</p> <div class="pgbox"> <select class="c10" style="width: 95%;" onchange="SelectExample(this);" id="example_list"> <option selected="selected" value="" id="example_start">Select an exmaple...</option> @@ -145,18 +147,6 @@ </div> <script> -if(window.location.search){ - const params = new Proxy(new URLSearchParams(window.location.search), { - get: (searchParams, prop) => searchParams.get(prop), - }); - // Get the value of "src" in eg "https://example.com/?src=source" - if(params.src){ - document.getElementById('playground').value = unescape(params.src); - } - //alert(escape('#!../output/nlc \n\nprint(\'Hello, world!\\n\');\n')); - // %23%21../output/nlc%20%0A%0Aprint%28%27Hello%2C%20world%21%5Cn%27%29%3B%0A -} - locations =[ "", "#!../output/nlc \n\nprint('Hello, world!\\n');\n", "#!../output/nlc \n\nfact := 1\\1; # Rational value support bigint\nmult := @iter(1000..1..-1); # Iterator from range\n@while( @curr(mult) ) {\n fact *= @next(mult);\n};\n\n# Check factorial 1000!\n@assert( fact == 402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\\1 );\n\n# Return result\nfact", @@ -165,14 +155,17 @@ "#!../output/nlc --eval\n\n# Create a tensor and fill it with values. \n# The last value is repeated up to the required tensor size\ntensor := :Single[2,5](-1, 0, 1, 2, 3, ... );\nprint('1: tensor = %s\\n', :StrChar(tensor));\n\nmult := tensor * 10;\nprint('2: tensor *= 10 -> %s\\n', :StrChar(mult));\n\nmult += 11;\nprint('3: tensor += 11 -> %s\\n', :StrChar(mult));\n\n# Import srand function and init random generator\nsrand(seed:Int32):None := %srand ...;\nsrand(100);\n\n# Import rand function to get random values\nrnd():Int32 := %rand ...;\nprint('4: %d, %d, %d, %d\\n', rnd(), rnd(), rnd(), rnd());\n\n# Create a tensor where the rand function is called for every element except the first\nmatrix := :Tensor[10,10]( 0, 42, ... rnd() ...);\nprint('5: matrix = %s\\n', :StrChar(matrix));\n\nmatrix //= 42;\nprint('6: matrix %%= 2 -> %s\\n', :StrChar(matrix));\nprint('7: matrix %%= 2 -> %s\\n', :StrChar(:Bool(matrix)));\n", ]; -function SelectExample(sel){ - - srcLocation = locations[sel.selectedIndex]; - if (srcLocation != undefined && srcLocation != "") { - obj = document.getElementById('playground'); - obj.value = locations[sel.selectedIndex]; - input_changed(obj); - } +function SelectExample(sel){ + obj = document.getElementById('playground'); + if(Number.isInteger(sel) && locations[sel]){ + obj.value = locations[sel]; + } else { + srcLocation = locations[sel.selectedIndex]; + if (srcLocation != undefined && srcLocation != "") { + obj.value = locations[sel.selectedIndex]; + } + } + input_changed(obj); } @@ -327,7 +320,7 @@ clearInterval(downloadTimer); document.getElementById('progress').style.display = "none"; document.getElementById('playground_out').classList.add("error"); - alert("Request failed!"); + alert("Request failed!\n\nCheck the connection protocol!\n\nThe site should open using the regular HTTP protocol without using SSL! Because browsers typically block unsecured connections on HTTPS pages."); }; xhr.ontimeout = (e) => { @@ -336,6 +329,22 @@ alert("Run query timeout!"); }; } + + +if(window.location.search){ + const params = new Proxy(new URLSearchParams(window.location.search), { + get: (searchParams, prop) => searchParams.get(prop), + }); + // Get the value of "src" in eg "https://example.com/?src=source" + if(params.id){ + SelectExample(parseInt(params.id)); + } else if(params.src){ + document.getElementById('playground').value = unescape(params.src); + } + //alert(escape('#!../output/nlc \n\nprint(\'Hello, world!\\n\');\n')); + // %23%21../output/nlc%20%0A%0Aprint%28%27Hello%2C%20world%21%5Cn%27%29%3B%0A +} + </script> </main> <footer class="td-footer row d-print-none"> diff --git a/docs/ru/blog/_print/index.html b/docs/ru/blog/_print/index.html index 73800d2b..ede586c2 100644 --- a/docs/ru/blog/_print/index.html +++ b/docs/ru/blog/_print/index.html @@ -132,7 +132,7 @@ <h1 class="title">Статьи</h1> - <li><a href="#pg-24881a51c9b3aaca484fa4a88ded08d7">Релиз языка программрования NewLang 0.4</a></li> + <li><a href="#pg-24881a51c9b3aaca484fa4a88ded08d7">Релиз языка программирования NewLang 0.4</a></li> @@ -286,7 +286,7 @@ <h1 class="title">Статьи</h1> <div class="td-content" style=""> - <h1 id="pg-24881a51c9b3aaca484fa4a88ded08d7">Релиз языка программрования NewLang 0.4</h1> + <h1 id="pg-24881a51c9b3aaca484fa4a88ded08d7">Релиз языка программирования NewLang 0.4</h1> <div class="td-byline mb-4"> @@ -294,17 +294,26 @@ <h1 id="pg-24881a51c9b3aaca484fa4a88ded08d7">Релиз языка програ <time datetime="2023-06-06" class="text-muted">06.06.2023</time> </div> - <p><img alt="КДПВ" src="/ru/blog/langs.jpeg"></p> - - -<div class="pageinfo pageinfo-primary"> -<p>Внимание!!!</p> -<p>&ldquo;nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии.</p> -<p>Актуальную версию синтаксиса языка можно посмотреть <a href="/ru/docs/">тут</a>.</p> - -</div> - -<p>ssssssssssssssssssssssssssssssssssssssssssssss</p> + <h2 id="новые-возможности-и-изменения-в-синтаксисе-newlang">Новые возможности и изменения в синтаксисе NewLang<a class="td-heading-self-link" href="#%d0%bd%d0%be%d0%b2%d1%8b%d0%b5-%d0%b2%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b8-%d0%b8%d0%b7%d0%bc%d0%b5%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b2-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81%d0%b5-newlang" aria-label="Heading self-link"></a></h2> +<ul> +<li>Переработано определение типов объектов с помощью <a href="https://newlang.net/docs/syntax/naming/">префикса имен (сигила)</a></li> +<li>Прерывание потока выполнения и возврат теперь может выполняться для <a href="https://newlang.net/docs/ops/throw/">именованных блоков кода</a>.</li> +<li>Упрощен синтаксис импорта <a href="https://newlang.net/docs/types/native/">нативных переменных и функций (С/С++)</a></li> +<li>Стабилизирован синтаксис для <a href="https://newlang.net/docs/ops/create/#comprehensions">заполнение начальными данными</a> значений тензоров, словарей и аргументов при вызове функций.</li> +<li>Появились встроенные макросы для написания кода с использованием ключевых слов в стиле <a href="https://newlang.net/docs/syntax/dsl/">DSL</a></li> +</ul> +<h2 id="новые-возможности-компилятора-nlc">Новые возможности компилятора (nlc)<a class="td-heading-self-link" href="#%d0%bd%d0%be%d0%b2%d1%8b%d0%b5-%d0%b2%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%82%d0%be%d1%80%d0%b0-nlc" aria-label="Heading self-link"></a></h2> +<ul> +<li>Полностью переделан макропроцессор.</li> +<li>Переработана архитектура компилятора с разделением на парсер, макропроцессор, синтаксический анализатор, интерпретатор и генератор кода.</li> +</ul> +<h2 id="разное">Разное<a class="td-heading-self-link" href="#%d1%80%d0%b0%d0%b7%d0%bd%d0%be%d0%b5" aria-label="Heading self-link"></a></h2> +<ul> +<li><a href="http://newlang.net">Сайт</a> с документацией переведен на <a href="https://gohugo.io/">Hugo</a> и сделан двуязычным.</li> +<li>Вместо бинарных сборок на сайт добавлен раздел <a href="https://newlang.net/playground/">Playground and example code</a> для небольших экспериментов.</li> +<li>Выполнен переход на clang-16 (переход на clang-17 и старше планируется после полной реализации корутин и поддержки расширенных форматов чисел с плавающей запятой).</li> +<li>Количество контрибуторов проекта стало больше одного!</li> +</ul> </div> diff --git a/docs/ru/blog/complex-prog/index.html b/docs/ru/blog/complex-prog/index.html index fdb49207..1243fa0f 100644 --- a/docs/ru/blog/complex-prog/index.html +++ b/docs/ru/blog/complex-prog/index.html @@ -76,7 +76,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/complex-prog/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div></li> </ul> @@ -128,7 +128,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/complex-prog/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div> </div> @@ -137,7 +137,7 @@ <a href="/ru/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-rublog"><span class="">Статьи</span></a> <ul class="ul-1"> <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogrelease-v04-li"> - <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> + <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программирования NewLang 0.4</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogparser-nuances-li"> <a href="/ru/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogdsl-with-macros-li"> diff --git a/docs/ru/blog/dsl-with-macros/index.html b/docs/ru/blog/dsl-with-macros/index.html index 0f0714cb..5e705d6a 100644 --- a/docs/ru/blog/dsl-with-macros/index.html +++ b/docs/ru/blog/dsl-with-macros/index.html @@ -145,7 +145,7 @@ <a href="/ru/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-rublog"><span class="">Статьи</span></a> <ul class="ul-1"> <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogrelease-v04-li"> - <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> + <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программирования NewLang 0.4</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogparser-nuances-li"> <a href="/ru/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child active-path" id="m-rublogdsl-with-macros-li"> diff --git a/docs/ru/blog/index.html b/docs/ru/blog/index.html index f4b5bf35..cb7039c2 100644 --- a/docs/ru/blog/index.html +++ b/docs/ru/blog/index.html @@ -126,7 +126,7 @@ <a href="/ru/blog/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__section tree-root" id="m-rublog"><span class="td-sidebar-nav-active-item">Статьи</span></a> <ul class="ul-1"> <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogrelease-v04-li"> - <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> + <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программирования NewLang 0.4</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogparser-nuances-li"> <a href="/ru/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogdsl-with-macros-li"> @@ -191,7 +191,7 @@ <h5 class="taxonomy-title">Tag Cloud</h5> <ul class="td-blog-posts-list"> <li class="td-blog-posts-list__item"> <div class="td-blog-posts-list__body"> - <h5 class="mt-0 mb-1"><a href="/ru/blog/release-v0.4/">Релиз языка программрования NewLang 0.4</a></h5> + <h5 class="mt-0 mb-1"><a href="/ru/blog/release-v0.4/">Релиз языка программирования NewLang 0.4</a></h5> <p class="mb-2 mb-md-3"><small class="text-muted">06.06.2023 в Статьи</small></p> <header class="article-meta"> @@ -201,13 +201,8 @@ <h5 class="mt-0 mb-1"><a href="/ru/blog/release-v0.4/">Релиз языка п -<p class="pt-0 mt-0"> -Внимание!!! -&ldquo;nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -ssssssssssssssssssssssssssssssssssssssssssssss -</p> - <p class="pt-0"><a href="/ru/blog/release-v0.4/" aria-label="Подробнее - Релиз языка программрования NewLang 0.4">Подробнее</a></p> +<p class="pt-0 mt-0">Новые возможности и изменения в синтаксисе NewLang Переработано определение типов объектов с помощью префикса имен (сигила) Прерывание потока выполнения и возврат теперь может выполняться для именованных блоков кода. Упрощен синтаксис импорта …</p> + <p class="pt-0"><a href="/ru/blog/release-v0.4/" aria-label="Подробнее - Релиз языка программирования NewLang 0.4">Подробнее</a></p> </div> </li> <li class="td-blog-posts-list__item"> diff --git a/docs/ru/blog/index.xml b/docs/ru/blog/index.xml index 155554d0..d8778776 100644 --- a/docs/ru/blog/index.xml +++ b/docs/ru/blog/index.xml @@ -15,7 +15,7 @@ <item> - <title>Blog: Релиз языка программрования NewLang 0.4</title> + <title>Blog: Релиз языка программирования NewLang 0.4</title> <link>http://localhost:1313/ru/blog/release-v0.4/</link> <pubDate>Tue, 06 Jun 2023 00:00:00 +0000</pubDate> @@ -23,17 +23,26 @@ <description> - &lt;p&gt;&lt;img alt=&#34;КДПВ&#34; src=&#34;http://localhost:1313/ru/blog/langs.jpeg&#34;&gt;&lt;/p&gt; - - -&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; -&lt;p&gt;Внимание!!!&lt;/p&gt; -&lt;p&gt;&amp;ldquo;nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии.&lt;/p&gt; -&lt;p&gt;Актуальную версию синтаксиса языка можно посмотреть &lt;a href=&#34;http://localhost:1313/ru/docs/&#34;&gt;тут&lt;/a&gt;.&lt;/p&gt; - -&lt;/div&gt; - -&lt;p&gt;ssssssssssssssssssssssssssssssssssssssssssssss&lt;/p&gt; + &lt;h2 id=&#34;новые-возможности-и-изменения-в-синтаксисе-newlang&#34;&gt;Новые возможности и изменения в синтаксисе NewLang&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bd%d0%be%d0%b2%d1%8b%d0%b5-%d0%b2%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b8-%d0%b8%d0%b7%d0%bc%d0%b5%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b2-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81%d0%b5-newlang&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; +&lt;ul&gt; +&lt;li&gt;Переработано определение типов объектов с помощью &lt;a href=&#34;https://newlang.net/docs/syntax/naming/&#34;&gt;префикса имен (сигила)&lt;/a&gt;&lt;/li&gt; +&lt;li&gt;Прерывание потока выполнения и возврат теперь может выполняться для &lt;a href=&#34;https://newlang.net/docs/ops/throw/&#34;&gt;именованных блоков кода&lt;/a&gt;.&lt;/li&gt; +&lt;li&gt;Упрощен синтаксис импорта &lt;a href=&#34;https://newlang.net/docs/types/native/&#34;&gt;нативных переменных и функций (С/С++)&lt;/a&gt;&lt;/li&gt; +&lt;li&gt;Стабилизирован синтаксис для &lt;a href=&#34;https://newlang.net/docs/ops/create/#comprehensions&#34;&gt;заполнение начальными данными&lt;/a&gt; значений тензоров, словарей и аргументов при вызове функций.&lt;/li&gt; +&lt;li&gt;Появились встроенные макросы для написания кода с использованием ключевых слов в стиле &lt;a href=&#34;https://newlang.net/docs/syntax/dsl/&#34;&gt;DSL&lt;/a&gt;&lt;/li&gt; +&lt;/ul&gt; +&lt;h2 id=&#34;новые-возможности-компилятора-nlc&#34;&gt;Новые возможности компилятора (nlc)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bd%d0%be%d0%b2%d1%8b%d0%b5-%d0%b2%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%82%d0%be%d1%80%d0%b0-nlc&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; +&lt;ul&gt; +&lt;li&gt;Полностью переделан макропроцессор.&lt;/li&gt; +&lt;li&gt;Переработана архитектура компилятора с разделением на парсер, макропроцессор, синтаксический анализатор, интерпретатор и генератор кода.&lt;/li&gt; +&lt;/ul&gt; +&lt;h2 id=&#34;разное&#34;&gt;Разное&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%80%d0%b0%d0%b7%d0%bd%d0%be%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; +&lt;ul&gt; +&lt;li&gt;&lt;a href=&#34;http://newlang.net&#34;&gt;Сайт&lt;/a&gt; с документацией переведен на &lt;a href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt; и сделан двуязычным.&lt;/li&gt; +&lt;li&gt;Вместо бинарных сборок на сайт добавлен раздел &lt;a href=&#34;https://newlang.net/playground/&#34;&gt;Playground and example code&lt;/a&gt; для небольших экспериментов.&lt;/li&gt; +&lt;li&gt;Выполнен переход на clang-16 (переход на clang-17 и старше планируется после полной реализации корутин и поддержки расширенных форматов чисел с плавающей запятой).&lt;/li&gt; +&lt;li&gt;Количество контрибуторов проекта стало больше одного!&lt;/li&gt; +&lt;/ul&gt; </description> </item> diff --git a/docs/ru/blog/inter-prog/index.html b/docs/ru/blog/inter-prog/index.html index da9624dd..7fd04c88 100644 --- a/docs/ru/blog/inter-prog/index.html +++ b/docs/ru/blog/inter-prog/index.html @@ -84,7 +84,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/inter-prog/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div></li> </ul> @@ -136,7 +136,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/inter-prog/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div> </div> @@ -145,7 +145,7 @@ <a href="/ru/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-rublog"><span class="">Статьи</span></a> <ul class="ul-1"> <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogrelease-v04-li"> - <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> + <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программирования NewLang 0.4</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogparser-nuances-li"> <a href="/ru/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogdsl-with-macros-li"> diff --git a/docs/ru/blog/lang-final/index.html b/docs/ru/blog/lang-final/index.html index f5ee814e..63b7d898 100644 --- a/docs/ru/blog/lang-final/index.html +++ b/docs/ru/blog/lang-final/index.html @@ -80,7 +80,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/lang-final/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div></li> </ul> @@ -132,7 +132,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/lang-final/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div> </div> @@ -141,7 +141,7 @@ <a href="/ru/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-rublog"><span class="">Статьи</span></a> <ul class="ul-1"> <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogrelease-v04-li"> - <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> + <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программирования NewLang 0.4</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogparser-nuances-li"> <a href="/ru/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogdsl-with-macros-li"> diff --git a/docs/ru/blog/logic-prog/index.html b/docs/ru/blog/logic-prog/index.html index 47fbe087..e632aee2 100644 --- a/docs/ru/blog/logic-prog/index.html +++ b/docs/ru/blog/logic-prog/index.html @@ -72,7 +72,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/logic-prog/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div></li> </ul> @@ -124,7 +124,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/logic-prog/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div> </div> @@ -133,7 +133,7 @@ <a href="/ru/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-rublog"><span class="">Статьи</span></a> <ul class="ul-1"> <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogrelease-v04-li"> - <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> + <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программирования NewLang 0.4</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogparser-nuances-li"> <a href="/ru/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogdsl-with-macros-li"> diff --git a/docs/ru/blog/newlang/index.html b/docs/ru/blog/newlang/index.html index 5605d394..ebbd7dff 100644 --- a/docs/ru/blog/newlang/index.html +++ b/docs/ru/blog/newlang/index.html @@ -84,7 +84,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/newlang/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div></li> </ul> @@ -136,7 +136,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/newlang/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div> </div> @@ -145,7 +145,7 @@ <a href="/ru/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-rublog"><span class="">Статьи</span></a> <ul class="ul-1"> <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogrelease-v04-li"> - <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> + <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программирования NewLang 0.4</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogparser-nuances-li"> <a href="/ru/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogdsl-with-macros-li"> diff --git a/docs/ru/blog/page/2/index.html b/docs/ru/blog/page/2/index.html index bdb8b05c..fea9fac7 100644 --- a/docs/ru/blog/page/2/index.html +++ b/docs/ru/blog/page/2/index.html @@ -126,7 +126,7 @@ <a href="/ru/blog/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__section tree-root" id="m-rublog"><span class="td-sidebar-nav-active-item">Статьи</span></a> <ul class="ul-1"> <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogrelease-v04-li"> - <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> + <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программирования NewLang 0.4</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogparser-nuances-li"> <a href="/ru/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogdsl-with-macros-li"> diff --git a/docs/ru/blog/parser-nuances/index.html b/docs/ru/blog/parser-nuances/index.html index 6583bc91..3e463f21 100644 --- a/docs/ru/blog/parser-nuances/index.html +++ b/docs/ru/blog/parser-nuances/index.html @@ -76,7 +76,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/parser-nuances/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div></li> </ul> @@ -128,7 +128,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/parser-nuances/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div> </div> @@ -137,7 +137,7 @@ <a href="/ru/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-rublog"><span class="">Статьи</span></a> <ul class="ul-1"> <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogrelease-v04-li"> - <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> + <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программирования NewLang 0.4</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child active-path" id="m-rublogparser-nuances-li"> <a href="/ru/blog/parser-nuances/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__page" id="m-rublogparser-nuances"><span class="td-sidebar-nav-active-item">Нюансы разработки парсера для своего языка программирования</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogdsl-with-macros-li"> @@ -315,7 +315,7 @@ <h2 id="самое-главное-при-разработке-грамматик <a href="/ru/blog/dsl-with-macros/" aria-label="Предыдущая - Вариант реализации DSL (domain-specific language) с помощью макросов" class="btn btn-primary"><span class="me-1">←</span>Предыдущая</a> </li> <li> - <a href="/ru/blog/release-v0.4/" aria-label="Следующая - Релиз языка программрования NewLang 0.4" class="btn btn-primary">Следующая<span class="ms-1">→</span></a> + <a href="/ru/blog/release-v0.4/" aria-label="Следующая - Релиз языка программирования NewLang 0.4" class="btn btn-primary">Следующая<span class="ms-1">→</span></a> </li> </ul> diff --git a/docs/ru/blog/prog-styles-same-time/index.html b/docs/ru/blog/prog-styles-same-time/index.html index db859133..546d0ba6 100644 --- a/docs/ru/blog/prog-styles-same-time/index.html +++ b/docs/ru/blog/prog-styles-same-time/index.html @@ -80,7 +80,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/prog-styles-same-time/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div></li> </ul> @@ -132,7 +132,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/prog-styles-same-time/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div> </div> @@ -141,7 +141,7 @@ <a href="/ru/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-rublog"><span class="">Статьи</span></a> <ul class="ul-1"> <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogrelease-v04-li"> - <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> + <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программирования NewLang 0.4</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogparser-nuances-li"> <a href="/ru/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogdsl-with-macros-li"> diff --git a/docs/ru/blog/release-v0.1/index.html b/docs/ru/blog/release-v0.1/index.html index b99f8fd9..79fecff7 100644 --- a/docs/ru/blog/release-v0.1/index.html +++ b/docs/ru/blog/release-v0.1/index.html @@ -84,7 +84,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/release-v0.1/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div></li> </ul> @@ -136,7 +136,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/release-v0.1/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div> </div> @@ -145,7 +145,7 @@ <a href="/ru/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-rublog"><span class="">Статьи</span></a> <ul class="ul-1"> <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogrelease-v04-li"> - <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> + <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программирования NewLang 0.4</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogparser-nuances-li"> <a href="/ru/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogdsl-with-macros-li"> diff --git a/docs/ru/blog/release-v0.2/index.html b/docs/ru/blog/release-v0.2/index.html index 2cde5ec1..e7e8f149 100644 --- a/docs/ru/blog/release-v0.2/index.html +++ b/docs/ru/blog/release-v0.2/index.html @@ -84,7 +84,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/release-v0.2/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div></li> </ul> @@ -136,7 +136,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/release-v0.2/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div> </div> @@ -145,7 +145,7 @@ <a href="/ru/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-rublog"><span class="">Статьи</span></a> <ul class="ul-1"> <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogrelease-v04-li"> - <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> + <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программирования NewLang 0.4</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogparser-nuances-li"> <a href="/ru/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogdsl-with-macros-li"> diff --git a/docs/ru/blog/release-v0.3/index.html b/docs/ru/blog/release-v0.3/index.html index b016af43..ae2c0eb7 100644 --- a/docs/ru/blog/release-v0.3/index.html +++ b/docs/ru/blog/release-v0.3/index.html @@ -84,7 +84,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/release-v0.3/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div></li> </ul> @@ -136,7 +136,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/release-v0.3/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div> </div> @@ -145,7 +145,7 @@ <a href="/ru/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-rublog"><span class="">Статьи</span></a> <ul class="ul-1"> <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogrelease-v04-li"> - <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> + <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программирования NewLang 0.4</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogparser-nuances-li"> <a href="/ru/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogdsl-with-macros-li"> diff --git a/docs/ru/blog/release-v0.4/index.html b/docs/ru/blog/release-v0.4/index.html index f02fd504..f2bee55c 100644 --- a/docs/ru/blog/release-v0.4/index.html +++ b/docs/ru/blog/release-v0.4/index.html @@ -17,32 +17,20 @@ <link rel="icon" type="image/png" href="/favicons/android-144x144.png" sizes="144x144"> <link rel="icon" type="image/png" href="/favicons/android-192x192.png" sizes="192x192"> -<title>Релиз языка программрования NewLang 0.4 | NewLang</title> -<meta name="description" content="Внимание!!! -&amp;ldquo;nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -ssssssssssssssssssssssssssssssssssssssssssssss"> -<meta property="og:title" content="Релиз языка программрования NewLang 0.4" /> -<meta property="og:description" content="Внимание!!! -&ldquo;nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -ssssssssssssssssssssssssssssssssssssssssssssss" /> +<title>Релиз языка программирования NewLang 0.4 | NewLang</title> +<meta name="description" content="Новые возможности и изменения в синтаксисе NewLang Переработано определение типов объектов с помощью префикса имен (сигила) Прерывание потока выполнения и возврат теперь может выполняться для именованных блоков кода. Упрощен синтаксис импорта нативных переменных и функций (С/С&#43;&#43;) Стабилизирован синтаксис для заполнение начальными данными значений тензоров, словарей и аргументов при вызове функций. Появились встроенные макросы для написания кода с использованием ключевых слов в стиле DSL Новые возможности компилятора (nlc) Полностью переделан макропроцессор. Переработана архитектура компилятора с разделением на парсер, макропроцессор, синтаксический анализатор, интерпретатор и генератор кода."> +<meta property="og:title" content="Релиз языка программирования NewLang 0.4" /> +<meta property="og:description" content="Новые возможности и изменения в синтаксисе NewLang Переработано определение типов объектов с помощью префикса имен (сигила) Прерывание потока выполнения и возврат теперь может выполняться для именованных блоков кода. Упрощен синтаксис импорта нативных переменных и функций (С/С&#43;&#43;) Стабилизирован синтаксис для заполнение начальными данными значений тензоров, словарей и аргументов при вызове функций. Появились встроенные макросы для написания кода с использованием ключевых слов в стиле DSL Новые возможности компилятора (nlc) Полностью переделан макропроцессор. Переработана архитектура компилятора с разделением на парсер, макропроцессор, синтаксический анализатор, интерпретатор и генератор кода." /> <meta property="og:type" content="article" /> <meta property="og:url" content="http://localhost:1313/ru/blog/release-v0.4/" /><meta property="article:section" content="blog" /> <meta property="article:published_time" content="2023-06-06T00:00:00+00:00" /> <meta property="article:modified_time" content="2024-03-22T23:57:08+03:00" /><meta property="og:site_name" content="NewLang" /> -<meta itemprop="name" content="Релиз языка программрования NewLang 0.4"> -<meta itemprop="description" content="Внимание!!! -&ldquo;nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -ssssssssssssssssssssssssssssssssssssssssssssss"><meta itemprop="datePublished" content="2023-06-06T00:00:00+00:00" /> +<meta itemprop="name" content="Релиз языка программирования NewLang 0.4"> +<meta itemprop="description" content="Новые возможности и изменения в синтаксисе NewLang Переработано определение типов объектов с помощью префикса имен (сигила) Прерывание потока выполнения и возврат теперь может выполняться для именованных блоков кода. Упрощен синтаксис импорта нативных переменных и функций (С/С&#43;&#43;) Стабилизирован синтаксис для заполнение начальными данными значений тензоров, словарей и аргументов при вызове функций. Появились встроенные макросы для написания кода с использованием ключевых слов в стиле DSL Новые возможности компилятора (nlc) Полностью переделан макропроцессор. Переработана архитектура компилятора с разделением на парсер, макропроцессор, синтаксический анализатор, интерпретатор и генератор кода."><meta itemprop="datePublished" content="2023-06-06T00:00:00+00:00" /> <meta itemprop="dateModified" content="2024-03-22T23:57:08+03:00" /> -<meta itemprop="wordCount" content="18"> -<meta itemprop="keywords" content="" /><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Релиз языка программрования NewLang 0.4"/> -<meta name="twitter:description" content="Внимание!!! -&ldquo;nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии. -Актуальную версию синтаксиса языка можно посмотреть тут. -ssssssssssssssssssssssssssssssssssssssssssssss"/> +<meta itemprop="wordCount" content="136"> +<meta itemprop="keywords" content="" /><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Релиз языка программирования NewLang 0.4"/> +<meta name="twitter:description" content="Новые возможности и изменения в синтаксисе NewLang Переработано определение типов объектов с помощью префикса имен (сигила) Прерывание потока выполнения и возврат теперь может выполняться для именованных блоков кода. Упрощен синтаксис импорта нативных переменных и функций (С/С&#43;&#43;) Стабилизирован синтаксис для заполнение начальными данными значений тензоров, словарей и аргументов при вызове функций. Появились встроенные макросы для написания кода с использованием ключевых слов в стиле DSL Новые возможности компилятора (nlc) Полностью переделан макропроцессор. Переработана архитектура компилятора с разделением на парсер, макропроцессор, синтаксический анализатор, интерпретатор и генератор кода."/> @@ -141,7 +129,7 @@ <a href="/ru/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-rublog"><span class="">Статьи</span></a> <ul class="ul-1"> <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child active-path" id="m-rublogrelease-v04-li"> - <a href="/ru/blog/release-v0.4/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="td-sidebar-nav-active-item">Релиз языка программрования NewLang 0.4</span></a> + <a href="/ru/blog/release-v0.4/" class="align-left ps-0 active td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="td-sidebar-nav-active-item">Релиз языка программирования NewLang 0.4</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogparser-nuances-li"> <a href="/ru/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogdsl-with-macros-li"> @@ -180,7 +168,16 @@ </div> - + <div class="td-toc"> + <nav id="TableOfContents"> + <ul> + <li><a href="#новые-возможности-и-изменения-в-синтаксисе-newlang">Новые возможности и изменения в синтаксисе NewLang</a></li> + <li><a href="#новые-возможности-компилятора-nlc">Новые возможности компилятора (nlc)</a></li> + <li><a href="#разное">Разное</a></li> + </ul> +</nav> + </div> + <div class="taxonomy taxonomy-terms-cloud taxo-tags"> <h5 class="taxonomy-title">Tag Cloud</h5> <ul class="taxonomy-terms"> @@ -202,7 +199,7 @@ <h5 class="taxonomy-title">Tag Cloud</h5> </a> <div class="td-content"> - <h1>Релиз языка программрования NewLang 0.4</h1> + <h1>Релиз языка программирования NewLang 0.4</h1> <div class="td-byline mb-4"> @@ -211,17 +208,26 @@ <h1>Релиз языка программрования NewLang 0.4</h1> <header class="article-meta"> </header> - <p><img alt="КДПВ" src="/ru/blog/langs.jpeg"></p> - - -<div class="pageinfo pageinfo-primary"> -<p>Внимание!!!</p> -<p>&ldquo;nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии.</p> -<p>Актуальную версию синтаксиса языка можно посмотреть <a href="/ru/docs/">тут</a>.</p> - -</div> - -<p>ssssssssssssssssssssssssssssssssssssssssssssss</p> + <h2 id="новые-возможности-и-изменения-в-синтаксисе-newlang">Новые возможности и изменения в синтаксисе NewLang<a class="td-heading-self-link" href="#%d0%bd%d0%be%d0%b2%d1%8b%d0%b5-%d0%b2%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b8-%d0%b8%d0%b7%d0%bc%d0%b5%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b2-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81%d0%b5-newlang" aria-label="Heading self-link"></a></h2> +<ul> +<li>Переработано определение типов объектов с помощью <a href="https://newlang.net/docs/syntax/naming/">префикса имен (сигила)</a></li> +<li>Прерывание потока выполнения и возврат теперь может выполняться для <a href="https://newlang.net/docs/ops/throw/">именованных блоков кода</a>.</li> +<li>Упрощен синтаксис импорта <a href="https://newlang.net/docs/types/native/">нативных переменных и функций (С/С++)</a></li> +<li>Стабилизирован синтаксис для <a href="https://newlang.net/docs/ops/create/#comprehensions">заполнение начальными данными</a> значений тензоров, словарей и аргументов при вызове функций.</li> +<li>Появились встроенные макросы для написания кода с использованием ключевых слов в стиле <a href="https://newlang.net/docs/syntax/dsl/">DSL</a></li> +</ul> +<h2 id="новые-возможности-компилятора-nlc">Новые возможности компилятора (nlc)<a class="td-heading-self-link" href="#%d0%bd%d0%be%d0%b2%d1%8b%d0%b5-%d0%b2%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%82%d0%be%d1%80%d0%b0-nlc" aria-label="Heading self-link"></a></h2> +<ul> +<li>Полностью переделан макропроцессор.</li> +<li>Переработана архитектура компилятора с разделением на парсер, макропроцессор, синтаксический анализатор, интерпретатор и генератор кода.</li> +</ul> +<h2 id="разное">Разное<a class="td-heading-self-link" href="#%d1%80%d0%b0%d0%b7%d0%bd%d0%be%d0%b5" aria-label="Heading self-link"></a></h2> +<ul> +<li><a href="http://newlang.net">Сайт</a> с документацией переведен на <a href="https://gohugo.io/">Hugo</a> и сделан двуязычным.</li> +<li>Вместо бинарных сборок на сайт добавлен раздел <a href="https://newlang.net/playground/">Playground and example code</a> для небольших экспериментов.</li> +<li>Выполнен переход на clang-16 (переход на clang-17 и старше планируется после полной реализации корутин и поддержки расширенных форматов чисел с плавающей запятой).</li> +<li>Количество контрибуторов проекта стало больше одного!</li> +</ul> <ul class="list-unstyled d-flex justify-content-between align-items-center mb-0 pt-5"> <li> diff --git a/docs/ru/blog/unusual-prog/index.html b/docs/ru/blog/unusual-prog/index.html index 87afee06..aefbe075 100644 --- a/docs/ru/blog/unusual-prog/index.html +++ b/docs/ru/blog/unusual-prog/index.html @@ -80,7 +80,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/unusual-prog/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div></li> </ul> @@ -132,7 +132,7 @@ <div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Русский</a> <ul class="dropdown-menu"> - <li><a class="dropdown-item" href="/blog/unusual-prog/">English</a></li> + <li><a class="dropdown-item" href="/">English</a></li> </ul> </div> </div> @@ -141,7 +141,7 @@ <a href="/ru/blog/" class="align-left ps-0 td-sidebar-link td-sidebar-link__section tree-root" id="m-rublog"><span class="">Статьи</span></a> <ul class="ul-1"> <li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogrelease-v04-li"> - <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программрования NewLang 0.4</span></a> + <a href="/ru/blog/release-v0.4/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogrelease-v04"><span class="">Релиз языка программирования NewLang 0.4</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogparser-nuances-li"> <a href="/ru/blog/parser-nuances/" class="align-left ps-0 td-sidebar-link td-sidebar-link__page" id="m-rublogparser-nuances"><span class="">Нюансы разработки парсера для своего языка программирования</span></a> </li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id="m-rublogdsl-with-macros-li"> diff --git a/docs/ru/docs/_print/index.html b/docs/ru/docs/_print/index.html index 1829fe78..5ac31f9e 100644 --- a/docs/ru/docs/_print/index.html +++ b/docs/ru/docs/_print/index.html @@ -447,42 +447,6 @@ <h1 class="title">Документация</h1> <div class="content"> <p>Основные материалы по языку программирования NewLang.</p> <p>Описание акутально для текущей версии 4.0</p> -<p>clang-17 не поддерживает:</p> -<table> -<thead> -<tr> -<th>Feature</th> -<th>Proposal</th> -<th>Available</th> -</tr> -</thead> -<tbody> -<tr> -<td>Coroutines</td> -<td>P0912R5</td> -<td><em>Partial</em> Fully supported on all targets except Windows, which still has some stability and ABI issues.</td> -</tr> -<tr> -<td>Extended floating-point types and standard names</td> -<td>P1467R9</td> -<td>No</td> -</tr> -<tr> -<td>Concepts</td> -<td>P0848R3</td> -<td>Clang 16 (Partial)</td> -</tr> -<tr> -<td>Modules</td> -<td></td> -<td>No</td> -</tr> -</tbody> -</table> -<h3 id="начиная-с-c-should-adopt-the-same-characters-for-c26">Начиная с C++ should adopt the same characters for C++26.<a class="td-heading-self-link" href="#%d0%bd%d0%b0%d1%87%d0%b8%d0%bd%d0%b0%d1%8f-%d1%81-c-should-adopt-the-same-characters-for-c26" aria-label="Heading self-link"></a></h3> -<ul> -<li>Add <strong>@</strong>, <strong>$</strong>, and ` to the basic character set P2558R2 Yes</li> -</ul> </div> </div> @@ -502,7 +466,7 @@ <h3 id="начиная-с-c-should-adopt-the-same-characters-for-c26">Начин -<div class="td-content" style="page-break-before: always"> +<div class="td-content" style=""> <h1 id="pg-b5bb7377324fcfd7c83c1943bfd4e128">1 - Синтаксис</h1> <div class="lead">Правила синтаксиса и основные понятия языка программирования NewLang</div> @@ -1101,7 +1065,8 @@ <h3 id="пример-программы">Пример программы<a class <h1 id="pg-66431dc9242fce562d24bb69bdc576f3">1.5 - Макросы</h1> - <p>Макросы в <strong>NewLang</strong>, это один или несколько последовательных терминов, которые заменяются на другой термин + <p>Макросы используются и для превращеня исходного кода <em>NewLang</em> в более привычный синтаксис на основе <a href="https://newlang.net/syntax_dsl.html">ключевых слов</a>, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода.</p> +<p>Макросы в <strong>NewLang</strong>, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем).</p> <p>Макросы обработываются во время работы <strong>лексера</strong>, т.е. перед передачей последовательности лексем в парсер, что позволяет с помощью маросов изменять фрагменты синтаксиса языка, например, при реализации собственных диалектов DSL.</p> @@ -1136,13 +1101,13 @@ <h3 id="определение-макросов">Определение макр с одинаковыми именами, один из которых будет с аргументами (скобками), а другой без них.</p> <p>Поэтому, если требуется использовать макрос в двух разных вариантах (с аргументами и без оных), следует определять макрос без аргументов и в этом случае контроль параметров будет выполнятся компилятором.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> @@macro@@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Макрос без аргументов</span> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> @@ macro @@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Макрос без аргументов</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> macro<span style="color:#ce5c00;font-weight:bold">(</span>args<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># ОК -&gt; term(args);</span> </span></span><span style="display:flex;"><span> macro<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># ОК -&gt; term;</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Но </span> -</span></span><span style="display:flex;"><span> @@call<span style="color:#ce5c00;font-weight:bold">()</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> @@ call<span style="color:#ce5c00;font-weight:bold">()</span> @@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> call<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># ОК -&gt; term();</span> </span></span><span style="display:flex;"><span> call<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Ошибка (@call определен с аргументами) </span> @@ -1155,286 +1120,49 @@ <h3 id="определение-макросов">Определение макр <p>По аналогии с препроцессором С/С++, для соединения двух лексем в одну, в теле макроса используется оператор <strong>&quot;@##&quot;</strong>, а для преобразование лексемы в текстову строку применяется операторы <strong>@#</strong>, <strong>@#&quot;</strong> или <strong>@#&rsquo;</strong>, например, <code>@@macro($arg)@@ := @@ func_ @## @$arg( @#&quot; arg ) @;</code>, тогда вызов <code>macro(name);</code> будет преобразован в <code>func_name (&quot;name&quot;);</code></p> - - -<div class="pageinfo pageinfo-primary"> -<h4 id="ограничения-макропроцессора-в-текущей-версии">Ограничения макропроцессора в текущей версии<a class="td-heading-self-link" href="#%d0%be%d0%b3%d1%80%d0%b0%d0%bd%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d0%bf%d1%80%d0%be%d1%86%d0%b5%d1%81%d1%81%d0%be%d1%80%d0%b0-%d0%b2-%d1%82%d0%b5%d0%ba%d1%83%d1%89%d0%b5%d0%b9-%d0%b2%d0%b5%d1%80%d1%81%d0%b8%d0%b8" aria-label="Heading self-link"></a></h4> -<p>На текущий момент макросы реализованы в минимальном объеме для самых простых сценариев использования:</p> -<ul> -<li>DSL для keyword based syntax (if, else, return, match, while и т.д.) - (1 термин с произвольными аргументами и без) - требуется сейчас !!!</li> -</ul> -<p><em>Парсер при обработке макросов может анализировать информацию о типах данных, если она указана.</em> -<em>Но на текущий момент типы данных в макросах никак не обрабатываются и это одна из обязательных фич, которая будет реализована в будущем.</em></p> -<ul> -<li>Определения (func, class) - (несколько терминов с аргументами и без аргументов) - Реализация ООП и импорт С++ классов</li> -<li>Модификации при определениях (override) - (несколько терминов и шаблоны с аргументами и без аргументов) - Реализация ООП и импорт С++ классов</li> -</ul> - -</div> - -<h1 id="макросы-без-аргументов-или-все-аргументы-сразу-">МАКРОСЫ БЕЗ АРГУМЕНТОВ ИЛИ ВСЕ АРГУМЕНТЫ СРАЗУ !!!!!<a class="td-heading-self-link" href="#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b1%d0%b5%d0%b7-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d0%b8%d0%bb%d0%b8-%d0%b2%d1%81%d0%b5-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d1%8b-%d1%81%d1%80%d0%b0%d0%b7%d1%83-" aria-label="Heading self-link"></a></h1> -<h1 id="анализа-аргументов-или-их-типов-не-производится-">анализа аргументов или их типов не производится !!!<a class="td-heading-self-link" href="#%d0%b0%d0%bd%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d0%b8%d0%bb%d0%b8-%d0%b8%d1%85-%d1%82%d0%b8%d0%bf%d0%be%d0%b2-%d0%bd%d0%b5-%d0%bf%d1%80%d0%be%d0%b8%d0%b7%d0%b2%d0%be%d0%b4%d0%b8%d1%82%d1%81%d1%8f-" aria-label="Heading self-link"></a></h1> -<p>Lambda -@@ lambda $name(&hellip;) @@ ::= @@ @$name( @$&hellip; ) ::= ( _( @$&hellip; ) ::= @<strong>PRAGMA_FINALIZE</strong>( @), {, {+, {-, {* ) @@</p> -<h3 id="примеры-использования-макросов">Примеры использования макросов<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80%d1%8b-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2" aria-label="Heading self-link"></a></h3> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Обычные макросы (тело макроса корректное выражение)</span> -</span></span><span style="display:flex;"><span> @@macro@@ :<span style="color:#ce5c00;font-weight:bold">=</span> replace<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@macro2<span style="color:#ce5c00;font-weight:bold">(</span>arg<span style="color:#ce5c00;font-weight:bold">)</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">{</span> call<span style="color:#ce5c00;font-weight:bold">(</span>@<span style="color:#000">$arg</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> call<span style="color:#ce5c00;font-weight:bold">()}</span><span style="color:#000;font-weight:bold">;</span> +<p>Примеры использования макросов:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Обычные макросы (тело макроса корректное выражение)</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000">macro</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000">replace</span><span style="color:#000;font-weight:bold">();</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000">macro2</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">arg</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000;font-weight:bold">{</span> <span style="color:#000">call</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#a40000">$</span><span style="color:#000">arg</span><span style="color:#000;font-weight:bold">);</span> <span style="color:#000">call</span><span style="color:#000;font-weight:bold">()};</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Тело макросов из последовательности лексем</span> -</span></span><span style="display:flex;"><span> @@if<span style="color:#ce5c00;font-weight:bold">(</span>...<span style="color:#ce5c00;font-weight:bold">)</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ <span style="color:#ce5c00;font-weight:bold">[</span> <span style="color:#4e9a06">\$</span><span style="color:#204a87;font-weight:bold">if</span><span style="color:#ce5c00;font-weight:bold">(</span>*<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">]</span>--&gt; @@<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Выражение может быть не полным</span> -</span></span><span style="display:flex;"><span> @@elif<span style="color:#ce5c00;font-weight:bold">(</span>...<span style="color:#ce5c00;font-weight:bold">)</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ ,<span style="color:#ce5c00;font-weight:bold">[</span> <span style="color:#4e9a06">\$</span><span style="color:#204a87;font-weight:bold">elif</span><span style="color:#ce5c00;font-weight:bold">(</span>*<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">]</span>--&gt; @@<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@else@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ ,<span style="color:#ce5c00;font-weight:bold">[</span>_<span style="color:#ce5c00;font-weight:bold">]</span>--&gt; @@<span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#204a87;font-weight:bold">if</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000;font-weight:bold">[</span> <span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#a40000">$</span><span style="color:#ce5c00;font-weight:bold">...</span> <span style="color:#000;font-weight:bold">]</span><span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#ce5c00;font-weight:bold">@@</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Выражение может быть не полным</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#204a87;font-weight:bold">elif</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000;font-weight:bold">,[</span> <span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#a40000">$</span><span style="color:#ce5c00;font-weight:bold">...</span> <span style="color:#000;font-weight:bold">]</span><span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#ce5c00;font-weight:bold">@@</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000;font-weight:bold">,[</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">]</span><span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#ce5c00;font-weight:bold">@@</span><span style="color:#000;font-weight:bold">;</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Запись условного оператора с использованием </span> </span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># определенных выше макросов</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">if</span><span style="color:#ce5c00;font-weight:bold">(</span> condition <span style="color:#ce5c00;font-weight:bold">){</span> -</span></span><span style="display:flex;"><span> ... -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">elif</span><span style="color:#ce5c00;font-weight:bold">(</span> condition2 <span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> ... -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#ce5c00;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> ... -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>Зачем нужна трансформация синтаксиса? -Нативная поддержка других языков нужна чтобы не переписывать легаси код на этих языках.</p> -<p>Чтобы можно было использовать существующие исходники как собственные требуется настройка работы -препроцессора и лексера под конкретный язык программирования (описание DSL). -Для <strong>С/С++</strong> потребуется выделять лексером комментарии из-за пересечения синтаксиса (которые сейчас игнорируются). -Для <strong>Python</strong> требуется выделять лексером отступы (которые сейчас тоже игнорируются), причем потребуется реализация не только синтаксиса, -но и зависимых пакетов с последующая трансляцией этого кода в С++, что в настоящий момент делать не целесообразно (cython ???).</p> -<p>Но так как возможность трансформации кода с других языков программирования принципиальная возможна, -стоит над этим думать только после полноценного релиза NewLang и его перехода в прод.</p> -<p>Для реализации DSL требуется передача команд в парсер для управления его работой (по аналогии с командой #pragma) -Но так как обработка таких команд должна происходить в лексере до передачи данных в парсер (анализатор), -то команды для макропроцессора должны быть в максимально простом виде и состоять из элементов, -которые лексер может самостоятельно идентифицировать, т.е. термины, строки и цифры (без выражений и именованных аргументов).</p> -<p>После обработки такой команды она анализируется макропроцессором и удаляется из потока лексем, т.е. в парсер (анализатор) не передается. -Но в случае ошибки с синтаксисе, данные команды нужно уметь однозначно идентифировать и самый простой способ, -комбинация признака макроса и системного имени, т.е. что-то вроде</p> -<pre tabindex="0"><code> @__PRAGMA_DIAG__(push) - @__PRAGMA_DIAG__(ignored, &#34;-Wundef&#34;) - @__PRAGMA_DIAG__(warning, &#34;-Wformat&#34;) - @__PRAGMA_DIAG__(error &#34;-Wuninitialized&#34;) - @__PRAGMA_DIAG__(pop) - - #pragma message &#34;Compiling &#34; __FILE__ &#34;...&#34; - @__PRAGMA_MESSAGE__(&#34;Compiling &#34;, __FILE__, &#34;...&#34;) - - #pragma error &#34;Error &#34; __FILE__ &#34;...&#34; - @__PRAGMA_ERROR__(&#34;Error &#34;, __FILE__, &#34;...&#34;) - - -#define DO_PRAGMA(x) _Pragma (#x) -#define TODO(x) DO_PRAGMA(message (&#34;TODO - &#34; #x)) - -@@TODO( ... )@@ := @__PRAGMA_MESSAGE__(&#34;TODO - &#34;, @*) - -@TODO(Remember to fix this) # note: TODO - Remember to fix this - -\\.__lexer__ignore_space__ = 1; -\\.__lexer__ignore_indent__ = 1; -\\.__lexer__ignore_comment__ = 1; -\\.__lexer__ignore_crlf__ = 1; -</code></pre><p>Таким образом можно трансформировать условный оператор на питоне в синтаксис NewLang следующим макросом:</p> -<pre tabindex="0"><code> -#pragma clang attribute push -#pragma clang diagnostic ignored &#34;-Wundef&#34; -#pragma clang diagnostic ignored &#34;-Wunused-variable&#34; - - -#elif __GNUC__ - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored &#34;-Wuninitialized&#34; - -#pragma GCC diagnostic ignored &#34;-Wall&#34; -#pragma GCC diagnostic ignored &#34;-Wextra&#34; - - @pragma warning(pop) - - @@ pragma warning(...) @@ := __PRAGMA_TERM_DIAG_WARNING__(); -@__PRAGMA_DIAG__(warning, pop); +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@if</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">condition</span> <span style="color:#000;font-weight:bold">){</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">...</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> <span style="color:#5c35cc;font-weight:bold">@elif</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">condition2</span> <span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">...</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> <span style="color:#5c35cc;font-weight:bold">@else</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">...</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span></code></pre></div><p>Например цикл до 5:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">[</span> <span style="color:#0000cf;font-weight:bold">1</span> <span style="color:#000;font-weight:bold">]</span> <span style="color:#ce5c00;font-weight:bold">&lt;-&gt;</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">[</span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#0000cf;font-weight:bold">5</span> <span style="color:#000;font-weight:bold">]</span> <span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">--</span> <span style="color:#0000cf;font-weight:bold">42</span> <span style="color:#ce5c00;font-weight:bold">--</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span><span style="display:flex;"><span> <span style="color:#000">count</span><span style="color:#ce5c00;font-weight:bold">+=</span><span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span></code></pre></div><p>Будет выглядеть более привычно:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@while</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">true</span> <span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@if</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#0000cf;font-weight:bold">5</span> <span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@return</span> <span style="color:#0000cf;font-weight:bold">42</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span><span style="display:flex;"><span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">+=</span> <span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span></code></pre></div> -Обработка терминов в макропроцессоре в максимально простом виде. -Агрументы только термины, строки и цифры без вложенных выражений и именованных аргументов, -т.е. только элементы, которые может самостоятельно идентифицировать лексер. +<div class="pageinfo pageinfo-primary"> +<h3 id="далее-идеи-на-будущее">Далее идеи на будущее<a class="td-heading-self-link" href="#%d0%b4%d0%b0%d0%bb%d0%b5%d0%b5-%d0%b8%d0%b4%d0%b5%d0%b8-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5" aria-label="Heading self-link"></a></h3> +<h3 id="символьное-программирование">Символьное программирование<a class="td-heading-self-link" href="#%d1%81%d0%b8%d0%bc%d0%b2%d0%be%d0%bb%d1%8c%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> -@warning(&#34;--&#34;) - @@ if ... : @@ := @@ [ @$* ]-&gt; __TERM_BLOCK_INDENT__(&#34;{&#34;, force_semicolon=1) @@ - - if __name__ == &#34;__main__&#34;: - run1() - run2() +</div> - [ __name__ == &#34;__main__&#34; ]-&gt; { - run1(); - run2(); - }; - - -</code></pre><p>Ключ &ndash;parser-syntax-only только текстовый парсинг исходного кода без загрузки модулей, раскрытия макросов и проверки имен.</p> -<p>Ключ &ndash;parser-no-macros - без раскрытия макросов -Ключ &ndash;parser-no-module - без загрузки модулей (и мокросов, если они в них определяются) -Ключ &ndash;parser-no-check-prototype - без проверки имен при обращении</p> -<p>prototype -@<strong>PRAGMA_PROTOTYPE</strong>(define) -@<strong>PRAGMA_PROTOTYPE</strong>(implement)</p> -<p>$$</p> -<p>\$ - корень системы (система)</p> -<p>$ - текущий модуль</p> -<h1 id="макросы-для-конвертора-проверки-в-python">Макросы для конвертора проверки в Python<a class="td-heading-self-link" href="#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b4%d0%bb%d1%8f-%d0%ba%d0%be%d0%bd%d0%b2%d0%b5%d1%80%d1%82%d0%be%d1%80%d0%b0-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b8-%d0%b2-python" aria-label="Heading self-link"></a></h1> -<h1 id="if-__name__--__main__">if <strong>name</strong> == &ldquo;<strong>main</strong>&rdquo;:<a class="td-heading-self-link" href="#if-__name__--__main__" aria-label="Heading self-link"></a></h1> -<p>@@ <strong>name</strong> @@ ::= @@ $. @<strong>PRAGMA_NO_MACRO</strong>() <strong>name</strong> @@ -@@ if $&hellip; @: @@ ::= @@ [ @$&hellip; ] &ndash;&gt; @@</p> -<p>@if( $.<strong>name</strong> == &ldquo;<strong>main</strong>&rdquo; ) {</p> -<p>}</p> -<p>\каталог\модуль() - статический импорт модуля -\(&ldquo;каталог\модуль&rdquo;)() - динамический импорт модуля</p> -<p>printf := :Pointer(&lsquo;printf(format:FmtChar, &hellip;):Int32&rsquo;); -printf := %printf(format:FmtChar, &hellip;):Int32;</p> -<h1 id="регистрация-прототипа-нативной-функции">Регистрация прототипа нативной функции<a class="td-heading-self-link" href="#%d1%80%d0%b5%d0%b3%d0%b8%d1%81%d1%82%d1%80%d0%b0%d1%86%d0%b8%d1%8f-%d0%bf%d1%80%d0%be%d1%82%d0%be%d1%82%d0%b8%d0%bf%d0%b0-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h1> -<p>@prototype -%puts(format:StrChar):Int32;</p> -<h1 id="импорт-нативной-функции-с-предварительной-проверкой-её-наличия-во-время-компиляции-статическая-линковка">Импорт нативной функции с предварительной проверкой её наличия во время компиляции (статическая линковка)<a class="td-heading-self-link" href="#%d0%b8%d0%bc%d0%bf%d0%be%d1%80%d1%82-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d1%81-%d0%bf%d1%80%d0%b5%d0%b4%d0%b2%d0%b0%d1%80%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d0%be%d0%b9-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%be%d0%b9-%d0%b5%d1%91-%d0%bd%d0%b0%d0%bb%d0%b8%d1%87%d0%b8%d1%8f-%d0%b2%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d1%8f-%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%86%d0%b8%d0%b8-%d1%81%d1%82%d0%b0%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bb%d0%b8%d0%bd%d0%ba%d0%be%d0%b2%d0%ba%d0%b0" aria-label="Heading self-link"></a></h1> -<p>puts2(format:StrChar):Int32 := %puts(format:StrChar):Int32;</p> -<h1 id="импорт-нативной-функции-по-её-прототипу-во-время-выполнения-динамическая-линковка">Импорт нативной функции по её прототипу во время выполнения (динамическая линковка)<a class="td-heading-self-link" href="#%d0%b8%d0%bc%d0%bf%d0%be%d1%80%d1%82-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d0%bf%d0%be-%d0%b5%d1%91-%d0%bf%d1%80%d0%be%d1%82%d0%be%d1%82%d0%b8%d0%bf%d1%83-%d0%b2%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d1%8f-%d0%b2%d1%8b%d0%bf%d0%be%d0%bb%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b4%d0%b8%d0%bd%d0%b0%d0%bc%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bb%d0%b8%d0%bd%d0%ba%d0%be%d0%b2%d0%ba%d0%b0" aria-label="Heading self-link"></a></h1> -<p>puts3(format:StrChar):Int32 := :Pointer(&lsquo;puts(format:StrChar):Int32&rsquo;);</p> -<p>%puts(&lsquo;Тест вывода строки&rsquo;); # Линковка с нативной функцией во время компиляции и непосредственный вызов с оптимизацией передачи параметров -puts2(&lsquo;Тест 2 вывода строки&rsquo;); # Линковка с нативной функцией во время компиляции -puts3(&lsquo;Тест 3 вывода строки&rsquo;); # Линковка с нативной функцией во время выполнения при первом вызове puts3</p> -<ul> -<li>Парсинг исходного текста без раскрытия макросов и загрузки модулей</li> -<li>Парсинг исходного текста с раскрытием макросов (требуется загрузка модулей для зависимых и переопределяемых макросов)</li> -<li>Загружатся модули могут как в виде исходников (которые требуется парсить и компилировть/выполнять) -или в виде бинарников (в них должны быть список макросов, типов и имена объектов)</li> -<li>После парсинга получается список <strong>имен</strong> макросов, типов и объектов (TermPtr)</li> -<li>После выполнения модуля - список <strong>имен</strong> заполняется реальными объектами (ObjPtr).</li> -</ul> -<h1 id="компиляция-файла">Компиляция файла<a class="td-heading-self-link" href="#%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%86%d0%b8%d1%8f-%d1%84%d0%b0%d0%b9%d0%bb%d0%b0" aria-label="Heading self-link"></a></h1> -<ul> -<li>Парсинг исходника для построения AST (без анализа имен, связей, загрузки модулей и пр. только исходые тексты с раскрытием макросов</li> -<li></li> -</ul> -<h1 id="систематизация-реализации-макросов">Систематизация реализации макросов<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0%d1%82%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d1%80%d0%b5%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d0%b8-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2" aria-label="Heading self-link"></a></h1> -<p>последовательность лексем MACRO_SEQ мужду @@ @@ сохраняется в m_block, так как фрагменты блоков не могут быть идентификаторами</p> -<p>Разбор макросов происходит в лексере. Определением макроса всегда является целая строка, -которая заканчивается точкой с запятой, а идентификатором макроса всегда выступает последовательность лексем:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> @@ id @@ :<span style="color:#ce5c00;font-weight:bold">=</span> macro<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@ id @@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ @@<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@ id @@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@@ @@@<span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>Хранилищем текущих максросов является объект класса MacroBuffer. -Последовательность лексем идентификатора (id) макроса должна сохраняется в отдельном поле термина и однозначно его идентифицирует. -Первый термин в идентификаторе хранится как ключ hashmap, а дальше происходит поиск полным перебором. -Этапы работы с макросами</p> -<ul> -<li> -<p>Входные термины из лексера получаются вызовом GetNextToken, внутри которой и происходит раскрытие макросов. -Внутренний буфер заполняется до окончания строки (выражения), т.е. до символа &lsquo;;&rsquo; или <END>, после чего производится -поиск макросов в объекте MacroBuffer для текущей последовательности лексем в буфере.</p> -</li> -<li> -<p>Если макрос найден, то соответствющая ему последоваетльность заменяется на тело макроса и происходит переход -на повторный анализ входного буфера.</p> -</li> -<li> -<p>Если макрос не найден, то данные передаются в парсер для дальнейшего синтаксическго анализа.</p> -</li> -<li> -<p>Для этого во входном потоке лексем (parser.y) во время оператората создания/присвоения вызывается функция проверки на макрос. -MacroBuffer::CheckMacroAndConvertDel($$), и после этого выходному значению присваивается результат выполнения driver.MacroEval($$), -и в дальнейшем этот макрос никак не обработывается.</p> -</li> -<li> -<p>Создание макросов, проверка на дубликаты и логические ошибки в определении происходит путем обращения к методам объекта MacroBuffer.</p> -<p>/*</p> -<ul> -<li>Макросы хрянтся как фрагменты AST в виде объектов типа Term,</li> -<li>так как создаются после обработки парсером по правилам стандратной грамматики.</li> -<li></li> -<li>Но анализ входных данных на предмет раскрытия макросов проиходит из потока (последовательности) лексем,</li> -<li>т.е. <strong>ДО</strong> обработки парсером, так как при раскрытии макросов может меняться грамматика выражений.</li> -<li></li> -<li>Функция \ref CompareMacro сравнивает входной буфер (последовательность лексем)</li> -<li>на предмет возможного соответствия одному конкретному макросу.</li> -<li>Сравниваются только ключевые словам без учета аргументов в скобках,</li> -<li>но само наличие аргументов проверяется ??????????????????</li> -<li></li> -<li>Проблема:</li> -<li>К функции можно обратится с целью её вызова (указав после имени скобки),</li> -<li>так и по имени без скобок (например для получения ссылки на объект).</li> -<li>Так и к переменной можно обратиться только по имени,</li> -<li>так и указав скобки после имени как к функции (при копировании объекта).</li> -<li></li> -<li>Сделать один макрос под оба сценария (со скобками и без скобок) не получится, так как непонятно,</li> -<li>что делать с аргументами при раскрытии тела макроса, когда они не указаны.</li> -<li></li> -<li>Но может быть следует переименовывать только одно имя без учета скобок,</li> -<li>например, оставив такую возможность только для одиночных макросов.</li> -<li></li> -<li>\name -&gt; name или name (&hellip;), hash: name</li> -<li>но \name(&hellip;) -&gt; name(&hellip;), а name - ошибка !!!! hash: name</li> -<li></li> -<li>Или все же следует различать макросы со скобками и без скобок как два разных объекта???</li> -<li>\name := name2; и \name(&hellip;) := name2(&hellip;); будут разными объектами</li> -<li></li> -<li>Или добавить макросы-алиасы без аргументов только для переименования отдельных терминов?</li> -<li>\alias :- name2; но как их отличать от обычных макросов в операции удаления?</li> -<li>Или вообще не нужно отличать и оставить только один варинат (либо макрос, либо алиас)</li> -<li>Тода вопрос со скобками закрывается сам собой, алиасы всегда без скобок,</li> -<li>макросы со скбками или без скобок, но должно быть полное соответствие.</li> -<li></li> -<li>@ name name2 @ -&gt; name name2, но name name2(&hellip;) - ошибка!!! (hash: name,name2)</li> -<li>@ name name2(&hellip;) @ -&gt; name name2(&hellip;), но name name2 - ошибка !!!! (hash: name,name2)</li> -<li>@ name name2<a href="...">&hellip;</a> @ -&gt; name name2<a href="...">&hellip;</a>, но name name2 - ошибка !!!! ( hash: name,name2 )</li> -<li>@ name $tmpl<a href="...">&hellip;</a> name3@ -&gt; name $tmpl<a href="...">&hellip;</a> name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )</li> -<li></li> -<li>Но!</li> -<li>@ name name2 @ ::- -&gt; name name2 - ок, но name name2(&hellip;) - ок</li> -<li>@ name $tmpl name3@ ::- -&gt; name $tmpl<a href="...">&hellip;</a> name3 - ок, name $tmpl(&hellip;) name3[&hellip;] - ок</li> -<li></li> -<li></li> -<li></li> -<li>Для последовательности лексем требуется полное соответствие с учетом скобок ???</li> -<li>и может ли быть несколько скобок одного типа (несколько крыглях, или несколько квардратных????</li> -<li>&lt;Может быть несколько скобок одного типа, например, при указании типа у аргументов или типа возвращаемого значения.&gt;</li> -<li></li> -<li>@ name name2 @ -&gt; name name2, но name name2(&hellip;) - ошибка!!! (hash: name,name2)</li> -<li>@ name name2(&hellip;) @ -&gt; name name2(&hellip;), но name name2 - ошибка !!!! (hash: name,name2)</li> -<li>@ name name2<a href="...">&hellip;</a> @ -&gt; name name2<a href="...">&hellip;</a>, но name name2 - ошибка !!!! ( hash: name,name2 )</li> -<li>@ name $tmpl<a href="...">&hellip;</a> name3@ -&gt; name $tmpl<a href="...">&hellip;</a> name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )</li> -<li></li> -<li>Проблема скобок возникает из-за сценария замены одного термина на другой,</li> -<li>который есть в препроцессоре С/С++, но отсутствует при реализации с использованием шаблонов.</li> -<li></li> -<li></li> -</ul> -<p>*/</p> -</li> -</ul> -<p>Макросы используются и для превращеня исходного кода <em>NewLang</em> в более привычный синтаксис на основе <a href="https://newlang.net/syntax_dsl.html">ключевых слов</a>, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода.</p> -<p><a href="https://newlang.net/syntax_dsl.html">Например:</a>.</p> -<pre tabindex="0"><code> @@if(...)@@ ::= @@ [ \$* ]--&gt; @@; - @@while(...)@@ ::= @@ [\$*] &lt;-&gt; @@; - @@return $arg@@::= @@ -- \$arg -- @@; - @@true@@ ::= 1; -</code></pre><p>Тогда цикл до 5:</p> -<pre tabindex="0"><code>count:=1; -[ 1 ] &lt;-&gt; { - [count&gt;5] --&gt; { - -- 42 --; - }; - count+=1; -}; -</code></pre><p>будет выглядеть более привычно</p> -<pre tabindex="0"><code>count:=1; -while( true ) { - if(count&gt;5) { - return 42; - }; - count+=1; -}; -</code></pre><h2 id="идеи-на-будущее">Идеи на будущее<a class="td-heading-self-link" href="#%d0%b8%d0%b4%d0%b5%d0%b8-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5" aria-label="Heading self-link"></a></h2> -<h3 id="символьное-программирование">Символьное программирование<a class="td-heading-self-link" href="#%d1%81%d0%b8%d0%bc%d0%b2%d0%be%d0%bb%d1%8c%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> <blockquote> <p>Символьное программирование, часто называемое декларативным программированием, представляет собой парадигму программирования, которая использует математическую логику, отношения и символы для представления знаний и помощи в решении проблем. Вместо того, чтобы сосредотачиваться на описании последовательности операций, необходимых для выполнения вычислений, как в императивном программировании, символическое программирование делает упор на выражении отношений и ограничений между структурами данных, уделяя особое внимание «что», а не «как».</p> <p>В контексте парадигм программирования символическое программирование часто противопоставляется процедурному или императивному программированию, где программы определяют пошаговые процедуры для достижения своих целей. В то время как императивное программирование фокусируется на описании потока управления с использованием таких конструкций, как циклы и условные выражения, для управления выполнением, символическое программирование сосредоточено на выражении фактов о проблеме и позволяет выполнению естественным образом выводить последующие последствия из предоставленной информации.</p> @@ -2165,195 +1893,105 @@ <h2 id="предопределенные-макросы">Предопредел <h1 id="pg-8e386bb5b373d09fe8bcbec82c31b73f">1.9 - Keyword syntax (DSL)</h1> - <h2 id="dsl">DSL<a class="td-heading-self-link" href="#dsl" aria-label="Heading self-link"></a></h2> -<h3 id="особенности-ассоциативной-памяти">Особенности ассоциативной памяти<a class="td-heading-self-link" href="#%d0%be%d1%81%d0%be%d0%b1%d0%b5%d0%bd%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b0%d1%81%d1%81%d0%be%d1%86%d0%b8%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8" aria-label="Heading self-link"></a></h3> + <h3 id="особенности-ассоциативной-памяти">Особенности ассоциативной памяти<a class="td-heading-self-link" href="#%d0%be%d1%81%d0%be%d0%b1%d0%b5%d0%bd%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b0%d1%81%d1%81%d0%be%d1%86%d0%b8%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8" aria-label="Heading self-link"></a></h3> <p>Синтаксис языка <em>NewLang</em> основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например <strong>if</strong>, чем комбинация <em>минус минус правая угловая скобка</em> <strong>&ndash;&gt;</strong>. Из-за этого имеет смысл использовать не &ldquo;чистый&rdquo; базовый синтаксис, а более привычный диалект с использованием ключевых слов.</p> -<h3 id="синтаксис-на-ключевых-словах">Синтаксис на ключевых словах<a class="td-heading-self-link" href="#%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81-%d0%bd%d0%b0-%d0%ba%d0%bb%d1%8e%d1%87%d0%b5%d0%b2%d1%8b%d1%85-%d1%81%d0%bb%d0%be%d0%b2%d0%b0%d1%85" aria-label="Heading self-link"></a></h3> -<p>В файле dsl.nlp находится набор макросов, которые расширяют базовый синтаксис <em>NewLang</em>, основанный на правилах, -набором предопределенных ключевых слов как в классических языках программирования. -А при необходимости, их можно адаптировать или дополнить под собственную предметную область.</p> -<h2 id="константы">Константы<a class="td-heading-self-link" href="#%d0%ba%d0%be%d0%bd%d1%81%d1%82%d0%b0%d0%bd%d1%82%d1%8b" aria-label="Heading self-link"></a></h2> -<h3 id="логические">Логические<a class="td-heading-self-link" href="#%d0%bb%d0%be%d0%b3%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> +<p><em>NewLang</em> уже содержит набор макросов, которые расширяют базовый синтаксис <em>NewLang</em>, основанный на правилах, +набором предопределенных ключевых слов как в классических языках программирования, +которые можно адаптировать или дополнить под собственную предметную область.</p> +<h3 id="константы">Константы<a class="td-heading-self-link" href="#%d0%ba%d0%be%d0%bd%d1%81%d1%82%d0%b0%d0%bd%d1%82%d1%8b" aria-label="Heading self-link"></a></h3> <ul> -<li><strong>true</strong> - 1</li> -<li><strong>yes</strong> - 1</li> -<li><strong>false</strong> - 0</li> -<li><strong>no</strong> - 0</li> +<li> +<p><em>@true</em> - 1</p> +</li> +<li> +<p><em>@yes</em> - 1</p> +</li> +<li> +<p><em>@false</em> - 0</p> +</li> +<li> +<p><em>@no</em> - 0</p> +</li> +<li> +<p><em>@this</em> или <em>@self</em> - Текущий объект</p> +</li> +<li> +<p><em>@super</em> - Родительский объект</p> +</li> +<li> +<p><em>@latter</em> или <em>@last</em>- Результат выполенения последнего оператора Result of the last operation</p> +</li> </ul> -<h3 id="системные-имена">Системные имена<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%8b%d0%b5-%d0%b8%d0%bc%d0%b5%d0%bd%d0%b0" aria-label="Heading self-link"></a></h3> +<h3 id="логические-операторы">Логические операторы<a class="td-heading-self-link" href="#%d0%bb%d0%be%d0%b3%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b" aria-label="Heading self-link"></a></h3> <ul> -<li><strong>this</strong> - Текущий объект (<strong>$0</strong>)</li> -<li><strong>parent</strong> - Родительский объект (<strong>$$</strong>)</li> -<li><strong>last</strong> - Результат выполнения последнего оператора (<strong>$^</strong>)</li> +<li><em>@and</em> - Логическое <strong>И</strong></li> +<li><em>@or</em> - Логическое <strong>ИЛИ</strong></li> +<li><em>@xor</em> - Логическое <strong>Исключающее ИЛИ</strong></li> +<li><em>@not(value)</em> - Логическое отрицание</li> </ul> -<p>!!!!!!!!- <strong>args</strong> - Все аргументы функции (<strong>$*</strong>)</p> -<p>!!!!!!!!- <strong>sys</strong> - Системный контекст запущенной программы (<strong>@@</strong>) -!!!!!!!!- <strong>current</strong> - Текущий модуль (<strong>@$</strong>) -!!!!!!!!- <strong>cmd</strong> - Все аргументы выполняющегося приложения из командной строки (<strong>@*</strong>)</p> -<p>!!!!!!!!!!1### Типовые функции и проверки -!!!!!!!!!!- <strong>run(&lsquo;filename&rsquo;)</strong> - Выполнить указанный файл (<strong>@@(&lsquo;filename&rsquo;)</strong>) -!!!!!!!!!!- <strong>ifmain</strong> - Проверка, если текущий модуль основной (<strong>[@$.$0] &ndash;&gt;</strong> { &hellip; }) -!!!!!!!!!!- <strong>ifload</strong> - Проверка, если текущий модуль загружается впервые (<strong>[@$.<strong>load</strong>] &ndash;&gt;</strong> { &hellip; })</p> <h3 id="операторы">Операторы<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b" aria-label="Heading self-link"></a></h3> <ul> <li> -<p><strong>match(cond)</strong> - Оператор <a href="https://newlang.net/ops.html#%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B0-%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F">оценки выражения</a></p> +<p><em>@if(&hellip;)</em> - Первый условный оператор</p> </li> <li> -<p><strong>if(&hellip;)</strong> - Первый условный оператор (<strong>[$*]&ndash;&gt;</strong> { &hellip; })</p> +<p><em>@elif(&hellip;)</em> - Второй и все последующие условные операторы</p> </li> <li> -<p><strong>elif(&hellip;)</strong> - Второй и все последующие (<strong>,[$*]&ndash;&gt;</strong> { &hellip; })</p> +<p><em>@else</em> - Оператор <em>иначе</em></p> </li> <li> -<p><strong>else</strong> - Оператор <em>иначе</em> (<strong>,[_]&ndash;&gt;</strong> { &hellip; })</p> +<p><em>@while(&hellip;)</em> - Оператор цикла с предусловием</p> </li> <li> -<p><strong>while(cond)</strong> - Оператор цикла с предусловием (<strong>[@$cond] &lt;-&gt;</strong> { &hellip; } )</p> +<p><em>@dowhile(&hellip;)</em> - Оператор цикла с постусловием</p> </li> <li> -<p><strong>dowhile(cond)</strong> - Оператор цикла с постусловием ({ &hellip; } <strong>&lt;-&gt;[@$cond]</strong>)</p> +<p><em>@loop</em> - Оператор безконечного цикла</p> </li> <li> -<p><strong>iter(obj, &hellip; )</strong> - Создание итератора ( <strong>@$obj</strong> ? (@$*) )</p> +<p><em>@break $label</em> - Оператор выхода из именованного именованного блока кода</p> </li> <li> -<p><strong>next(obj, &hellip; )</strong> - Следующий элемент итератора ( <strong>@$obj</strong> ! ($*) )</p> +<p><em>@continue $label</em> - Оператор прехода на начало именованного блока кода</p> </li> <li> -<p><strong>curr(obj, &hellip; )</strong> - Текущий элемент итератора ( <strong>@$obj</strong> !? ($*) )</p> +<p><em>@return( result )</em> - Оператор возврата значения и выхода из функции</p> </li> <li> -<p><strong>first(obj)</strong> - Перейти на первый элемент итератора ( <strong>@$obj</strong> !! )</p> +<p><em>@throw( error )</em> - Оператор создания исключения и возврата ошибки</p> </li> <li> -<p><strong>all(obj)</strong> - Получить сразу все элементы итератора ( <strong>@$obj</strong> ??)</p> +<p><em>@match( &hellip; )</em> - Оператор оценки выражения</p> </li> -</ul> -<h3 id="прерывания">Прерывания<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b5%d1%80%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h3> -<ul> <li> -<p><strong>return</strong> - Положительное прерывание (<strong>++</strong>)</p> +<p><em>@case( &hellip; )</em> - Оператор сравнения с образцом</p> </li> <li> -<p><strong>return(&hellip;)</strong>- Положительное прерывание с возвратом значения (<strong>++</strong> @$value <strong>++</strong>)</p> +<p><em>@default</em> - Оператор выбора по улочанию</p> </li> <li> -<p><strong>error</strong> - Отрицательное прерывание (<strong>--</strong>)</p> +<p><em>@iter(obj, &hellip; )</em> - Создание итератора</p> </li> <li> -<p><strong>error(&hellip;)</strong> - Отрицательное прерывание с возвратом значения (<strong>--</strong> @$value <strong>--</strong>)</p> +<p><em>@next(obj, &hellip; )</em> - Получить следующий элемент итератора</p> </li> <li> -<p><strong>break+</strong> и <strong>break-</strong> - Выход из цикла:</p> +<p><em>@curr(obj, &hellip; )</em> - Получить текущий элемент итератора</p> +</li> +<li> +<p><em>@first(obj)</em> - Перейти на первый элемент итератора</p> +</li> +<li> +<p><em>@all(obj)</em> - Получить сразу все элементы итератора</p> </li> </ul> -<pre tabindex="0"><code> while(...) {+ - ++ :Break ++ - +} - while(...) {- - -- :Break -- - -} -</code></pre><ul> -<li><strong>continue+</strong> и <strong>continue-</strong> - В начало цикла:</li> -</ul> -<pre tabindex="0"><code> while(...) {+ - ++ :Continue ++ - +} - while(...) {- - -- :Continue -- - -} -</code></pre><p>obj { -.field = 1; -.prop(); -};</p> -<p>#Python</p> -<h1 id="1-without-using-with-statement">1) without using with statement<a class="td-heading-self-link" href="#1-without-using-with-statement" aria-label="Heading self-link"></a></h1> -<p>file = open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) -file.write(&lsquo;hello world !&rsquo;) -file.close()</p> -<h1 id="2-without-using-with-statement">2) without using with statement<a class="td-heading-self-link" href="#2-without-using-with-statement" aria-label="Heading self-link"></a></h1> -<p>file = open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) -try: -file.write(&lsquo;hello world&rsquo;) -finally: -file.close()</p> -<p>open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) { -.write(&lsquo;hello world !&rsquo;); -.close(); -}</p> -<p>Python3</p> -<h1 id="using-with-statement">using with statement<a class="td-heading-self-link" href="#using-with-statement" aria-label="Heading self-link"></a></h1> -<p>with open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) as file: -file.write(&lsquo;hello world !&rsquo;)</p> -<h1 id="a-simple-file-writer-object">a simple file writer object<a class="td-heading-self-link" href="#a-simple-file-writer-object" aria-label="Heading self-link"></a></h1> -<p>class MessageWriter(object): -def <strong>init</strong>(self, file_name): -self.file_name = file_name</p> -<pre><code>def __enter__(self): - self.file = open(self.file_name, 'w') - return self.file - -def __exit__(self, *args): - self.file.close() -</code></pre> -<h1 id="using-with-statement-with-messagewriter">using with statement with MessageWriter<a class="td-heading-self-link" href="#using-with-statement-with-messagewriter" aria-label="Heading self-link"></a></h1> -<p>with MessageWriter(&lsquo;my_file.txt&rsquo;) as xfile: -xfile.write(&lsquo;hello world&rsquo;)</p> -<h1 id="a-simple-file-writer-object-1">a simple file writer object<a class="td-heading-self-link" href="#a-simple-file-writer-object-1" aria-label="Heading self-link"></a></h1> -<p>:MessageWriter { -def <strong>init</strong>(self, file_name): -self.file_name = file_name</p> -<pre><code>def __enter__(self): - self.file = open(self.file_name, 'w') - return self.file - -def __exit__(self, *args): - self.file.close() -</code></pre> -<p>}</p> -<h1 id="using-with-statement-with-messagewriter-1">using with statement with MessageWriter<a class="td-heading-self-link" href="#using-with-statement-with-messagewriter-1" aria-label="Heading self-link"></a></h1> -<p>MessageWriter(&lsquo;my_file.txt&rsquo;) { -.write(&lsquo;hello world&rsquo;); -};</p> -<p>from contextlib import contextmanager</p> -<p>class MessageWriter(object): -def <strong>init</strong>(self, filename): -self.file_name = filename</p> -<pre><code>@contextmanager -def open_file(self): - try: - file = open(self.file_name, 'w') - yield file - finally: - file.close() -</code></pre> -<h1 id="usage">usage<a class="td-heading-self-link" href="#usage" aria-label="Heading self-link"></a></h1> -<p>message_writer = MessageWriter(&lsquo;hello.txt&rsquo;) -with message_writer.open_file() as my_file: -my_file.write(&lsquo;hello world&rsquo;)</p> -<p>:MessageWriter(object) { -def <strong>init</strong>(self, filename): -self.file_name = filename</p> -<pre><code>@contextmanager -def open_file(self): - try: - file = open(self.file_name, 'w') - yield file - finally: - file.close() -</code></pre> -<p>}</p> -<h1 id="usage-1">usage<a class="td-heading-self-link" href="#usage-1" aria-label="Heading self-link"></a></h1> -<p>message_writer = MessageWriter(&lsquo;hello.txt&rsquo;) -with message_writer.open_file() as my_file: -my_file.write(&lsquo;hello world&rsquo;)</p> -<h1 id="приложения">Приложения<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b8%d0%bb%d0%be%d0%b6%d0%b5%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h1> <h2 id="предопределенные-макросы">Предопределенные макросы<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b5%d0%b4%d0%be%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%bd%d1%8b%d0%b5-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b" aria-label="Heading self-link"></a></h2> -<p>При работе парсера <em>NewLang</em> автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. +<p>При работе парсера <em>NewLang</em> автоматически формируются несколько зарезервированных макросов, +часть из которых соответствуют макросам препроцессора у С/С++. Данные предопределенные макросы можно использовать как обычные константы.</p> <ul> <li> @@ -3156,11 +2794,34 @@ <h3 id="еще-пример-возможностей-для-расширения <h1 id="pg-cf08b42ee4f3746e6fd20919aa6660c8">2.9 - Нативные типы</h1> <h2 id="нативные-типы-данных">Нативные типы данных<a class="td-heading-self-link" href="#%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85" aria-label="Heading self-link"></a></h2> -<p>Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &ldquo;<strong>%</strong>&rdquo;. -В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат.</p> +<p>Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &ldquo;<strong>%</strong>&rdquo;.</p> +<p>В случае переменных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определенный формат.</p> +<p>Чтобы использовать уже существующие библиотеки, нужно импортировать нативный объект, +тем самым создав объкт NewLang, но с реализацией на другом языке, например на С/С++.</p> +<p>Синтаксис импорта нативных объектов такой же, как и для <a href="/ru/docs/ops/create/">создания</a> обычных объектов языка, +только в качестве правого операнда в операторе создания требуется указать имя нативнного объекта.</p> +<p>При импорте нативного объекта необходимо всегда указывать типы переменных, а также типы аргументов и возвращаемых значений для функций.</p> +<p>Если типы данных у создаваемого и нативного объекта совпадают (т.е. не требуется преобразование типов), +то нативное имя объекта можно указать с многоточием, которое означает, что типы данных будут повторять заданные у левого операнда.</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#000">Plain</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#000">fopen</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">filename</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">StrChar</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">modes</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">StrChar</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">FILE</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fopen</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">fclose</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">f</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fclose</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">fflush</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">f</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fflush</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">fprintf</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">f</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#204a87">format</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FmtChar</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fprintf</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#000">fremove</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">filename</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">String</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">remove</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">frename</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">old</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">String</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">new</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">String</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">rename</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span></code></pre></div> + +<div class="pageinfo pageinfo-primary"> +<p>Последующее описание находится в процессе разработки.</p> + +</div> + <h3 id="pointer--указатель-на-системную-область-памяти-или-нативную-функцию">:Pointer — указатель на системную область памяти или нативную функцию<a class="td-heading-self-link" href="#pointer--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%83%d1%8e-%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8-%d0%b8%d0%bb%d0%b8-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%83%d1%8e-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8e" aria-label="Heading self-link"></a></h3> -<p>Так как любой программе приходится взаимодействовать с внешним миром, т -о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, +<p>Так как любой программе приходится взаимодействовать с внешним миром, +то по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип <em>:Pointer</em>. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. Но можно вывести его значение, например для отладки.</p> <h3 id="plain--указатель-на-представление-данных-в-бинарном-виде">:Plain — указатель на представление данных в бинарном виде<a class="td-heading-self-link" href="#plain--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d0%bf%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%be%d0%bc-%d0%b2%d0%b8%d0%b4%d0%b5" aria-label="Heading self-link"></a></h3> @@ -4249,7 +3910,44 @@ <h3 id="catch">Перехват прерывааний<a class="td-heading-self- <h1 id="pg-1777268c8246a0a796e4cb0a4fdf4c15">4 - Архитектура</h1> <div class="lead">Описание архитектуры компилятора для и конкретных технических решений</div> - <h2 id="система-классов-реализации">Система классов реализации<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0-%d0%ba%d0%bb%d0%b0%d1%81%d1%81%d0%be%d0%b2-%d1%80%d0%b5%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h2> + <h2 id="на-память">На память<a class="td-heading-self-link" href="#%d0%bd%d0%b0-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d1%8c" aria-label="Heading self-link"></a></h2> +<p>clang-17 не поддерживает:</p> +<table> +<thead> +<tr> +<th>Feature</th> +<th>Proposal</th> +<th>Available</th> +</tr> +</thead> +<tbody> +<tr> +<td>Coroutines</td> +<td>P0912R5</td> +<td><em>Partial</em> Fully supported on all targets except Windows, which still has some stability and ABI issues.</td> +</tr> +<tr> +<td>Extended floating-point types and standard names</td> +<td>P1467R9</td> +<td>No</td> +</tr> +<tr> +<td>Concepts</td> +<td>P0848R3</td> +<td>Clang 16 (Partial)</td> +</tr> +<tr> +<td>Modules</td> +<td></td> +<td>No</td> +</tr> +</tbody> +</table> +<h3 id="начиная-с-c-should-adopt-the-same-characters-for-c26">Начиная с C++ should adopt the same characters for C++26.<a class="td-heading-self-link" href="#%d0%bd%d0%b0%d1%87%d0%b8%d0%bd%d0%b0%d1%8f-%d1%81-c-should-adopt-the-same-characters-for-c26" aria-label="Heading self-link"></a></h3> +<ul> +<li>Add <strong>@</strong>, <strong>$</strong>, and ` to the basic character set P2558R2 Yes</li> +</ul> +<h2 id="система-классов-реализации">Система классов реализации<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0-%d0%ba%d0%bb%d0%b0%d1%81%d1%81%d0%be%d0%b2-%d1%80%d0%b5%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h2> <p>RunTime - единственный класс для приложения (процесса) - интерфейс для взаимодействия с операционной системой</p> <ul> <li>Загружат и выгружает модули и является их владельцем (shared_ptr)</li> diff --git a/docs/ru/docs/arch/_print/index.html b/docs/ru/docs/arch/_print/index.html index 7a677503..906a4915 100644 --- a/docs/ru/docs/arch/_print/index.html +++ b/docs/ru/docs/arch/_print/index.html @@ -149,7 +149,44 @@ <h1 class="title">Архитектура</h1> <div class="content"> - <h2 id="система-классов-реализации">Система классов реализации<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0-%d0%ba%d0%bb%d0%b0%d1%81%d1%81%d0%be%d0%b2-%d1%80%d0%b5%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h2> + <h2 id="на-память">На память<a class="td-heading-self-link" href="#%d0%bd%d0%b0-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d1%8c" aria-label="Heading self-link"></a></h2> +<p>clang-17 не поддерживает:</p> +<table> +<thead> +<tr> +<th>Feature</th> +<th>Proposal</th> +<th>Available</th> +</tr> +</thead> +<tbody> +<tr> +<td>Coroutines</td> +<td>P0912R5</td> +<td><em>Partial</em> Fully supported on all targets except Windows, which still has some stability and ABI issues.</td> +</tr> +<tr> +<td>Extended floating-point types and standard names</td> +<td>P1467R9</td> +<td>No</td> +</tr> +<tr> +<td>Concepts</td> +<td>P0848R3</td> +<td>Clang 16 (Partial)</td> +</tr> +<tr> +<td>Modules</td> +<td></td> +<td>No</td> +</tr> +</tbody> +</table> +<h3 id="начиная-с-c-should-adopt-the-same-characters-for-c26">Начиная с C++ should adopt the same characters for C++26.<a class="td-heading-self-link" href="#%d0%bd%d0%b0%d1%87%d0%b8%d0%bd%d0%b0%d1%8f-%d1%81-c-should-adopt-the-same-characters-for-c26" aria-label="Heading self-link"></a></h3> +<ul> +<li>Add <strong>@</strong>, <strong>$</strong>, and ` to the basic character set P2558R2 Yes</li> +</ul> +<h2 id="система-классов-реализации">Система классов реализации<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0-%d0%ba%d0%bb%d0%b0%d1%81%d1%81%d0%be%d0%b2-%d1%80%d0%b5%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h2> <p>RunTime - единственный класс для приложения (процесса) - интерфейс для взаимодействия с операционной системой</p> <ul> <li>Загружат и выгружает модули и является их владельцем (shared_ptr)</li> diff --git a/docs/ru/docs/arch/index.html b/docs/ru/docs/arch/index.html index 10d7c0ad..b001a7c2 100644 --- a/docs/ru/docs/arch/index.html +++ b/docs/ru/docs/arch/index.html @@ -226,6 +226,11 @@ <div class="td-toc"> <nav id="TableOfContents"> <ul> + <li><a href="#на-память">На память</a> + <ul> + <li><a href="#начиная-с-c-should-adopt-the-same-characters-for-c26">Начиная с C++ should adopt the same characters for C++26.</a></li> + </ul> + </li> <li><a href="#система-классов-реализации">Система классов реализации</a></li> <li><a href="#реализация-загрузки-модулей-и-пакетов">Реализация загрузки модулей и пакетов</a></li> <li><a href="#шаги-сборки-компилятора">Шаги сборки компилятора</a></li> @@ -277,7 +282,44 @@ <h1>Архитектура</h1> <header class="article-meta"> </header> - <h2 id="система-классов-реализации">Система классов реализации<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0-%d0%ba%d0%bb%d0%b0%d1%81%d1%81%d0%be%d0%b2-%d1%80%d0%b5%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h2> + <h2 id="на-память">На память<a class="td-heading-self-link" href="#%d0%bd%d0%b0-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d1%8c" aria-label="Heading self-link"></a></h2> +<p>clang-17 не поддерживает:</p> +<table> +<thead> +<tr> +<th>Feature</th> +<th>Proposal</th> +<th>Available</th> +</tr> +</thead> +<tbody> +<tr> +<td>Coroutines</td> +<td>P0912R5</td> +<td><em>Partial</em> Fully supported on all targets except Windows, which still has some stability and ABI issues.</td> +</tr> +<tr> +<td>Extended floating-point types and standard names</td> +<td>P1467R9</td> +<td>No</td> +</tr> +<tr> +<td>Concepts</td> +<td>P0848R3</td> +<td>Clang 16 (Partial)</td> +</tr> +<tr> +<td>Modules</td> +<td></td> +<td>No</td> +</tr> +</tbody> +</table> +<h3 id="начиная-с-c-should-adopt-the-same-characters-for-c26">Начиная с C++ should adopt the same characters for C++26.<a class="td-heading-self-link" href="#%d0%bd%d0%b0%d1%87%d0%b8%d0%bd%d0%b0%d1%8f-%d1%81-c-should-adopt-the-same-characters-for-c26" aria-label="Heading self-link"></a></h3> +<ul> +<li>Add <strong>@</strong>, <strong>$</strong>, and ` to the basic character set P2558R2 Yes</li> +</ul> +<h2 id="система-классов-реализации">Система классов реализации<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0-%d0%ba%d0%bb%d0%b0%d1%81%d1%81%d0%be%d0%b2-%d1%80%d0%b5%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h2> <p>RunTime - единственный класс для приложения (процесса) - интерфейс для взаимодействия с операционной системой</p> <ul> <li>Загружат и выгружает модули и является их владельцем (shared_ptr)</li> diff --git a/docs/ru/docs/index.html b/docs/ru/docs/index.html index 9bbb80ff..1572f350 100644 --- a/docs/ru/docs/index.html +++ b/docs/ru/docs/index.html @@ -219,18 +219,7 @@ </div> - <div class="td-toc"> - <nav id="TableOfContents"> - <ul> - <li> - <ul> - <li><a href="#начиная-с-c-should-adopt-the-same-characters-for-c26">Начиная с C++ should adopt the same characters for C++26.</a></li> - </ul> - </li> - </ul> -</nav> - </div> - + <div class="taxonomy taxonomy-terms-cloud taxo-tags"> <h5 class="taxonomy-title">Tag Cloud</h5> <ul class="taxonomy-terms"> @@ -265,42 +254,6 @@ <h1>Документация</h1> </header> <p>Основные материалы по языку программирования NewLang.</p> <p>Описание акутально для текущей версии 4.0</p> -<p>clang-17 не поддерживает:</p> -<table> -<thead> -<tr> -<th>Feature</th> -<th>Proposal</th> -<th>Available</th> -</tr> -</thead> -<tbody> -<tr> -<td>Coroutines</td> -<td>P0912R5</td> -<td><em>Partial</em> Fully supported on all targets except Windows, which still has some stability and ABI issues.</td> -</tr> -<tr> -<td>Extended floating-point types and standard names</td> -<td>P1467R9</td> -<td>No</td> -</tr> -<tr> -<td>Concepts</td> -<td>P0848R3</td> -<td>Clang 16 (Partial)</td> -</tr> -<tr> -<td>Modules</td> -<td></td> -<td>No</td> -</tr> -</tbody> -</table> -<h3 id="начиная-с-c-should-adopt-the-same-characters-for-c26">Начиная с C++ should adopt the same characters for C++26.<a class="td-heading-self-link" href="#%d0%bd%d0%b0%d1%87%d0%b8%d0%bd%d0%b0%d1%8f-%d1%81-c-should-adopt-the-same-characters-for-c26" aria-label="Heading self-link"></a></h3> -<ul> -<li>Add <strong>@</strong>, <strong>$</strong>, and ` to the basic character set P2558R2 Yes</li> -</ul> <div class="section-index"> diff --git a/docs/ru/docs/index.xml b/docs/ru/docs/index.xml index fd80460f..df97a5c9 100644 --- a/docs/ru/docs/index.xml +++ b/docs/ru/docs/index.xml @@ -1700,7 +1700,8 @@ Sum1(arg1, arg2) :- {$arg1+$arg2;}; # Создать или переопреде <description> - &lt;p&gt;Макросы в &lt;strong&gt;NewLang&lt;/strong&gt;, это один или несколько последовательных терминов, которые заменяются на другой термин + &lt;p&gt;Макросы используются и для превращеня исходного кода &lt;em&gt;NewLang&lt;/em&gt; в более привычный синтаксис на основе &lt;a href=&#34;https://newlang.net/syntax_dsl.html&#34;&gt;ключевых слов&lt;/a&gt;, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода.&lt;/p&gt; +&lt;p&gt;Макросы в &lt;strong&gt;NewLang&lt;/strong&gt;, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем).&lt;/p&gt; &lt;p&gt;Макросы обработываются во время работы &lt;strong&gt;лексера&lt;/strong&gt;, т.е. перед передачей последовательности лексем в парсер, что позволяет с помощью маросов изменять фрагменты синтаксиса языка, например, при реализации собственных диалектов DSL.&lt;/p&gt; @@ -1735,13 +1736,13 @@ Sum1(arg1, arg2) :- {$arg1+$arg2;}; # Создать или переопреде с одинаковыми именами, один из которых будет с аргументами (скобками), а другой без них.&lt;/p&gt; &lt;p&gt;Поэтому, если требуется использовать макрос в двух разных вариантах (с аргументами и без оных), следует определять макрос без аргументов и в этом случае контроль параметров будет выполнятся компилятором.&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@macro@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; term&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Макрос без аргументов&lt;/span&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@ macro @@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; term&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Макрос без аргументов&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; macro&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;args&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# ОК -&amp;gt; term(args);&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; macro&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# ОК -&amp;gt; term;&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Но &lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; term&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@ call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt; @@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; term&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# ОК -&amp;gt; term();&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; call&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Ошибка (@call определен с аргументами) &lt;/span&gt; @@ -1754,286 +1755,49 @@ Sum1(arg1, arg2) :- {$arg1+$arg2;}; # Создать или переопреде &lt;p&gt;По аналогии с препроцессором С/С++, для соединения двух лексем в одну, в теле макроса используется оператор &lt;strong&gt;&amp;quot;@##&amp;quot;&lt;/strong&gt;, а для преобразование лексемы в текстову строку применяется операторы &lt;strong&gt;@#&lt;/strong&gt;, &lt;strong&gt;@#&amp;quot;&lt;/strong&gt; или &lt;strong&gt;@#&amp;rsquo;&lt;/strong&gt;, например, &lt;code&gt;@@macro($arg)@@ := @@ func_ @## @$arg( @#&amp;quot; arg ) @;&lt;/code&gt;, тогда вызов &lt;code&gt;macro(name);&lt;/code&gt; будет преобразован в &lt;code&gt;func_name (&amp;quot;name&amp;quot;);&lt;/code&gt;&lt;/p&gt; - - -&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; -&lt;h4 id=&#34;ограничения-макропроцессора-в-текущей-версии&#34;&gt;Ограничения макропроцессора в текущей версии&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%b3%d1%80%d0%b0%d0%bd%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d0%bf%d1%80%d0%be%d1%86%d0%b5%d1%81%d1%81%d0%be%d1%80%d0%b0-%d0%b2-%d1%82%d0%b5%d0%ba%d1%83%d1%89%d0%b5%d0%b9-%d0%b2%d0%b5%d1%80%d1%81%d0%b8%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h4&gt; -&lt;p&gt;На текущий момент макросы реализованы в минимальном объеме для самых простых сценариев использования:&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;DSL для keyword based syntax (if, else, return, match, while и т.д.) - (1 термин с произвольными аргументами и без) - требуется сейчас !!!&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;&lt;em&gt;Парсер при обработке макросов может анализировать информацию о типах данных, если она указана.&lt;/em&gt; -&lt;em&gt;Но на текущий момент типы данных в макросах никак не обрабатываются и это одна из обязательных фич, которая будет реализована в будущем.&lt;/em&gt;&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Определения (func, class) - (несколько терминов с аргументами и без аргументов) - Реализация ООП и импорт С++ классов&lt;/li&gt; -&lt;li&gt;Модификации при определениях (override) - (несколько терминов и шаблоны с аргументами и без аргументов) - Реализация ООП и импорт С++ классов&lt;/li&gt; -&lt;/ul&gt; - -&lt;/div&gt; - -&lt;h1 id=&#34;макросы-без-аргументов-или-все-аргументы-сразу-&#34;&gt;МАКРОСЫ БЕЗ АРГУМЕНТОВ ИЛИ ВСЕ АРГУМЕНТЫ СРАЗУ !!!!!&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b1%d0%b5%d0%b7-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d0%b8%d0%bb%d0%b8-%d0%b2%d1%81%d0%b5-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d1%8b-%d1%81%d1%80%d0%b0%d0%b7%d1%83-&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;h1 id=&#34;анализа-аргументов-или-их-типов-не-производится-&#34;&gt;анализа аргументов или их типов не производится !!!&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b0%d0%bd%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d0%b8%d0%bb%d0%b8-%d0%b8%d1%85-%d1%82%d0%b8%d0%bf%d0%be%d0%b2-%d0%bd%d0%b5-%d0%bf%d1%80%d0%be%d0%b8%d0%b7%d0%b2%d0%be%d0%b4%d0%b8%d1%82%d1%81%d1%8f-&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;Lambda -@@ lambda $name(&amp;hellip;) @@ ::= @@ @$name( @$&amp;hellip; ) ::= ( _( @$&amp;hellip; ) ::= @&lt;strong&gt;PRAGMA_FINALIZE&lt;/strong&gt;( @), {, {+, {-, {* ) @@&lt;/p&gt; -&lt;h3 id=&#34;примеры-использования-макросов&#34;&gt;Примеры использования макросов&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80%d1%8b-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Обычные макросы (тело макроса корректное выражение)&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@macro@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; replace&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@macro2&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;arg&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt; call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;@&lt;span style=&#34;color:#000&#34;&gt;$arg&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()}&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;p&gt;Примеры использования макросов:&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Обычные макросы (тело макроса корректное выражение)&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;macro&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;replace&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;();&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;macro2&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;arg&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;call&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;arg&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;call&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;()};&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Тело макросов из последовательности лексем&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@if&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;...&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@ &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;\$&lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;*&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;--&amp;gt; @@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Выражение может быть не полным&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@elif&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;...&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@ ,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;\$&lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;elif&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;*&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;--&amp;gt; @@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@else@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@ ,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;_&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;--&amp;gt; @@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Выражение может быть не полным&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;elif&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,[&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,[&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Запись условного оператора с использованием &lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# определенных выше макросов&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt; condition &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;){&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ... -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;elif&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt; condition2 &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ... -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ... -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Зачем нужна трансформация синтаксиса? -Нативная поддержка других языков нужна чтобы не переписывать легаси код на этих языках.&lt;/p&gt; -&lt;p&gt;Чтобы можно было использовать существующие исходники как собственные требуется настройка работы -препроцессора и лексера под конкретный язык программирования (описание DSL). -Для &lt;strong&gt;С/С++&lt;/strong&gt; потребуется выделять лексером комментарии из-за пересечения синтаксиса (которые сейчас игнорируются). -Для &lt;strong&gt;Python&lt;/strong&gt; требуется выделять лексером отступы (которые сейчас тоже игнорируются), причем потребуется реализация не только синтаксиса, -но и зависимых пакетов с последующая трансляцией этого кода в С++, что в настоящий момент делать не целесообразно (cython ???).&lt;/p&gt; -&lt;p&gt;Но так как возможность трансформации кода с других языков программирования принципиальная возможна, -стоит над этим думать только после полноценного релиза NewLang и его перехода в прод.&lt;/p&gt; -&lt;p&gt;Для реализации DSL требуется передача команд в парсер для управления его работой (по аналогии с командой #pragma) -Но так как обработка таких команд должна происходить в лексере до передачи данных в парсер (анализатор), -то команды для макропроцессора должны быть в максимально простом виде и состоять из элементов, -которые лексер может самостоятельно идентифицировать, т.е. термины, строки и цифры (без выражений и именованных аргументов).&lt;/p&gt; -&lt;p&gt;После обработки такой команды она анализируется макропроцессором и удаляется из потока лексем, т.е. в парсер (анализатор) не передается. -Но в случае ошибки с синтаксисе, данные команды нужно уметь однозначно идентифировать и самый простой способ, -комбинация признака макроса и системного имени, т.е. что-то вроде&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; @__PRAGMA_DIAG__(push) - @__PRAGMA_DIAG__(ignored, &amp;#34;-Wundef&amp;#34;) - @__PRAGMA_DIAG__(warning, &amp;#34;-Wformat&amp;#34;) - @__PRAGMA_DIAG__(error &amp;#34;-Wuninitialized&amp;#34;) - @__PRAGMA_DIAG__(pop) - - #pragma message &amp;#34;Compiling &amp;#34; __FILE__ &amp;#34;...&amp;#34; - @__PRAGMA_MESSAGE__(&amp;#34;Compiling &amp;#34;, __FILE__, &amp;#34;...&amp;#34;) - - #pragma error &amp;#34;Error &amp;#34; __FILE__ &amp;#34;...&amp;#34; - @__PRAGMA_ERROR__(&amp;#34;Error &amp;#34;, __FILE__, &amp;#34;...&amp;#34;) - - -#define DO_PRAGMA(x) _Pragma (#x) -#define TODO(x) DO_PRAGMA(message (&amp;#34;TODO - &amp;#34; #x)) - -@@TODO( ... )@@ := @__PRAGMA_MESSAGE__(&amp;#34;TODO - &amp;#34;, @*) - -@TODO(Remember to fix this) # note: TODO - Remember to fix this - -\\.__lexer__ignore_space__ = 1; -\\.__lexer__ignore_indent__ = 1; -\\.__lexer__ignore_comment__ = 1; -\\.__lexer__ignore_crlf__ = 1; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Таким образом можно трансформировать условный оператор на питоне в синтаксис NewLang следующим макросом:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; -#pragma clang attribute push -#pragma clang diagnostic ignored &amp;#34;-Wundef&amp;#34; -#pragma clang diagnostic ignored &amp;#34;-Wunused-variable&amp;#34; - - -#elif __GNUC__ - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored &amp;#34;-Wuninitialized&amp;#34; - -#pragma GCC diagnostic ignored &amp;#34;-Wall&amp;#34; -#pragma GCC diagnostic ignored &amp;#34;-Wextra&amp;#34; - - @pragma warning(pop) +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@if&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;condition&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;){&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@elif&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;condition2&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@else&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Например цикл до 5:&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;5&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;42&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;+=&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Будет выглядеть более привычно:&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@while&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;true&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@if&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;5&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@return&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;42&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; - @@ pragma warning(...) @@ := __PRAGMA_TERM_DIAG_WARNING__(); -@__PRAGMA_DIAG__(warning, pop); +&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; +&lt;h3 id=&#34;далее-идеи-на-будущее&#34;&gt;Далее идеи на будущее&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b4%d0%b0%d0%bb%d0%b5%d0%b5-%d0%b8%d0%b4%d0%b5%d0%b8-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; +&lt;h3 id=&#34;символьное-программирование&#34;&gt;Символьное программирование&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d0%bc%d0%b2%d0%be%d0%bb%d1%8c%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -Обработка терминов в макропроцессоре в максимально простом виде. -Агрументы только термины, строки и цифры без вложенных выражений и именованных аргументов, -т.е. только элементы, которые может самостоятельно идентифицировать лексер. +&lt;/div&gt; -@warning(&amp;#34;--&amp;#34;) - @@ if ... : @@ := @@ [ @$* ]-&amp;gt; __TERM_BLOCK_INDENT__(&amp;#34;{&amp;#34;, force_semicolon=1) @@ - - if __name__ == &amp;#34;__main__&amp;#34;: - run1() - run2() - - [ __name__ == &amp;#34;__main__&amp;#34; ]-&amp;gt; { - run1(); - run2(); - }; - - -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ключ &amp;ndash;parser-syntax-only только текстовый парсинг исходного кода без загрузки модулей, раскрытия макросов и проверки имен.&lt;/p&gt; -&lt;p&gt;Ключ &amp;ndash;parser-no-macros - без раскрытия макросов -Ключ &amp;ndash;parser-no-module - без загрузки модулей (и мокросов, если они в них определяются) -Ключ &amp;ndash;parser-no-check-prototype - без проверки имен при обращении&lt;/p&gt; -&lt;p&gt;prototype -@&lt;strong&gt;PRAGMA_PROTOTYPE&lt;/strong&gt;(define) -@&lt;strong&gt;PRAGMA_PROTOTYPE&lt;/strong&gt;(implement)&lt;/p&gt; -&lt;p&gt;$$&lt;/p&gt; -&lt;p&gt;\$ - корень системы (система)&lt;/p&gt; -&lt;p&gt;$ - текущий модуль&lt;/p&gt; -&lt;h1 id=&#34;макросы-для-конвертора-проверки-в-python&#34;&gt;Макросы для конвертора проверки в Python&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b4%d0%bb%d1%8f-%d0%ba%d0%be%d0%bd%d0%b2%d0%b5%d1%80%d1%82%d0%be%d1%80%d0%b0-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b8-%d0%b2-python&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;h1 id=&#34;if-__name__--__main__&#34;&gt;if &lt;strong&gt;name&lt;/strong&gt; == &amp;ldquo;&lt;strong&gt;main&lt;/strong&gt;&amp;rdquo;:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#if-__name__--__main__&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;@@ &lt;strong&gt;name&lt;/strong&gt; @@ ::= @@ $. @&lt;strong&gt;PRAGMA_NO_MACRO&lt;/strong&gt;() &lt;strong&gt;name&lt;/strong&gt; @@ -@@ if $&amp;hellip; @: @@ ::= @@ [ @$&amp;hellip; ] &amp;ndash;&amp;gt; @@&lt;/p&gt; -&lt;p&gt;@if( $.&lt;strong&gt;name&lt;/strong&gt; == &amp;ldquo;&lt;strong&gt;main&lt;/strong&gt;&amp;rdquo; ) {&lt;/p&gt; -&lt;p&gt;}&lt;/p&gt; -&lt;p&gt;\каталог\модуль() - статический импорт модуля -\(&amp;ldquo;каталог\модуль&amp;rdquo;)() - динамический импорт модуля&lt;/p&gt; -&lt;p&gt;printf := :Pointer(&amp;lsquo;printf(format:FmtChar, &amp;hellip;):Int32&amp;rsquo;); -printf := %printf(format:FmtChar, &amp;hellip;):Int32;&lt;/p&gt; -&lt;h1 id=&#34;регистрация-прототипа-нативной-функции&#34;&gt;Регистрация прототипа нативной функции&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%80%d0%b5%d0%b3%d0%b8%d1%81%d1%82%d1%80%d0%b0%d1%86%d0%b8%d1%8f-%d0%bf%d1%80%d0%be%d1%82%d0%be%d1%82%d0%b8%d0%bf%d0%b0-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;@prototype -%puts(format:StrChar):Int32;&lt;/p&gt; -&lt;h1 id=&#34;импорт-нативной-функции-с-предварительной-проверкой-её-наличия-во-время-компиляции-статическая-линковка&#34;&gt;Импорт нативной функции с предварительной проверкой её наличия во время компиляции (статическая линковка)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b8%d0%bc%d0%bf%d0%be%d1%80%d1%82-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d1%81-%d0%bf%d1%80%d0%b5%d0%b4%d0%b2%d0%b0%d1%80%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d0%be%d0%b9-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%be%d0%b9-%d0%b5%d1%91-%d0%bd%d0%b0%d0%bb%d0%b8%d1%87%d0%b8%d1%8f-%d0%b2%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d1%8f-%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%86%d0%b8%d0%b8-%d1%81%d1%82%d0%b0%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bb%d0%b8%d0%bd%d0%ba%d0%be%d0%b2%d0%ba%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;puts2(format:StrChar):Int32 := %puts(format:StrChar):Int32;&lt;/p&gt; -&lt;h1 id=&#34;импорт-нативной-функции-по-её-прототипу-во-время-выполнения-динамическая-линковка&#34;&gt;Импорт нативной функции по её прототипу во время выполнения (динамическая линковка)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b8%d0%bc%d0%bf%d0%be%d1%80%d1%82-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d0%bf%d0%be-%d0%b5%d1%91-%d0%bf%d1%80%d0%be%d1%82%d0%be%d1%82%d0%b8%d0%bf%d1%83-%d0%b2%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d1%8f-%d0%b2%d1%8b%d0%bf%d0%be%d0%bb%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b4%d0%b8%d0%bd%d0%b0%d0%bc%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bb%d0%b8%d0%bd%d0%ba%d0%be%d0%b2%d0%ba%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;puts3(format:StrChar):Int32 := :Pointer(&amp;lsquo;puts(format:StrChar):Int32&amp;rsquo;);&lt;/p&gt; -&lt;p&gt;%puts(&amp;lsquo;Тест вывода строки&amp;rsquo;); # Линковка с нативной функцией во время компиляции и непосредственный вызов с оптимизацией передачи параметров -puts2(&amp;lsquo;Тест 2 вывода строки&amp;rsquo;); # Линковка с нативной функцией во время компиляции -puts3(&amp;lsquo;Тест 3 вывода строки&amp;rsquo;); # Линковка с нативной функцией во время выполнения при первом вызове puts3&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Парсинг исходного текста без раскрытия макросов и загрузки модулей&lt;/li&gt; -&lt;li&gt;Парсинг исходного текста с раскрытием макросов (требуется загрузка модулей для зависимых и переопределяемых макросов)&lt;/li&gt; -&lt;li&gt;Загружатся модули могут как в виде исходников (которые требуется парсить и компилировть/выполнять) -или в виде бинарников (в них должны быть список макросов, типов и имена объектов)&lt;/li&gt; -&lt;li&gt;После парсинга получается список &lt;strong&gt;имен&lt;/strong&gt; макросов, типов и объектов (TermPtr)&lt;/li&gt; -&lt;li&gt;После выполнения модуля - список &lt;strong&gt;имен&lt;/strong&gt; заполняется реальными объектами (ObjPtr).&lt;/li&gt; -&lt;/ul&gt; -&lt;h1 id=&#34;компиляция-файла&#34;&gt;Компиляция файла&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%86%d0%b8%d1%8f-%d1%84%d0%b0%d0%b9%d0%bb%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;ul&gt; -&lt;li&gt;Парсинг исходника для построения AST (без анализа имен, связей, загрузки модулей и пр. только исходые тексты с раскрытием макросов&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;/ul&gt; -&lt;h1 id=&#34;систематизация-реализации-макросов&#34;&gt;Систематизация реализации макросов&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0%d1%82%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d1%80%d0%b5%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d0%b8-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;последовательность лексем MACRO_SEQ мужду @@ @@ сохраняется в m_block, так как фрагменты блоков не могут быть идентификаторами&lt;/p&gt; -&lt;p&gt;Разбор макросов происходит в лексере. Определением макроса всегда является целая строка, -которая заканчивается точкой с запятой, а идентификатором макроса всегда выступает последовательность лексем:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@ id @@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; macro&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@ id @@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@ @@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@ id @@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@@ @@@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Хранилищем текущих максросов является объект класса MacroBuffer. -Последовательность лексем идентификатора (id) макроса должна сохраняется в отдельном поле термина и однозначно его идентифицирует. -Первый термин в идентификаторе хранится как ключ hashmap, а дальше происходит поиск полным перебором. -Этапы работы с макросами&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt; -&lt;p&gt;Входные термины из лексера получаются вызовом GetNextToken, внутри которой и происходит раскрытие макросов. -Внутренний буфер заполняется до окончания строки (выражения), т.е. до символа &amp;lsquo;;&amp;rsquo; или &lt;END&gt;, после чего производится -поиск макросов в объекте MacroBuffer для текущей последовательности лексем в буфере.&lt;/p&gt; -&lt;/li&gt; -&lt;li&gt; -&lt;p&gt;Если макрос найден, то соответствющая ему последоваетльность заменяется на тело макроса и происходит переход -на повторный анализ входного буфера.&lt;/p&gt; -&lt;/li&gt; -&lt;li&gt; -&lt;p&gt;Если макрос не найден, то данные передаются в парсер для дальнейшего синтаксическго анализа.&lt;/p&gt; -&lt;/li&gt; -&lt;li&gt; -&lt;p&gt;Для этого во входном потоке лексем (parser.y) во время оператората создания/присвоения вызывается функция проверки на макрос. -MacroBuffer::CheckMacroAndConvertDel($$), и после этого выходному значению присваивается результат выполнения driver.MacroEval($$), -и в дальнейшем этот макрос никак не обработывается.&lt;/p&gt; -&lt;/li&gt; -&lt;li&gt; -&lt;p&gt;Создание макросов, проверка на дубликаты и логические ошибки в определении происходит путем обращения к методам объекта MacroBuffer.&lt;/p&gt; -&lt;p&gt;/*&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Макросы хрянтся как фрагменты AST в виде объектов типа Term,&lt;/li&gt; -&lt;li&gt;так как создаются после обработки парсером по правилам стандратной грамматики.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Но анализ входных данных на предмет раскрытия макросов проиходит из потока (последовательности) лексем,&lt;/li&gt; -&lt;li&gt;т.е. &lt;strong&gt;ДО&lt;/strong&gt; обработки парсером, так как при раскрытии макросов может меняться грамматика выражений.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Функция \ref CompareMacro сравнивает входной буфер (последовательность лексем)&lt;/li&gt; -&lt;li&gt;на предмет возможного соответствия одному конкретному макросу.&lt;/li&gt; -&lt;li&gt;Сравниваются только ключевые словам без учета аргументов в скобках,&lt;/li&gt; -&lt;li&gt;но само наличие аргументов проверяется ??????????????????&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Проблема:&lt;/li&gt; -&lt;li&gt;К функции можно обратится с целью её вызова (указав после имени скобки),&lt;/li&gt; -&lt;li&gt;так и по имени без скобок (например для получения ссылки на объект).&lt;/li&gt; -&lt;li&gt;Так и к переменной можно обратиться только по имени,&lt;/li&gt; -&lt;li&gt;так и указав скобки после имени как к функции (при копировании объекта).&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Сделать один макрос под оба сценария (со скобками и без скобок) не получится, так как непонятно,&lt;/li&gt; -&lt;li&gt;что делать с аргументами при раскрытии тела макроса, когда они не указаны.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Но может быть следует переименовывать только одно имя без учета скобок,&lt;/li&gt; -&lt;li&gt;например, оставив такую возможность только для одиночных макросов.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;\name -&amp;gt; name или name (&amp;hellip;), hash: name&lt;/li&gt; -&lt;li&gt;но \name(&amp;hellip;) -&amp;gt; name(&amp;hellip;), а name - ошибка !!!! hash: name&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Или все же следует различать макросы со скобками и без скобок как два разных объекта???&lt;/li&gt; -&lt;li&gt;\name := name2; и \name(&amp;hellip;) := name2(&amp;hellip;); будут разными объектами&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Или добавить макросы-алиасы без аргументов только для переименования отдельных терминов?&lt;/li&gt; -&lt;li&gt;\alias :- name2; но как их отличать от обычных макросов в операции удаления?&lt;/li&gt; -&lt;li&gt;Или вообще не нужно отличать и оставить только один варинат (либо макрос, либо алиас)&lt;/li&gt; -&lt;li&gt;Тода вопрос со скобками закрывается сам собой, алиасы всегда без скобок,&lt;/li&gt; -&lt;li&gt;макросы со скбками или без скобок, но должно быть полное соответствие.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;@ name name2 @ -&amp;gt; name name2, но name name2(&amp;hellip;) - ошибка!!! (hash: name,name2)&lt;/li&gt; -&lt;li&gt;@ name name2(&amp;hellip;) @ -&amp;gt; name name2(&amp;hellip;), но name name2 - ошибка !!!! (hash: name,name2)&lt;/li&gt; -&lt;li&gt;@ name name2&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; @ -&amp;gt; name name2&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt;, но name name2 - ошибка !!!! ( hash: name,name2 )&lt;/li&gt; -&lt;li&gt;@ name $tmpl&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; name3@ -&amp;gt; name $tmpl&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Но!&lt;/li&gt; -&lt;li&gt;@ name name2 @ ::- -&amp;gt; name name2 - ок, но name name2(&amp;hellip;) - ок&lt;/li&gt; -&lt;li&gt;@ name $tmpl name3@ ::- -&amp;gt; name $tmpl&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; name3 - ок, name $tmpl(&amp;hellip;) name3[&amp;hellip;] - ок&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Для последовательности лексем требуется полное соответствие с учетом скобок ???&lt;/li&gt; -&lt;li&gt;и может ли быть несколько скобок одного типа (несколько крыглях, или несколько квардратных????&lt;/li&gt; -&lt;li&gt;&amp;lt;Может быть несколько скобок одного типа, например, при указании типа у аргументов или типа возвращаемого значения.&amp;gt;&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;@ name name2 @ -&amp;gt; name name2, но name name2(&amp;hellip;) - ошибка!!! (hash: name,name2)&lt;/li&gt; -&lt;li&gt;@ name name2(&amp;hellip;) @ -&amp;gt; name name2(&amp;hellip;), но name name2 - ошибка !!!! (hash: name,name2)&lt;/li&gt; -&lt;li&gt;@ name name2&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; @ -&amp;gt; name name2&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt;, но name name2 - ошибка !!!! ( hash: name,name2 )&lt;/li&gt; -&lt;li&gt;@ name $tmpl&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; name3@ -&amp;gt; name $tmpl&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Проблема скобок возникает из-за сценария замены одного термина на другой,&lt;/li&gt; -&lt;li&gt;который есть в препроцессоре С/С++, но отсутствует при реализации с использованием шаблонов.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;*/&lt;/p&gt; -&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;Макросы используются и для превращеня исходного кода &lt;em&gt;NewLang&lt;/em&gt; в более привычный синтаксис на основе &lt;a href=&#34;https://newlang.net/syntax_dsl.html&#34;&gt;ключевых слов&lt;/a&gt;, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода.&lt;/p&gt; -&lt;p&gt;&lt;a href=&#34;https://newlang.net/syntax_dsl.html&#34;&gt;Например:&lt;/a&gt;.&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; @@if(...)@@ ::= @@ [ \$* ]--&amp;gt; @@; - @@while(...)@@ ::= @@ [\$*] &amp;lt;-&amp;gt; @@; - @@return $arg@@::= @@ -- \$arg -- @@; - @@true@@ ::= 1; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Тогда цикл до 5:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;count:=1; -[ 1 ] &amp;lt;-&amp;gt; { - [count&amp;gt;5] --&amp;gt; { - -- 42 --; - }; - count+=1; -}; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;будет выглядеть более привычно&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;count:=1; -while( true ) { - if(count&amp;gt;5) { - return 42; - }; - count+=1; -}; -&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;идеи-на-будущее&#34;&gt;Идеи на будущее&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b8%d0%b4%d0%b5%d0%b8-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h3 id=&#34;символьное-программирование&#34;&gt;Символьное программирование&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d0%bc%d0%b2%d0%be%d0%bb%d1%8c%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;Символьное программирование, часто называемое декларативным программированием, представляет собой парадигму программирования, которая использует математическую логику, отношения и символы для представления знаний и помощи в решении проблем. Вместо того, чтобы сосредотачиваться на описании последовательности операций, необходимых для выполнения вычислений, как в императивном программировании, символическое программирование делает упор на выражении отношений и ограничений между структурами данных, уделяя особое внимание «что», а не «как».&lt;/p&gt; &lt;p&gt;В контексте парадигм программирования символическое программирование часто противопоставляется процедурному или императивному программированию, где программы определяют пошаговые процедуры для достижения своих целей. В то время как императивное программирование фокусируется на описании потока управления с использованием таких конструкций, как циклы и условные выражения, для управления выполнением, символическое программирование сосредоточено на выражении фактов о проблеме и позволяет выполнению естественным образом выводить последующие последствия из предоставленной информации.&lt;/p&gt; @@ -2284,11 +2048,34 @@ Number 5 from the thread!&lt;/p&gt; &lt;h2 id=&#34;нативные-типы-данных&#34;&gt;Нативные типы данных&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &amp;ldquo;&lt;strong&gt;%&lt;/strong&gt;&amp;rdquo;. -В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат.&lt;/p&gt; +&lt;p&gt;Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &amp;ldquo;&lt;strong&gt;%&lt;/strong&gt;&amp;rdquo;.&lt;/p&gt; +&lt;p&gt;В случае переменных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определенный формат.&lt;/p&gt; +&lt;p&gt;Чтобы использовать уже существующие библиотеки, нужно импортировать нативный объект, +тем самым создав объкт NewLang, но с реализацией на другом языке, например на С/С++.&lt;/p&gt; +&lt;p&gt;Синтаксис импорта нативных объектов такой же, как и для &lt;a href=&#34;http://localhost:1313/ru/docs/ops/create/&#34;&gt;создания&lt;/a&gt; обычных объектов языка, +только в качестве правого операнда в операторе создания требуется указать имя нативнного объекта.&lt;/p&gt; +&lt;p&gt;При импорте нативного объекта необходимо всегда указывать типы переменных, а также типы аргументов и возвращаемых значений для функций.&lt;/p&gt; +&lt;p&gt;Если типы данных у создаваемого и нативного объекта совпадают (т.е. не требуется преобразование типов), +то нативное имя объекта можно указать с многоточием, которое означает, что типы данных будут повторять заданные у левого операнда.&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Plain&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fopen&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;filename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;StrChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;modes&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;StrChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fopen&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fclose&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fclose&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fflush&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fflush&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fprintf&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#204a87&#34;&gt;format&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FmtChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fprintf&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fremove&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;filename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;remove&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;frename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;old&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;new&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;rename&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; + +&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; +&lt;p&gt;Последующее описание находится в процессе разработки.&lt;/p&gt; + +&lt;/div&gt; + &lt;h3 id=&#34;pointer--указатель-на-системную-область-памяти-или-нативную-функцию&#34;&gt;:Pointer — указатель на системную область памяти или нативную функцию&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#pointer--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%83%d1%8e-%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8-%d0%b8%d0%bb%d0%b8-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%83%d1%8e-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8e&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Так как любой программе приходится взаимодействовать с внешним миром, т -о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, +&lt;p&gt;Так как любой программе приходится взаимодействовать с внешним миром, +то по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип &lt;em&gt;:Pointer&lt;/em&gt;. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. Но можно вывести его значение, например для отладки.&lt;/p&gt; &lt;h3 id=&#34;plain--указатель-на-представление-данных-в-бинарном-виде&#34;&gt;:Plain — указатель на представление данных в бинарном виде&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#plain--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d0%bf%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%be%d0%bc-%d0%b2%d0%b8%d0%b4%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; @@ -3050,195 +2837,105 @@ my_file.write(&amp;lsquo;hello world&amp;rsquo;)&lt;/p&gt; <description> - &lt;h2 id=&#34;dsl&#34;&gt;DSL&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#dsl&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h3 id=&#34;особенности-ассоциативной-памяти&#34;&gt;Особенности ассоциативной памяти&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d1%81%d0%be%d0%b1%d0%b5%d0%bd%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b0%d1%81%d1%81%d0%be%d1%86%d0%b8%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; + &lt;h3 id=&#34;особенности-ассоциативной-памяти&#34;&gt;Особенности ассоциативной памяти&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d1%81%d0%be%d0%b1%d0%b5%d0%bd%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b0%d1%81%d1%81%d0%be%d1%86%d0%b8%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;Синтаксис языка &lt;em&gt;NewLang&lt;/em&gt; основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например &lt;strong&gt;if&lt;/strong&gt;, чем комбинация &lt;em&gt;минус минус правая угловая скобка&lt;/em&gt; &lt;strong&gt;&amp;ndash;&amp;gt;&lt;/strong&gt;. Из-за этого имеет смысл использовать не &amp;ldquo;чистый&amp;rdquo; базовый синтаксис, а более привычный диалект с использованием ключевых слов.&lt;/p&gt; -&lt;h3 id=&#34;синтаксис-на-ключевых-словах&#34;&gt;Синтаксис на ключевых словах&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81-%d0%bd%d0%b0-%d0%ba%d0%bb%d1%8e%d1%87%d0%b5%d0%b2%d1%8b%d1%85-%d1%81%d0%bb%d0%be%d0%b2%d0%b0%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;В файле dsl.nlp находится набор макросов, которые расширяют базовый синтаксис &lt;em&gt;NewLang&lt;/em&gt;, основанный на правилах, -набором предопределенных ключевых слов как в классических языках программирования. -А при необходимости, их можно адаптировать или дополнить под собственную предметную область.&lt;/p&gt; -&lt;h2 id=&#34;константы&#34;&gt;Константы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%ba%d0%be%d0%bd%d1%81%d1%82%d0%b0%d0%bd%d1%82%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h3 id=&#34;логические&#34;&gt;Логические&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bb%d0%be%d0%b3%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; +&lt;p&gt;&lt;em&gt;NewLang&lt;/em&gt; уже содержит набор макросов, которые расширяют базовый синтаксис &lt;em&gt;NewLang&lt;/em&gt;, основанный на правилах, +набором предопределенных ключевых слов как в классических языках программирования, +которые можно адаптировать или дополнить под собственную предметную область.&lt;/p&gt; +&lt;h3 id=&#34;константы&#34;&gt;Константы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%ba%d0%be%d0%bd%d1%81%d1%82%d0%b0%d0%bd%d1%82%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; -&lt;li&gt;&lt;strong&gt;true&lt;/strong&gt; - 1&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;yes&lt;/strong&gt; - 1&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;false&lt;/strong&gt; - 0&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;no&lt;/strong&gt; - 0&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@true&lt;/em&gt; - 1&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@yes&lt;/em&gt; - 1&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@false&lt;/em&gt; - 0&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@no&lt;/em&gt; - 0&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@this&lt;/em&gt; или &lt;em&gt;@self&lt;/em&gt; - Текущий объект&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@super&lt;/em&gt; - Родительский объект&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@latter&lt;/em&gt; или &lt;em&gt;@last&lt;/em&gt;- Результат выполенения последнего оператора Result of the last operation&lt;/p&gt; +&lt;/li&gt; &lt;/ul&gt; -&lt;h3 id=&#34;системные-имена&#34;&gt;Системные имена&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%8b%d0%b5-%d0%b8%d0%bc%d0%b5%d0%bd%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; +&lt;h3 id=&#34;логические-операторы&#34;&gt;Логические операторы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bb%d0%be%d0%b3%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; -&lt;li&gt;&lt;strong&gt;this&lt;/strong&gt; - Текущий объект (&lt;strong&gt;$0&lt;/strong&gt;)&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;parent&lt;/strong&gt; - Родительский объект (&lt;strong&gt;$$&lt;/strong&gt;)&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;last&lt;/strong&gt; - Результат выполнения последнего оператора (&lt;strong&gt;$^&lt;/strong&gt;)&lt;/li&gt; +&lt;li&gt;&lt;em&gt;@and&lt;/em&gt; - Логическое &lt;strong&gt;И&lt;/strong&gt;&lt;/li&gt; +&lt;li&gt;&lt;em&gt;@or&lt;/em&gt; - Логическое &lt;strong&gt;ИЛИ&lt;/strong&gt;&lt;/li&gt; +&lt;li&gt;&lt;em&gt;@xor&lt;/em&gt; - Логическое &lt;strong&gt;Исключающее ИЛИ&lt;/strong&gt;&lt;/li&gt; +&lt;li&gt;&lt;em&gt;@not(value)&lt;/em&gt; - Логическое отрицание&lt;/li&gt; &lt;/ul&gt; -&lt;p&gt;!!!!!!!!- &lt;strong&gt;args&lt;/strong&gt; - Все аргументы функции (&lt;strong&gt;$*&lt;/strong&gt;)&lt;/p&gt; -&lt;p&gt;!!!!!!!!- &lt;strong&gt;sys&lt;/strong&gt; - Системный контекст запущенной программы (&lt;strong&gt;@@&lt;/strong&gt;) -!!!!!!!!- &lt;strong&gt;current&lt;/strong&gt; - Текущий модуль (&lt;strong&gt;@$&lt;/strong&gt;) -!!!!!!!!- &lt;strong&gt;cmd&lt;/strong&gt; - Все аргументы выполняющегося приложения из командной строки (&lt;strong&gt;@*&lt;/strong&gt;)&lt;/p&gt; -&lt;p&gt;!!!!!!!!!!1### Типовые функции и проверки -!!!!!!!!!!- &lt;strong&gt;run(&amp;lsquo;filename&amp;rsquo;)&lt;/strong&gt; - Выполнить указанный файл (&lt;strong&gt;@@(&amp;lsquo;filename&amp;rsquo;)&lt;/strong&gt;) -!!!!!!!!!!- &lt;strong&gt;ifmain&lt;/strong&gt; - Проверка, если текущий модуль основной (&lt;strong&gt;[@$.$0] &amp;ndash;&amp;gt;&lt;/strong&gt; { &amp;hellip; }) -!!!!!!!!!!- &lt;strong&gt;ifload&lt;/strong&gt; - Проверка, если текущий модуль загружается впервые (&lt;strong&gt;[@$.&lt;strong&gt;load&lt;/strong&gt;] &amp;ndash;&amp;gt;&lt;/strong&gt; { &amp;hellip; })&lt;/p&gt; &lt;h3 id=&#34;операторы&#34;&gt;Операторы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;match(cond)&lt;/strong&gt; - Оператор &lt;a href=&#34;https://newlang.net/ops.html#%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B0-%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&#34;&gt;оценки выражения&lt;/a&gt;&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@if(&amp;hellip;)&lt;/em&gt; - Первый условный оператор&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;if(&amp;hellip;)&lt;/strong&gt; - Первый условный оператор (&lt;strong&gt;[$*]&amp;ndash;&amp;gt;&lt;/strong&gt; { &amp;hellip; })&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@elif(&amp;hellip;)&lt;/em&gt; - Второй и все последующие условные операторы&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;elif(&amp;hellip;)&lt;/strong&gt; - Второй и все последующие (&lt;strong&gt;,[$*]&amp;ndash;&amp;gt;&lt;/strong&gt; { &amp;hellip; })&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@else&lt;/em&gt; - Оператор &lt;em&gt;иначе&lt;/em&gt;&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;else&lt;/strong&gt; - Оператор &lt;em&gt;иначе&lt;/em&gt; (&lt;strong&gt;,[_]&amp;ndash;&amp;gt;&lt;/strong&gt; { &amp;hellip; })&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@while(&amp;hellip;)&lt;/em&gt; - Оператор цикла с предусловием&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;while(cond)&lt;/strong&gt; - Оператор цикла с предусловием (&lt;strong&gt;[@$cond] &amp;lt;-&amp;gt;&lt;/strong&gt; { &amp;hellip; } )&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@dowhile(&amp;hellip;)&lt;/em&gt; - Оператор цикла с постусловием&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;dowhile(cond)&lt;/strong&gt; - Оператор цикла с постусловием ({ &amp;hellip; } &lt;strong&gt;&amp;lt;-&amp;gt;[@$cond]&lt;/strong&gt;)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@loop&lt;/em&gt; - Оператор безконечного цикла&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;iter(obj, &amp;hellip; )&lt;/strong&gt; - Создание итератора ( &lt;strong&gt;@$obj&lt;/strong&gt; ? (@$*) )&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@break $label&lt;/em&gt; - Оператор выхода из именованного именованного блока кода&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;next(obj, &amp;hellip; )&lt;/strong&gt; - Следующий элемент итератора ( &lt;strong&gt;@$obj&lt;/strong&gt; ! ($*) )&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@continue $label&lt;/em&gt; - Оператор прехода на начало именованного блока кода&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;curr(obj, &amp;hellip; )&lt;/strong&gt; - Текущий элемент итератора ( &lt;strong&gt;@$obj&lt;/strong&gt; !? ($*) )&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@return( result )&lt;/em&gt; - Оператор возврата значения и выхода из функции&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;first(obj)&lt;/strong&gt; - Перейти на первый элемент итератора ( &lt;strong&gt;@$obj&lt;/strong&gt; !! )&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@throw( error )&lt;/em&gt; - Оператор создания исключения и возврата ошибки&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;all(obj)&lt;/strong&gt; - Получить сразу все элементы итератора ( &lt;strong&gt;@$obj&lt;/strong&gt; ??)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@match( &amp;hellip; )&lt;/em&gt; - Оператор оценки выражения&lt;/p&gt; &lt;/li&gt; -&lt;/ul&gt; -&lt;h3 id=&#34;прерывания&#34;&gt;Прерывания&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b5%d1%80%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;ul&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;return&lt;/strong&gt; - Положительное прерывание (&lt;strong&gt;++&lt;/strong&gt;)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@case( &amp;hellip; )&lt;/em&gt; - Оператор сравнения с образцом&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;return(&amp;hellip;)&lt;/strong&gt;- Положительное прерывание с возвратом значения (&lt;strong&gt;++&lt;/strong&gt; @$value &lt;strong&gt;++&lt;/strong&gt;)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@default&lt;/em&gt; - Оператор выбора по улочанию&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;error&lt;/strong&gt; - Отрицательное прерывание (&lt;strong&gt;--&lt;/strong&gt;)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@iter(obj, &amp;hellip; )&lt;/em&gt; - Создание итератора&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;error(&amp;hellip;)&lt;/strong&gt; - Отрицательное прерывание с возвратом значения (&lt;strong&gt;--&lt;/strong&gt; @$value &lt;strong&gt;--&lt;/strong&gt;)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@next(obj, &amp;hellip; )&lt;/em&gt; - Получить следующий элемент итератора&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;break+&lt;/strong&gt; и &lt;strong&gt;break-&lt;/strong&gt; - Выход из цикла:&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@curr(obj, &amp;hellip; )&lt;/em&gt; - Получить текущий элемент итератора&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@first(obj)&lt;/em&gt; - Перейти на первый элемент итератора&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@all(obj)&lt;/em&gt; - Получить сразу все элементы итератора&lt;/p&gt; &lt;/li&gt; &lt;/ul&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; while(...) {+ - ++ :Break ++ - +} - while(...) {- - -- :Break -- - -} -&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt; -&lt;li&gt;&lt;strong&gt;continue+&lt;/strong&gt; и &lt;strong&gt;continue-&lt;/strong&gt; - В начало цикла:&lt;/li&gt; -&lt;/ul&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; while(...) {+ - ++ :Continue ++ - +} - while(...) {- - -- :Continue -- - -} -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;obj { -.field = 1; -.prop(); -};&lt;/p&gt; -&lt;p&gt;#Python&lt;/p&gt; -&lt;h1 id=&#34;1-without-using-with-statement&#34;&gt;1) without using with statement&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#1-without-using-with-statement&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;file = open(&amp;lsquo;file_path&amp;rsquo;, &amp;lsquo;w&amp;rsquo;) -file.write(&amp;lsquo;hello world !&amp;rsquo;) -file.close()&lt;/p&gt; -&lt;h1 id=&#34;2-without-using-with-statement&#34;&gt;2) without using with statement&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#2-without-using-with-statement&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;file = open(&amp;lsquo;file_path&amp;rsquo;, &amp;lsquo;w&amp;rsquo;) -try: -file.write(&amp;lsquo;hello world&amp;rsquo;) -finally: -file.close()&lt;/p&gt; -&lt;p&gt;open(&amp;lsquo;file_path&amp;rsquo;, &amp;lsquo;w&amp;rsquo;) { -.write(&amp;lsquo;hello world !&amp;rsquo;); -.close(); -}&lt;/p&gt; -&lt;p&gt;Python3&lt;/p&gt; -&lt;h1 id=&#34;using-with-statement&#34;&gt;using with statement&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#using-with-statement&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;with open(&amp;lsquo;file_path&amp;rsquo;, &amp;lsquo;w&amp;rsquo;) as file: -file.write(&amp;lsquo;hello world !&amp;rsquo;)&lt;/p&gt; -&lt;h1 id=&#34;a-simple-file-writer-object&#34;&gt;a simple file writer object&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#a-simple-file-writer-object&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;class MessageWriter(object): -def &lt;strong&gt;init&lt;/strong&gt;(self, file_name): -self.file_name = file_name&lt;/p&gt; -&lt;pre&gt;&lt;code&gt;def __enter__(self): - self.file = open(self.file_name, &#39;w&#39;) - return self.file - -def __exit__(self, *args): - self.file.close() -&lt;/code&gt;&lt;/pre&gt; -&lt;h1 id=&#34;using-with-statement-with-messagewriter&#34;&gt;using with statement with MessageWriter&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#using-with-statement-with-messagewriter&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;with MessageWriter(&amp;lsquo;my_file.txt&amp;rsquo;) as xfile: -xfile.write(&amp;lsquo;hello world&amp;rsquo;)&lt;/p&gt; -&lt;h1 id=&#34;a-simple-file-writer-object-1&#34;&gt;a simple file writer object&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#a-simple-file-writer-object-1&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;:MessageWriter { -def &lt;strong&gt;init&lt;/strong&gt;(self, file_name): -self.file_name = file_name&lt;/p&gt; -&lt;pre&gt;&lt;code&gt;def __enter__(self): - self.file = open(self.file_name, &#39;w&#39;) - return self.file - -def __exit__(self, *args): - self.file.close() -&lt;/code&gt;&lt;/pre&gt; -&lt;p&gt;}&lt;/p&gt; -&lt;h1 id=&#34;using-with-statement-with-messagewriter-1&#34;&gt;using with statement with MessageWriter&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#using-with-statement-with-messagewriter-1&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;MessageWriter(&amp;lsquo;my_file.txt&amp;rsquo;) { -.write(&amp;lsquo;hello world&amp;rsquo;); -};&lt;/p&gt; -&lt;p&gt;from contextlib import contextmanager&lt;/p&gt; -&lt;p&gt;class MessageWriter(object): -def &lt;strong&gt;init&lt;/strong&gt;(self, filename): -self.file_name = filename&lt;/p&gt; -&lt;pre&gt;&lt;code&gt;@contextmanager -def open_file(self): - try: - file = open(self.file_name, &#39;w&#39;) - yield file - finally: - file.close() -&lt;/code&gt;&lt;/pre&gt; -&lt;h1 id=&#34;usage&#34;&gt;usage&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#usage&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;message_writer = MessageWriter(&amp;lsquo;hello.txt&amp;rsquo;) -with message_writer.open_file() as my_file: -my_file.write(&amp;lsquo;hello world&amp;rsquo;)&lt;/p&gt; -&lt;p&gt;:MessageWriter(object) { -def &lt;strong&gt;init&lt;/strong&gt;(self, filename): -self.file_name = filename&lt;/p&gt; -&lt;pre&gt;&lt;code&gt;@contextmanager -def open_file(self): - try: - file = open(self.file_name, &#39;w&#39;) - yield file - finally: - file.close() -&lt;/code&gt;&lt;/pre&gt; -&lt;p&gt;}&lt;/p&gt; -&lt;h1 id=&#34;usage-1&#34;&gt;usage&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#usage-1&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;message_writer = MessageWriter(&amp;lsquo;hello.txt&amp;rsquo;) -with message_writer.open_file() as my_file: -my_file.write(&amp;lsquo;hello world&amp;rsquo;)&lt;/p&gt; -&lt;h1 id=&#34;приложения&#34;&gt;Приложения&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b8%d0%bb%d0%be%d0%b6%d0%b5%d0%bd%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;предопределенные-макросы&#34;&gt;Предопределенные макросы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b5%d0%b4%d0%be%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%bd%d1%8b%d0%b5-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;При работе парсера &lt;em&gt;NewLang&lt;/em&gt; автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. +&lt;p&gt;При работе парсера &lt;em&gt;NewLang&lt;/em&gt; автоматически формируются несколько зарезервированных макросов, +часть из которых соответствуют макросам препроцессора у С/С++. Данные предопределенные макросы можно использовать как обычные константы.&lt;/p&gt; &lt;ul&gt; &lt;li&gt; diff --git a/docs/ru/docs/syntax/_print/index.html b/docs/ru/docs/syntax/_print/index.html index f19b2890..77c7302f 100644 --- a/docs/ru/docs/syntax/_print/index.html +++ b/docs/ru/docs/syntax/_print/index.html @@ -798,7 +798,8 @@ <h3 id="пример-программы">Пример программы<a class <h1 id="pg-66431dc9242fce562d24bb69bdc576f3">5 - Макросы</h1> - <p>Макросы в <strong>NewLang</strong>, это один или несколько последовательных терминов, которые заменяются на другой термин + <p>Макросы используются и для превращеня исходного кода <em>NewLang</em> в более привычный синтаксис на основе <a href="https://newlang.net/syntax_dsl.html">ключевых слов</a>, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода.</p> +<p>Макросы в <strong>NewLang</strong>, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем).</p> <p>Макросы обработываются во время работы <strong>лексера</strong>, т.е. перед передачей последовательности лексем в парсер, что позволяет с помощью маросов изменять фрагменты синтаксиса языка, например, при реализации собственных диалектов DSL.</p> @@ -833,13 +834,13 @@ <h3 id="определение-макросов">Определение макр с одинаковыми именами, один из которых будет с аргументами (скобками), а другой без них.</p> <p>Поэтому, если требуется использовать макрос в двух разных вариантах (с аргументами и без оных), следует определять макрос без аргументов и в этом случае контроль параметров будет выполнятся компилятором.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> @@macro@@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Макрос без аргументов</span> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> @@ macro @@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Макрос без аргументов</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> macro<span style="color:#ce5c00;font-weight:bold">(</span>args<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># ОК -&gt; term(args);</span> </span></span><span style="display:flex;"><span> macro<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># ОК -&gt; term;</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Но </span> -</span></span><span style="display:flex;"><span> @@call<span style="color:#ce5c00;font-weight:bold">()</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> @@ call<span style="color:#ce5c00;font-weight:bold">()</span> @@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> call<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># ОК -&gt; term();</span> </span></span><span style="display:flex;"><span> call<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Ошибка (@call определен с аргументами) </span> @@ -852,286 +853,49 @@ <h3 id="определение-макросов">Определение макр <p>По аналогии с препроцессором С/С++, для соединения двух лексем в одну, в теле макроса используется оператор <strong>&quot;@##&quot;</strong>, а для преобразование лексемы в текстову строку применяется операторы <strong>@#</strong>, <strong>@#&quot;</strong> или <strong>@#&rsquo;</strong>, например, <code>@@macro($arg)@@ := @@ func_ @## @$arg( @#&quot; arg ) @;</code>, тогда вызов <code>macro(name);</code> будет преобразован в <code>func_name (&quot;name&quot;);</code></p> - - -<div class="pageinfo pageinfo-primary"> -<h4 id="ограничения-макропроцессора-в-текущей-версии">Ограничения макропроцессора в текущей версии<a class="td-heading-self-link" href="#%d0%be%d0%b3%d1%80%d0%b0%d0%bd%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d0%bf%d1%80%d0%be%d1%86%d0%b5%d1%81%d1%81%d0%be%d1%80%d0%b0-%d0%b2-%d1%82%d0%b5%d0%ba%d1%83%d1%89%d0%b5%d0%b9-%d0%b2%d0%b5%d1%80%d1%81%d0%b8%d0%b8" aria-label="Heading self-link"></a></h4> -<p>На текущий момент макросы реализованы в минимальном объеме для самых простых сценариев использования:</p> -<ul> -<li>DSL для keyword based syntax (if, else, return, match, while и т.д.) - (1 термин с произвольными аргументами и без) - требуется сейчас !!!</li> -</ul> -<p><em>Парсер при обработке макросов может анализировать информацию о типах данных, если она указана.</em> -<em>Но на текущий момент типы данных в макросах никак не обрабатываются и это одна из обязательных фич, которая будет реализована в будущем.</em></p> -<ul> -<li>Определения (func, class) - (несколько терминов с аргументами и без аргументов) - Реализация ООП и импорт С++ классов</li> -<li>Модификации при определениях (override) - (несколько терминов и шаблоны с аргументами и без аргументов) - Реализация ООП и импорт С++ классов</li> -</ul> - -</div> - -<h1 id="макросы-без-аргументов-или-все-аргументы-сразу-">МАКРОСЫ БЕЗ АРГУМЕНТОВ ИЛИ ВСЕ АРГУМЕНТЫ СРАЗУ !!!!!<a class="td-heading-self-link" href="#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b1%d0%b5%d0%b7-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d0%b8%d0%bb%d0%b8-%d0%b2%d1%81%d0%b5-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d1%8b-%d1%81%d1%80%d0%b0%d0%b7%d1%83-" aria-label="Heading self-link"></a></h1> -<h1 id="анализа-аргументов-или-их-типов-не-производится-">анализа аргументов или их типов не производится !!!<a class="td-heading-self-link" href="#%d0%b0%d0%bd%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d0%b8%d0%bb%d0%b8-%d0%b8%d1%85-%d1%82%d0%b8%d0%bf%d0%be%d0%b2-%d0%bd%d0%b5-%d0%bf%d1%80%d0%be%d0%b8%d0%b7%d0%b2%d0%be%d0%b4%d0%b8%d1%82%d1%81%d1%8f-" aria-label="Heading self-link"></a></h1> -<p>Lambda -@@ lambda $name(&hellip;) @@ ::= @@ @$name( @$&hellip; ) ::= ( _( @$&hellip; ) ::= @<strong>PRAGMA_FINALIZE</strong>( @), {, {+, {-, {* ) @@</p> -<h3 id="примеры-использования-макросов">Примеры использования макросов<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80%d1%8b-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2" aria-label="Heading self-link"></a></h3> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Обычные макросы (тело макроса корректное выражение)</span> -</span></span><span style="display:flex;"><span> @@macro@@ :<span style="color:#ce5c00;font-weight:bold">=</span> replace<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@macro2<span style="color:#ce5c00;font-weight:bold">(</span>arg<span style="color:#ce5c00;font-weight:bold">)</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">{</span> call<span style="color:#ce5c00;font-weight:bold">(</span>@<span style="color:#000">$arg</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> call<span style="color:#ce5c00;font-weight:bold">()}</span><span style="color:#000;font-weight:bold">;</span> +<p>Примеры использования макросов:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Обычные макросы (тело макроса корректное выражение)</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000">macro</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000">replace</span><span style="color:#000;font-weight:bold">();</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000">macro2</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">arg</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000;font-weight:bold">{</span> <span style="color:#000">call</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#a40000">$</span><span style="color:#000">arg</span><span style="color:#000;font-weight:bold">);</span> <span style="color:#000">call</span><span style="color:#000;font-weight:bold">()};</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Тело макросов из последовательности лексем</span> -</span></span><span style="display:flex;"><span> @@if<span style="color:#ce5c00;font-weight:bold">(</span>...<span style="color:#ce5c00;font-weight:bold">)</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ <span style="color:#ce5c00;font-weight:bold">[</span> <span style="color:#4e9a06">\$</span><span style="color:#204a87;font-weight:bold">if</span><span style="color:#ce5c00;font-weight:bold">(</span>*<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">]</span>--&gt; @@<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Выражение может быть не полным</span> -</span></span><span style="display:flex;"><span> @@elif<span style="color:#ce5c00;font-weight:bold">(</span>...<span style="color:#ce5c00;font-weight:bold">)</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ ,<span style="color:#ce5c00;font-weight:bold">[</span> <span style="color:#4e9a06">\$</span><span style="color:#204a87;font-weight:bold">elif</span><span style="color:#ce5c00;font-weight:bold">(</span>*<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">]</span>--&gt; @@<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@else@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ ,<span style="color:#ce5c00;font-weight:bold">[</span>_<span style="color:#ce5c00;font-weight:bold">]</span>--&gt; @@<span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#204a87;font-weight:bold">if</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000;font-weight:bold">[</span> <span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#a40000">$</span><span style="color:#ce5c00;font-weight:bold">...</span> <span style="color:#000;font-weight:bold">]</span><span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#ce5c00;font-weight:bold">@@</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Выражение может быть не полным</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#204a87;font-weight:bold">elif</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000;font-weight:bold">,[</span> <span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#a40000">$</span><span style="color:#ce5c00;font-weight:bold">...</span> <span style="color:#000;font-weight:bold">]</span><span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#ce5c00;font-weight:bold">@@</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000;font-weight:bold">,[</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">]</span><span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#ce5c00;font-weight:bold">@@</span><span style="color:#000;font-weight:bold">;</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Запись условного оператора с использованием </span> </span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># определенных выше макросов</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">if</span><span style="color:#ce5c00;font-weight:bold">(</span> condition <span style="color:#ce5c00;font-weight:bold">){</span> -</span></span><span style="display:flex;"><span> ... -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">elif</span><span style="color:#ce5c00;font-weight:bold">(</span> condition2 <span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> ... -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#ce5c00;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> ... -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>Зачем нужна трансформация синтаксиса? -Нативная поддержка других языков нужна чтобы не переписывать легаси код на этих языках.</p> -<p>Чтобы можно было использовать существующие исходники как собственные требуется настройка работы -препроцессора и лексера под конкретный язык программирования (описание DSL). -Для <strong>С/С++</strong> потребуется выделять лексером комментарии из-за пересечения синтаксиса (которые сейчас игнорируются). -Для <strong>Python</strong> требуется выделять лексером отступы (которые сейчас тоже игнорируются), причем потребуется реализация не только синтаксиса, -но и зависимых пакетов с последующая трансляцией этого кода в С++, что в настоящий момент делать не целесообразно (cython ???).</p> -<p>Но так как возможность трансформации кода с других языков программирования принципиальная возможна, -стоит над этим думать только после полноценного релиза NewLang и его перехода в прод.</p> -<p>Для реализации DSL требуется передача команд в парсер для управления его работой (по аналогии с командой #pragma) -Но так как обработка таких команд должна происходить в лексере до передачи данных в парсер (анализатор), -то команды для макропроцессора должны быть в максимально простом виде и состоять из элементов, -которые лексер может самостоятельно идентифицировать, т.е. термины, строки и цифры (без выражений и именованных аргументов).</p> -<p>После обработки такой команды она анализируется макропроцессором и удаляется из потока лексем, т.е. в парсер (анализатор) не передается. -Но в случае ошибки с синтаксисе, данные команды нужно уметь однозначно идентифировать и самый простой способ, -комбинация признака макроса и системного имени, т.е. что-то вроде</p> -<pre tabindex="0"><code> @__PRAGMA_DIAG__(push) - @__PRAGMA_DIAG__(ignored, &#34;-Wundef&#34;) - @__PRAGMA_DIAG__(warning, &#34;-Wformat&#34;) - @__PRAGMA_DIAG__(error &#34;-Wuninitialized&#34;) - @__PRAGMA_DIAG__(pop) - - #pragma message &#34;Compiling &#34; __FILE__ &#34;...&#34; - @__PRAGMA_MESSAGE__(&#34;Compiling &#34;, __FILE__, &#34;...&#34;) - - #pragma error &#34;Error &#34; __FILE__ &#34;...&#34; - @__PRAGMA_ERROR__(&#34;Error &#34;, __FILE__, &#34;...&#34;) - - -#define DO_PRAGMA(x) _Pragma (#x) -#define TODO(x) DO_PRAGMA(message (&#34;TODO - &#34; #x)) - -@@TODO( ... )@@ := @__PRAGMA_MESSAGE__(&#34;TODO - &#34;, @*) - -@TODO(Remember to fix this) # note: TODO - Remember to fix this - -\\.__lexer__ignore_space__ = 1; -\\.__lexer__ignore_indent__ = 1; -\\.__lexer__ignore_comment__ = 1; -\\.__lexer__ignore_crlf__ = 1; -</code></pre><p>Таким образом можно трансформировать условный оператор на питоне в синтаксис NewLang следующим макросом:</p> -<pre tabindex="0"><code> -#pragma clang attribute push -#pragma clang diagnostic ignored &#34;-Wundef&#34; -#pragma clang diagnostic ignored &#34;-Wunused-variable&#34; - - -#elif __GNUC__ - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored &#34;-Wuninitialized&#34; - -#pragma GCC diagnostic ignored &#34;-Wall&#34; -#pragma GCC diagnostic ignored &#34;-Wextra&#34; - - @pragma warning(pop) - - @@ pragma warning(...) @@ := __PRAGMA_TERM_DIAG_WARNING__(); -@__PRAGMA_DIAG__(warning, pop); +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@if</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">condition</span> <span style="color:#000;font-weight:bold">){</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">...</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> <span style="color:#5c35cc;font-weight:bold">@elif</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">condition2</span> <span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">...</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> <span style="color:#5c35cc;font-weight:bold">@else</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">...</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span></code></pre></div><p>Например цикл до 5:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">[</span> <span style="color:#0000cf;font-weight:bold">1</span> <span style="color:#000;font-weight:bold">]</span> <span style="color:#ce5c00;font-weight:bold">&lt;-&gt;</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">[</span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#0000cf;font-weight:bold">5</span> <span style="color:#000;font-weight:bold">]</span> <span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">--</span> <span style="color:#0000cf;font-weight:bold">42</span> <span style="color:#ce5c00;font-weight:bold">--</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span><span style="display:flex;"><span> <span style="color:#000">count</span><span style="color:#ce5c00;font-weight:bold">+=</span><span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span></code></pre></div><p>Будет выглядеть более привычно:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@while</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">true</span> <span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@if</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#0000cf;font-weight:bold">5</span> <span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@return</span> <span style="color:#0000cf;font-weight:bold">42</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span><span style="display:flex;"><span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">+=</span> <span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span></code></pre></div> -Обработка терминов в макропроцессоре в максимально простом виде. -Агрументы только термины, строки и цифры без вложенных выражений и именованных аргументов, -т.е. только элементы, которые может самостоятельно идентифицировать лексер. +<div class="pageinfo pageinfo-primary"> +<h3 id="далее-идеи-на-будущее">Далее идеи на будущее<a class="td-heading-self-link" href="#%d0%b4%d0%b0%d0%bb%d0%b5%d0%b5-%d0%b8%d0%b4%d0%b5%d0%b8-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5" aria-label="Heading self-link"></a></h3> +<h3 id="символьное-программирование">Символьное программирование<a class="td-heading-self-link" href="#%d1%81%d0%b8%d0%bc%d0%b2%d0%be%d0%bb%d1%8c%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> -@warning(&#34;--&#34;) - @@ if ... : @@ := @@ [ @$* ]-&gt; __TERM_BLOCK_INDENT__(&#34;{&#34;, force_semicolon=1) @@ - - if __name__ == &#34;__main__&#34;: - run1() - run2() +</div> - [ __name__ == &#34;__main__&#34; ]-&gt; { - run1(); - run2(); - }; - - -</code></pre><p>Ключ &ndash;parser-syntax-only только текстовый парсинг исходного кода без загрузки модулей, раскрытия макросов и проверки имен.</p> -<p>Ключ &ndash;parser-no-macros - без раскрытия макросов -Ключ &ndash;parser-no-module - без загрузки модулей (и мокросов, если они в них определяются) -Ключ &ndash;parser-no-check-prototype - без проверки имен при обращении</p> -<p>prototype -@<strong>PRAGMA_PROTOTYPE</strong>(define) -@<strong>PRAGMA_PROTOTYPE</strong>(implement)</p> -<p>$$</p> -<p>\$ - корень системы (система)</p> -<p>$ - текущий модуль</p> -<h1 id="макросы-для-конвертора-проверки-в-python">Макросы для конвертора проверки в Python<a class="td-heading-self-link" href="#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b4%d0%bb%d1%8f-%d0%ba%d0%be%d0%bd%d0%b2%d0%b5%d1%80%d1%82%d0%be%d1%80%d0%b0-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b8-%d0%b2-python" aria-label="Heading self-link"></a></h1> -<h1 id="if-__name__--__main__">if <strong>name</strong> == &ldquo;<strong>main</strong>&rdquo;:<a class="td-heading-self-link" href="#if-__name__--__main__" aria-label="Heading self-link"></a></h1> -<p>@@ <strong>name</strong> @@ ::= @@ $. @<strong>PRAGMA_NO_MACRO</strong>() <strong>name</strong> @@ -@@ if $&hellip; @: @@ ::= @@ [ @$&hellip; ] &ndash;&gt; @@</p> -<p>@if( $.<strong>name</strong> == &ldquo;<strong>main</strong>&rdquo; ) {</p> -<p>}</p> -<p>\каталог\модуль() - статический импорт модуля -\(&ldquo;каталог\модуль&rdquo;)() - динамический импорт модуля</p> -<p>printf := :Pointer(&lsquo;printf(format:FmtChar, &hellip;):Int32&rsquo;); -printf := %printf(format:FmtChar, &hellip;):Int32;</p> -<h1 id="регистрация-прототипа-нативной-функции">Регистрация прототипа нативной функции<a class="td-heading-self-link" href="#%d1%80%d0%b5%d0%b3%d0%b8%d1%81%d1%82%d1%80%d0%b0%d1%86%d0%b8%d1%8f-%d0%bf%d1%80%d0%be%d1%82%d0%be%d1%82%d0%b8%d0%bf%d0%b0-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h1> -<p>@prototype -%puts(format:StrChar):Int32;</p> -<h1 id="импорт-нативной-функции-с-предварительной-проверкой-её-наличия-во-время-компиляции-статическая-линковка">Импорт нативной функции с предварительной проверкой её наличия во время компиляции (статическая линковка)<a class="td-heading-self-link" href="#%d0%b8%d0%bc%d0%bf%d0%be%d1%80%d1%82-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d1%81-%d0%bf%d1%80%d0%b5%d0%b4%d0%b2%d0%b0%d1%80%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d0%be%d0%b9-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%be%d0%b9-%d0%b5%d1%91-%d0%bd%d0%b0%d0%bb%d0%b8%d1%87%d0%b8%d1%8f-%d0%b2%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d1%8f-%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%86%d0%b8%d0%b8-%d1%81%d1%82%d0%b0%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bb%d0%b8%d0%bd%d0%ba%d0%be%d0%b2%d0%ba%d0%b0" aria-label="Heading self-link"></a></h1> -<p>puts2(format:StrChar):Int32 := %puts(format:StrChar):Int32;</p> -<h1 id="импорт-нативной-функции-по-её-прототипу-во-время-выполнения-динамическая-линковка">Импорт нативной функции по её прототипу во время выполнения (динамическая линковка)<a class="td-heading-self-link" href="#%d0%b8%d0%bc%d0%bf%d0%be%d1%80%d1%82-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d0%bf%d0%be-%d0%b5%d1%91-%d0%bf%d1%80%d0%be%d1%82%d0%be%d1%82%d0%b8%d0%bf%d1%83-%d0%b2%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d1%8f-%d0%b2%d1%8b%d0%bf%d0%be%d0%bb%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b4%d0%b8%d0%bd%d0%b0%d0%bc%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bb%d0%b8%d0%bd%d0%ba%d0%be%d0%b2%d0%ba%d0%b0" aria-label="Heading self-link"></a></h1> -<p>puts3(format:StrChar):Int32 := :Pointer(&lsquo;puts(format:StrChar):Int32&rsquo;);</p> -<p>%puts(&lsquo;Тест вывода строки&rsquo;); # Линковка с нативной функцией во время компиляции и непосредственный вызов с оптимизацией передачи параметров -puts2(&lsquo;Тест 2 вывода строки&rsquo;); # Линковка с нативной функцией во время компиляции -puts3(&lsquo;Тест 3 вывода строки&rsquo;); # Линковка с нативной функцией во время выполнения при первом вызове puts3</p> -<ul> -<li>Парсинг исходного текста без раскрытия макросов и загрузки модулей</li> -<li>Парсинг исходного текста с раскрытием макросов (требуется загрузка модулей для зависимых и переопределяемых макросов)</li> -<li>Загружатся модули могут как в виде исходников (которые требуется парсить и компилировть/выполнять) -или в виде бинарников (в них должны быть список макросов, типов и имена объектов)</li> -<li>После парсинга получается список <strong>имен</strong> макросов, типов и объектов (TermPtr)</li> -<li>После выполнения модуля - список <strong>имен</strong> заполняется реальными объектами (ObjPtr).</li> -</ul> -<h1 id="компиляция-файла">Компиляция файла<a class="td-heading-self-link" href="#%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%86%d0%b8%d1%8f-%d1%84%d0%b0%d0%b9%d0%bb%d0%b0" aria-label="Heading self-link"></a></h1> -<ul> -<li>Парсинг исходника для построения AST (без анализа имен, связей, загрузки модулей и пр. только исходые тексты с раскрытием макросов</li> -<li></li> -</ul> -<h1 id="систематизация-реализации-макросов">Систематизация реализации макросов<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0%d1%82%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d1%80%d0%b5%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d0%b8-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2" aria-label="Heading self-link"></a></h1> -<p>последовательность лексем MACRO_SEQ мужду @@ @@ сохраняется в m_block, так как фрагменты блоков не могут быть идентификаторами</p> -<p>Разбор макросов происходит в лексере. Определением макроса всегда является целая строка, -которая заканчивается точкой с запятой, а идентификатором макроса всегда выступает последовательность лексем:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> @@ id @@ :<span style="color:#ce5c00;font-weight:bold">=</span> macro<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@ id @@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ @@<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@ id @@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@@ @@@<span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>Хранилищем текущих максросов является объект класса MacroBuffer. -Последовательность лексем идентификатора (id) макроса должна сохраняется в отдельном поле термина и однозначно его идентифицирует. -Первый термин в идентификаторе хранится как ключ hashmap, а дальше происходит поиск полным перебором. -Этапы работы с макросами</p> -<ul> -<li> -<p>Входные термины из лексера получаются вызовом GetNextToken, внутри которой и происходит раскрытие макросов. -Внутренний буфер заполняется до окончания строки (выражения), т.е. до символа &lsquo;;&rsquo; или <END>, после чего производится -поиск макросов в объекте MacroBuffer для текущей последовательности лексем в буфере.</p> -</li> -<li> -<p>Если макрос найден, то соответствющая ему последоваетльность заменяется на тело макроса и происходит переход -на повторный анализ входного буфера.</p> -</li> -<li> -<p>Если макрос не найден, то данные передаются в парсер для дальнейшего синтаксическго анализа.</p> -</li> -<li> -<p>Для этого во входном потоке лексем (parser.y) во время оператората создания/присвоения вызывается функция проверки на макрос. -MacroBuffer::CheckMacroAndConvertDel($$), и после этого выходному значению присваивается результат выполнения driver.MacroEval($$), -и в дальнейшем этот макрос никак не обработывается.</p> -</li> -<li> -<p>Создание макросов, проверка на дубликаты и логические ошибки в определении происходит путем обращения к методам объекта MacroBuffer.</p> -<p>/*</p> -<ul> -<li>Макросы хрянтся как фрагменты AST в виде объектов типа Term,</li> -<li>так как создаются после обработки парсером по правилам стандратной грамматики.</li> -<li></li> -<li>Но анализ входных данных на предмет раскрытия макросов проиходит из потока (последовательности) лексем,</li> -<li>т.е. <strong>ДО</strong> обработки парсером, так как при раскрытии макросов может меняться грамматика выражений.</li> -<li></li> -<li>Функция \ref CompareMacro сравнивает входной буфер (последовательность лексем)</li> -<li>на предмет возможного соответствия одному конкретному макросу.</li> -<li>Сравниваются только ключевые словам без учета аргументов в скобках,</li> -<li>но само наличие аргументов проверяется ??????????????????</li> -<li></li> -<li>Проблема:</li> -<li>К функции можно обратится с целью её вызова (указав после имени скобки),</li> -<li>так и по имени без скобок (например для получения ссылки на объект).</li> -<li>Так и к переменной можно обратиться только по имени,</li> -<li>так и указав скобки после имени как к функции (при копировании объекта).</li> -<li></li> -<li>Сделать один макрос под оба сценария (со скобками и без скобок) не получится, так как непонятно,</li> -<li>что делать с аргументами при раскрытии тела макроса, когда они не указаны.</li> -<li></li> -<li>Но может быть следует переименовывать только одно имя без учета скобок,</li> -<li>например, оставив такую возможность только для одиночных макросов.</li> -<li></li> -<li>\name -&gt; name или name (&hellip;), hash: name</li> -<li>но \name(&hellip;) -&gt; name(&hellip;), а name - ошибка !!!! hash: name</li> -<li></li> -<li>Или все же следует различать макросы со скобками и без скобок как два разных объекта???</li> -<li>\name := name2; и \name(&hellip;) := name2(&hellip;); будут разными объектами</li> -<li></li> -<li>Или добавить макросы-алиасы без аргументов только для переименования отдельных терминов?</li> -<li>\alias :- name2; но как их отличать от обычных макросов в операции удаления?</li> -<li>Или вообще не нужно отличать и оставить только один варинат (либо макрос, либо алиас)</li> -<li>Тода вопрос со скобками закрывается сам собой, алиасы всегда без скобок,</li> -<li>макросы со скбками или без скобок, но должно быть полное соответствие.</li> -<li></li> -<li>@ name name2 @ -&gt; name name2, но name name2(&hellip;) - ошибка!!! (hash: name,name2)</li> -<li>@ name name2(&hellip;) @ -&gt; name name2(&hellip;), но name name2 - ошибка !!!! (hash: name,name2)</li> -<li>@ name name2<a href="...">&hellip;</a> @ -&gt; name name2<a href="...">&hellip;</a>, но name name2 - ошибка !!!! ( hash: name,name2 )</li> -<li>@ name $tmpl<a href="...">&hellip;</a> name3@ -&gt; name $tmpl<a href="...">&hellip;</a> name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )</li> -<li></li> -<li>Но!</li> -<li>@ name name2 @ ::- -&gt; name name2 - ок, но name name2(&hellip;) - ок</li> -<li>@ name $tmpl name3@ ::- -&gt; name $tmpl<a href="...">&hellip;</a> name3 - ок, name $tmpl(&hellip;) name3[&hellip;] - ок</li> -<li></li> -<li></li> -<li></li> -<li>Для последовательности лексем требуется полное соответствие с учетом скобок ???</li> -<li>и может ли быть несколько скобок одного типа (несколько крыглях, или несколько квардратных????</li> -<li>&lt;Может быть несколько скобок одного типа, например, при указании типа у аргументов или типа возвращаемого значения.&gt;</li> -<li></li> -<li>@ name name2 @ -&gt; name name2, но name name2(&hellip;) - ошибка!!! (hash: name,name2)</li> -<li>@ name name2(&hellip;) @ -&gt; name name2(&hellip;), но name name2 - ошибка !!!! (hash: name,name2)</li> -<li>@ name name2<a href="...">&hellip;</a> @ -&gt; name name2<a href="...">&hellip;</a>, но name name2 - ошибка !!!! ( hash: name,name2 )</li> -<li>@ name $tmpl<a href="...">&hellip;</a> name3@ -&gt; name $tmpl<a href="...">&hellip;</a> name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )</li> -<li></li> -<li>Проблема скобок возникает из-за сценария замены одного термина на другой,</li> -<li>который есть в препроцессоре С/С++, но отсутствует при реализации с использованием шаблонов.</li> -<li></li> -<li></li> -</ul> -<p>*/</p> -</li> -</ul> -<p>Макросы используются и для превращеня исходного кода <em>NewLang</em> в более привычный синтаксис на основе <a href="https://newlang.net/syntax_dsl.html">ключевых слов</a>, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода.</p> -<p><a href="https://newlang.net/syntax_dsl.html">Например:</a>.</p> -<pre tabindex="0"><code> @@if(...)@@ ::= @@ [ \$* ]--&gt; @@; - @@while(...)@@ ::= @@ [\$*] &lt;-&gt; @@; - @@return $arg@@::= @@ -- \$arg -- @@; - @@true@@ ::= 1; -</code></pre><p>Тогда цикл до 5:</p> -<pre tabindex="0"><code>count:=1; -[ 1 ] &lt;-&gt; { - [count&gt;5] --&gt; { - -- 42 --; - }; - count+=1; -}; -</code></pre><p>будет выглядеть более привычно</p> -<pre tabindex="0"><code>count:=1; -while( true ) { - if(count&gt;5) { - return 42; - }; - count+=1; -}; -</code></pre><h2 id="идеи-на-будущее">Идеи на будущее<a class="td-heading-self-link" href="#%d0%b8%d0%b4%d0%b5%d0%b8-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5" aria-label="Heading self-link"></a></h2> -<h3 id="символьное-программирование">Символьное программирование<a class="td-heading-self-link" href="#%d1%81%d0%b8%d0%bc%d0%b2%d0%be%d0%bb%d1%8c%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> <blockquote> <p>Символьное программирование, часто называемое декларативным программированием, представляет собой парадигму программирования, которая использует математическую логику, отношения и символы для представления знаний и помощи в решении проблем. Вместо того, чтобы сосредотачиваться на описании последовательности операций, необходимых для выполнения вычислений, как в императивном программировании, символическое программирование делает упор на выражении отношений и ограничений между структурами данных, уделяя особое внимание «что», а не «как».</p> <p>В контексте парадигм программирования символическое программирование часто противопоставляется процедурному или императивному программированию, где программы определяют пошаговые процедуры для достижения своих целей. В то время как императивное программирование фокусируется на описании потока управления с использованием таких конструкций, как циклы и условные выражения, для управления выполнением, символическое программирование сосредоточено на выражении фактов о проблеме и позволяет выполнению естественным образом выводить последующие последствия из предоставленной информации.</p> @@ -1862,195 +1626,105 @@ <h2 id="предопределенные-макросы">Предопредел <h1 id="pg-8e386bb5b373d09fe8bcbec82c31b73f">9 - Keyword syntax (DSL)</h1> - <h2 id="dsl">DSL<a class="td-heading-self-link" href="#dsl" aria-label="Heading self-link"></a></h2> -<h3 id="особенности-ассоциативной-памяти">Особенности ассоциативной памяти<a class="td-heading-self-link" href="#%d0%be%d1%81%d0%be%d0%b1%d0%b5%d0%bd%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b0%d1%81%d1%81%d0%be%d1%86%d0%b8%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8" aria-label="Heading self-link"></a></h3> + <h3 id="особенности-ассоциативной-памяти">Особенности ассоциативной памяти<a class="td-heading-self-link" href="#%d0%be%d1%81%d0%be%d0%b1%d0%b5%d0%bd%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b0%d1%81%d1%81%d0%be%d1%86%d0%b8%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8" aria-label="Heading self-link"></a></h3> <p>Синтаксис языка <em>NewLang</em> основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например <strong>if</strong>, чем комбинация <em>минус минус правая угловая скобка</em> <strong>&ndash;&gt;</strong>. Из-за этого имеет смысл использовать не &ldquo;чистый&rdquo; базовый синтаксис, а более привычный диалект с использованием ключевых слов.</p> -<h3 id="синтаксис-на-ключевых-словах">Синтаксис на ключевых словах<a class="td-heading-self-link" href="#%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81-%d0%bd%d0%b0-%d0%ba%d0%bb%d1%8e%d1%87%d0%b5%d0%b2%d1%8b%d1%85-%d1%81%d0%bb%d0%be%d0%b2%d0%b0%d1%85" aria-label="Heading self-link"></a></h3> -<p>В файле dsl.nlp находится набор макросов, которые расширяют базовый синтаксис <em>NewLang</em>, основанный на правилах, -набором предопределенных ключевых слов как в классических языках программирования. -А при необходимости, их можно адаптировать или дополнить под собственную предметную область.</p> -<h2 id="константы">Константы<a class="td-heading-self-link" href="#%d0%ba%d0%be%d0%bd%d1%81%d1%82%d0%b0%d0%bd%d1%82%d1%8b" aria-label="Heading self-link"></a></h2> -<h3 id="логические">Логические<a class="td-heading-self-link" href="#%d0%bb%d0%be%d0%b3%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> +<p><em>NewLang</em> уже содержит набор макросов, которые расширяют базовый синтаксис <em>NewLang</em>, основанный на правилах, +набором предопределенных ключевых слов как в классических языках программирования, +которые можно адаптировать или дополнить под собственную предметную область.</p> +<h3 id="константы">Константы<a class="td-heading-self-link" href="#%d0%ba%d0%be%d0%bd%d1%81%d1%82%d0%b0%d0%bd%d1%82%d1%8b" aria-label="Heading self-link"></a></h3> <ul> -<li><strong>true</strong> - 1</li> -<li><strong>yes</strong> - 1</li> -<li><strong>false</strong> - 0</li> -<li><strong>no</strong> - 0</li> +<li> +<p><em>@true</em> - 1</p> +</li> +<li> +<p><em>@yes</em> - 1</p> +</li> +<li> +<p><em>@false</em> - 0</p> +</li> +<li> +<p><em>@no</em> - 0</p> +</li> +<li> +<p><em>@this</em> или <em>@self</em> - Текущий объект</p> +</li> +<li> +<p><em>@super</em> - Родительский объект</p> +</li> +<li> +<p><em>@latter</em> или <em>@last</em>- Результат выполенения последнего оператора Result of the last operation</p> +</li> </ul> -<h3 id="системные-имена">Системные имена<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%8b%d0%b5-%d0%b8%d0%bc%d0%b5%d0%bd%d0%b0" aria-label="Heading self-link"></a></h3> +<h3 id="логические-операторы">Логические операторы<a class="td-heading-self-link" href="#%d0%bb%d0%be%d0%b3%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b" aria-label="Heading self-link"></a></h3> <ul> -<li><strong>this</strong> - Текущий объект (<strong>$0</strong>)</li> -<li><strong>parent</strong> - Родительский объект (<strong>$$</strong>)</li> -<li><strong>last</strong> - Результат выполнения последнего оператора (<strong>$^</strong>)</li> +<li><em>@and</em> - Логическое <strong>И</strong></li> +<li><em>@or</em> - Логическое <strong>ИЛИ</strong></li> +<li><em>@xor</em> - Логическое <strong>Исключающее ИЛИ</strong></li> +<li><em>@not(value)</em> - Логическое отрицание</li> </ul> -<p>!!!!!!!!- <strong>args</strong> - Все аргументы функции (<strong>$*</strong>)</p> -<p>!!!!!!!!- <strong>sys</strong> - Системный контекст запущенной программы (<strong>@@</strong>) -!!!!!!!!- <strong>current</strong> - Текущий модуль (<strong>@$</strong>) -!!!!!!!!- <strong>cmd</strong> - Все аргументы выполняющегося приложения из командной строки (<strong>@*</strong>)</p> -<p>!!!!!!!!!!1### Типовые функции и проверки -!!!!!!!!!!- <strong>run(&lsquo;filename&rsquo;)</strong> - Выполнить указанный файл (<strong>@@(&lsquo;filename&rsquo;)</strong>) -!!!!!!!!!!- <strong>ifmain</strong> - Проверка, если текущий модуль основной (<strong>[@$.$0] &ndash;&gt;</strong> { &hellip; }) -!!!!!!!!!!- <strong>ifload</strong> - Проверка, если текущий модуль загружается впервые (<strong>[@$.<strong>load</strong>] &ndash;&gt;</strong> { &hellip; })</p> <h3 id="операторы">Операторы<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b" aria-label="Heading self-link"></a></h3> <ul> <li> -<p><strong>match(cond)</strong> - Оператор <a href="https://newlang.net/ops.html#%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B0-%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F">оценки выражения</a></p> +<p><em>@if(&hellip;)</em> - Первый условный оператор</p> </li> <li> -<p><strong>if(&hellip;)</strong> - Первый условный оператор (<strong>[$*]&ndash;&gt;</strong> { &hellip; })</p> +<p><em>@elif(&hellip;)</em> - Второй и все последующие условные операторы</p> </li> <li> -<p><strong>elif(&hellip;)</strong> - Второй и все последующие (<strong>,[$*]&ndash;&gt;</strong> { &hellip; })</p> +<p><em>@else</em> - Оператор <em>иначе</em></p> </li> <li> -<p><strong>else</strong> - Оператор <em>иначе</em> (<strong>,[_]&ndash;&gt;</strong> { &hellip; })</p> +<p><em>@while(&hellip;)</em> - Оператор цикла с предусловием</p> </li> <li> -<p><strong>while(cond)</strong> - Оператор цикла с предусловием (<strong>[@$cond] &lt;-&gt;</strong> { &hellip; } )</p> +<p><em>@dowhile(&hellip;)</em> - Оператор цикла с постусловием</p> </li> <li> -<p><strong>dowhile(cond)</strong> - Оператор цикла с постусловием ({ &hellip; } <strong>&lt;-&gt;[@$cond]</strong>)</p> +<p><em>@loop</em> - Оператор безконечного цикла</p> </li> <li> -<p><strong>iter(obj, &hellip; )</strong> - Создание итератора ( <strong>@$obj</strong> ? (@$*) )</p> +<p><em>@break $label</em> - Оператор выхода из именованного именованного блока кода</p> </li> <li> -<p><strong>next(obj, &hellip; )</strong> - Следующий элемент итератора ( <strong>@$obj</strong> ! ($*) )</p> +<p><em>@continue $label</em> - Оператор прехода на начало именованного блока кода</p> </li> <li> -<p><strong>curr(obj, &hellip; )</strong> - Текущий элемент итератора ( <strong>@$obj</strong> !? ($*) )</p> +<p><em>@return( result )</em> - Оператор возврата значения и выхода из функции</p> </li> <li> -<p><strong>first(obj)</strong> - Перейти на первый элемент итератора ( <strong>@$obj</strong> !! )</p> +<p><em>@throw( error )</em> - Оператор создания исключения и возврата ошибки</p> </li> <li> -<p><strong>all(obj)</strong> - Получить сразу все элементы итератора ( <strong>@$obj</strong> ??)</p> +<p><em>@match( &hellip; )</em> - Оператор оценки выражения</p> </li> -</ul> -<h3 id="прерывания">Прерывания<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b5%d1%80%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h3> -<ul> <li> -<p><strong>return</strong> - Положительное прерывание (<strong>++</strong>)</p> +<p><em>@case( &hellip; )</em> - Оператор сравнения с образцом</p> </li> <li> -<p><strong>return(&hellip;)</strong>- Положительное прерывание с возвратом значения (<strong>++</strong> @$value <strong>++</strong>)</p> +<p><em>@default</em> - Оператор выбора по улочанию</p> </li> <li> -<p><strong>error</strong> - Отрицательное прерывание (<strong>--</strong>)</p> +<p><em>@iter(obj, &hellip; )</em> - Создание итератора</p> </li> <li> -<p><strong>error(&hellip;)</strong> - Отрицательное прерывание с возвратом значения (<strong>--</strong> @$value <strong>--</strong>)</p> +<p><em>@next(obj, &hellip; )</em> - Получить следующий элемент итератора</p> </li> <li> -<p><strong>break+</strong> и <strong>break-</strong> - Выход из цикла:</p> +<p><em>@curr(obj, &hellip; )</em> - Получить текущий элемент итератора</p> +</li> +<li> +<p><em>@first(obj)</em> - Перейти на первый элемент итератора</p> +</li> +<li> +<p><em>@all(obj)</em> - Получить сразу все элементы итератора</p> </li> </ul> -<pre tabindex="0"><code> while(...) {+ - ++ :Break ++ - +} - while(...) {- - -- :Break -- - -} -</code></pre><ul> -<li><strong>continue+</strong> и <strong>continue-</strong> - В начало цикла:</li> -</ul> -<pre tabindex="0"><code> while(...) {+ - ++ :Continue ++ - +} - while(...) {- - -- :Continue -- - -} -</code></pre><p>obj { -.field = 1; -.prop(); -};</p> -<p>#Python</p> -<h1 id="1-without-using-with-statement">1) without using with statement<a class="td-heading-self-link" href="#1-without-using-with-statement" aria-label="Heading self-link"></a></h1> -<p>file = open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) -file.write(&lsquo;hello world !&rsquo;) -file.close()</p> -<h1 id="2-without-using-with-statement">2) without using with statement<a class="td-heading-self-link" href="#2-without-using-with-statement" aria-label="Heading self-link"></a></h1> -<p>file = open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) -try: -file.write(&lsquo;hello world&rsquo;) -finally: -file.close()</p> -<p>open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) { -.write(&lsquo;hello world !&rsquo;); -.close(); -}</p> -<p>Python3</p> -<h1 id="using-with-statement">using with statement<a class="td-heading-self-link" href="#using-with-statement" aria-label="Heading self-link"></a></h1> -<p>with open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) as file: -file.write(&lsquo;hello world !&rsquo;)</p> -<h1 id="a-simple-file-writer-object">a simple file writer object<a class="td-heading-self-link" href="#a-simple-file-writer-object" aria-label="Heading self-link"></a></h1> -<p>class MessageWriter(object): -def <strong>init</strong>(self, file_name): -self.file_name = file_name</p> -<pre><code>def __enter__(self): - self.file = open(self.file_name, 'w') - return self.file - -def __exit__(self, *args): - self.file.close() -</code></pre> -<h1 id="using-with-statement-with-messagewriter">using with statement with MessageWriter<a class="td-heading-self-link" href="#using-with-statement-with-messagewriter" aria-label="Heading self-link"></a></h1> -<p>with MessageWriter(&lsquo;my_file.txt&rsquo;) as xfile: -xfile.write(&lsquo;hello world&rsquo;)</p> -<h1 id="a-simple-file-writer-object-1">a simple file writer object<a class="td-heading-self-link" href="#a-simple-file-writer-object-1" aria-label="Heading self-link"></a></h1> -<p>:MessageWriter { -def <strong>init</strong>(self, file_name): -self.file_name = file_name</p> -<pre><code>def __enter__(self): - self.file = open(self.file_name, 'w') - return self.file - -def __exit__(self, *args): - self.file.close() -</code></pre> -<p>}</p> -<h1 id="using-with-statement-with-messagewriter-1">using with statement with MessageWriter<a class="td-heading-self-link" href="#using-with-statement-with-messagewriter-1" aria-label="Heading self-link"></a></h1> -<p>MessageWriter(&lsquo;my_file.txt&rsquo;) { -.write(&lsquo;hello world&rsquo;); -};</p> -<p>from contextlib import contextmanager</p> -<p>class MessageWriter(object): -def <strong>init</strong>(self, filename): -self.file_name = filename</p> -<pre><code>@contextmanager -def open_file(self): - try: - file = open(self.file_name, 'w') - yield file - finally: - file.close() -</code></pre> -<h1 id="usage">usage<a class="td-heading-self-link" href="#usage" aria-label="Heading self-link"></a></h1> -<p>message_writer = MessageWriter(&lsquo;hello.txt&rsquo;) -with message_writer.open_file() as my_file: -my_file.write(&lsquo;hello world&rsquo;)</p> -<p>:MessageWriter(object) { -def <strong>init</strong>(self, filename): -self.file_name = filename</p> -<pre><code>@contextmanager -def open_file(self): - try: - file = open(self.file_name, 'w') - yield file - finally: - file.close() -</code></pre> -<p>}</p> -<h1 id="usage-1">usage<a class="td-heading-self-link" href="#usage-1" aria-label="Heading self-link"></a></h1> -<p>message_writer = MessageWriter(&lsquo;hello.txt&rsquo;) -with message_writer.open_file() as my_file: -my_file.write(&lsquo;hello world&rsquo;)</p> -<h1 id="приложения">Приложения<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b8%d0%bb%d0%be%d0%b6%d0%b5%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h1> <h2 id="предопределенные-макросы">Предопределенные макросы<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b5%d0%b4%d0%be%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%bd%d1%8b%d0%b5-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b" aria-label="Heading self-link"></a></h2> -<p>При работе парсера <em>NewLang</em> автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. +<p>При работе парсера <em>NewLang</em> автоматически формируются несколько зарезервированных макросов, +часть из которых соответствуют макросам препроцессора у С/С++. Данные предопределенные макросы можно использовать как обычные константы.</p> <ul> <li> diff --git a/docs/ru/docs/syntax/dsl/index.html b/docs/ru/docs/syntax/dsl/index.html index 9ca15ded..7ef5182e 100644 --- a/docs/ru/docs/syntax/dsl/index.html +++ b/docs/ru/docs/syntax/dsl/index.html @@ -18,23 +18,23 @@ <link rel="icon" type="image/png" href="/favicons/android-192x192.png" sizes="192x192"> <title>Keyword syntax (DSL) | NewLang</title> -<meta name="description" content="DSL Особенности ассоциативной памяти Синтаксис языка NewLang основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например if, чем комбинация минус минус правая угловая скобка &amp;ndash;&amp;gt;. Из-за этого имеет смысл использовать не &amp;ldquo;чистый&amp;rdquo; базовый синтаксис, а более привычный диалект с использованием ключевых слов. -Синтаксис на ключевых словах В файле dsl.nlp находится набор макросов, которые расширяют базовый синтаксис NewLang, основанный на правилах, набором предопределенных ключевых слов как в классических языках программирования."> +<meta name="description" content="Особенности ассоциативной памяти Синтаксис языка NewLang основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например if, чем комбинация минус минус правая угловая скобка &amp;ndash;&amp;gt;. Из-за этого имеет смысл использовать не &amp;ldquo;чистый&amp;rdquo; базовый синтаксис, а более привычный диалект с использованием ключевых слов. +NewLang уже содержит набор макросов, которые расширяют базовый синтаксис NewLang, основанный на правилах, набором предопределенных ключевых слов как в классических языках программирования, которые можно адаптировать или дополнить под собственную предметную область."> <meta property="og:title" content="Keyword syntax (DSL)" /> -<meta property="og:description" content="DSL Особенности ассоциативной памяти Синтаксис языка NewLang основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например if, чем комбинация минус минус правая угловая скобка &ndash;&gt;. Из-за этого имеет смысл использовать не &ldquo;чистый&rdquo; базовый синтаксис, а более привычный диалект с использованием ключевых слов. -Синтаксис на ключевых словах В файле dsl.nlp находится набор макросов, которые расширяют базовый синтаксис NewLang, основанный на правилах, набором предопределенных ключевых слов как в классических языках программирования." /> +<meta property="og:description" content="Особенности ассоциативной памяти Синтаксис языка NewLang основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например if, чем комбинация минус минус правая угловая скобка &ndash;&gt;. Из-за этого имеет смысл использовать не &ldquo;чистый&rdquo; базовый синтаксис, а более привычный диалект с использованием ключевых слов. +NewLang уже содержит набор макросов, которые расширяют базовый синтаксис NewLang, основанный на правилах, набором предопределенных ключевых слов как в классических языках программирования, которые можно адаптировать или дополнить под собственную предметную область." /> <meta property="og:type" content="article" /> <meta property="og:url" content="http://localhost:1313/ru/docs/syntax/dsl/" /><meta property="article:section" content="docs" /> -<meta property="article:modified_time" content="2024-03-22T23:57:08+03:00" /><meta property="og:site_name" content="NewLang" /> +<meta property="article:modified_time" content="2024-03-23T22:03:23+03:00" /><meta property="og:site_name" content="NewLang" /> <meta itemprop="name" content="Keyword syntax (DSL)"> -<meta itemprop="description" content="DSL Особенности ассоциативной памяти Синтаксис языка NewLang основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например if, чем комбинация минус минус правая угловая скобка &ndash;&gt;. Из-за этого имеет смысл использовать не &ldquo;чистый&rdquo; базовый синтаксис, а более привычный диалект с использованием ключевых слов. -Синтаксис на ключевых словах В файле dsl.nlp находится набор макросов, которые расширяют базовый синтаксис NewLang, основанный на правилах, набором предопределенных ключевых слов как в классических языках программирования."> -<meta itemprop="dateModified" content="2024-03-22T23:57:08+03:00" /> -<meta itemprop="wordCount" content="769"> +<meta itemprop="description" content="Особенности ассоциативной памяти Синтаксис языка NewLang основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например if, чем комбинация минус минус правая угловая скобка &ndash;&gt;. Из-за этого имеет смысл использовать не &ldquo;чистый&rdquo; базовый синтаксис, а более привычный диалект с использованием ключевых слов. +NewLang уже содержит набор макросов, которые расширяют базовый синтаксис NewLang, основанный на правилах, набором предопределенных ключевых слов как в классических языках программирования, которые можно адаптировать или дополнить под собственную предметную область."> +<meta itemprop="dateModified" content="2024-03-23T22:03:23+03:00" /> +<meta itemprop="wordCount" content="471"> <meta itemprop="keywords" content="" /><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Keyword syntax (DSL)"/> -<meta name="twitter:description" content="DSL Особенности ассоциативной памяти Синтаксис языка NewLang основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например if, чем комбинация минус минус правая угловая скобка &ndash;&gt;. Из-за этого имеет смысл использовать не &ldquo;чистый&rdquo; базовый синтаксис, а более привычный диалект с использованием ключевых слов. -Синтаксис на ключевых словах В файле dsl.nlp находится набор макросов, которые расширяют базовый синтаксис NewLang, основанный на правилах, набором предопределенных ключевых слов как в классических языках программирования."/> +<meta name="twitter:description" content="Особенности ассоциативной памяти Синтаксис языка NewLang основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например if, чем комбинация минус минус правая угловая скобка &ndash;&gt;. Из-за этого имеет смысл использовать не &ldquo;чистый&rdquo; базовый синтаксис, а более привычный диалект с использованием ключевых слов. +NewLang уже содержит набор макросов, которые расширяют базовый синтаксис NewLang, основанный на правилах, набором предопределенных ключевых слов как в классических языках программирования, которые можно адаптировать или дополнить под собственную предметную область."/> @@ -229,23 +229,14 @@ <div class="td-toc"> <nav id="TableOfContents"> <ul> - <li><a href="#dsl">DSL</a> + <li> <ul> <li><a href="#особенности-ассоциативной-памяти">Особенности ассоциативной памяти</a></li> - <li><a href="#синтаксис-на-ключевых-словах">Синтаксис на ключевых словах</a></li> - </ul> - </li> - <li><a href="#константы">Константы</a> - <ul> - <li><a href="#логические">Логические</a></li> - <li><a href="#системные-имена">Системные имена</a></li> + <li><a href="#константы">Константы</a></li> + <li><a href="#логические-операторы">Логические операторы</a></li> <li><a href="#операторы">Операторы</a></li> - <li><a href="#прерывания">Прерывания</a></li> </ul> </li> - </ul> - - <ul> <li><a href="#предопределенные-макросы">Предопределенные макросы</a></li> </ul> </nav> @@ -287,195 +278,105 @@ <h1>Keyword syntax (DSL)</h1> <header class="article-meta"> </header> - <h2 id="dsl">DSL<a class="td-heading-self-link" href="#dsl" aria-label="Heading self-link"></a></h2> -<h3 id="особенности-ассоциативной-памяти">Особенности ассоциативной памяти<a class="td-heading-self-link" href="#%d0%be%d1%81%d0%be%d0%b1%d0%b5%d0%bd%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b0%d1%81%d1%81%d0%be%d1%86%d0%b8%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8" aria-label="Heading self-link"></a></h3> + <h3 id="особенности-ассоциативной-памяти">Особенности ассоциативной памяти<a class="td-heading-self-link" href="#%d0%be%d1%81%d0%be%d0%b1%d0%b5%d0%bd%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b0%d1%81%d1%81%d0%be%d1%86%d0%b8%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8" aria-label="Heading self-link"></a></h3> <p>Синтаксис языка <em>NewLang</em> основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например <strong>if</strong>, чем комбинация <em>минус минус правая угловая скобка</em> <strong>&ndash;&gt;</strong>. Из-за этого имеет смысл использовать не &ldquo;чистый&rdquo; базовый синтаксис, а более привычный диалект с использованием ключевых слов.</p> -<h3 id="синтаксис-на-ключевых-словах">Синтаксис на ключевых словах<a class="td-heading-self-link" href="#%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81-%d0%bd%d0%b0-%d0%ba%d0%bb%d1%8e%d1%87%d0%b5%d0%b2%d1%8b%d1%85-%d1%81%d0%bb%d0%be%d0%b2%d0%b0%d1%85" aria-label="Heading self-link"></a></h3> -<p>В файле dsl.nlp находится набор макросов, которые расширяют базовый синтаксис <em>NewLang</em>, основанный на правилах, -набором предопределенных ключевых слов как в классических языках программирования. -А при необходимости, их можно адаптировать или дополнить под собственную предметную область.</p> -<h2 id="константы">Константы<a class="td-heading-self-link" href="#%d0%ba%d0%be%d0%bd%d1%81%d1%82%d0%b0%d0%bd%d1%82%d1%8b" aria-label="Heading self-link"></a></h2> -<h3 id="логические">Логические<a class="td-heading-self-link" href="#%d0%bb%d0%be%d0%b3%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> +<p><em>NewLang</em> уже содержит набор макросов, которые расширяют базовый синтаксис <em>NewLang</em>, основанный на правилах, +набором предопределенных ключевых слов как в классических языках программирования, +которые можно адаптировать или дополнить под собственную предметную область.</p> +<h3 id="константы">Константы<a class="td-heading-self-link" href="#%d0%ba%d0%be%d0%bd%d1%81%d1%82%d0%b0%d0%bd%d1%82%d1%8b" aria-label="Heading self-link"></a></h3> <ul> -<li><strong>true</strong> - 1</li> -<li><strong>yes</strong> - 1</li> -<li><strong>false</strong> - 0</li> -<li><strong>no</strong> - 0</li> +<li> +<p><em>@true</em> - 1</p> +</li> +<li> +<p><em>@yes</em> - 1</p> +</li> +<li> +<p><em>@false</em> - 0</p> +</li> +<li> +<p><em>@no</em> - 0</p> +</li> +<li> +<p><em>@this</em> или <em>@self</em> - Текущий объект</p> +</li> +<li> +<p><em>@super</em> - Родительский объект</p> +</li> +<li> +<p><em>@latter</em> или <em>@last</em>- Результат выполенения последнего оператора Result of the last operation</p> +</li> </ul> -<h3 id="системные-имена">Системные имена<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%8b%d0%b5-%d0%b8%d0%bc%d0%b5%d0%bd%d0%b0" aria-label="Heading self-link"></a></h3> +<h3 id="логические-операторы">Логические операторы<a class="td-heading-self-link" href="#%d0%bb%d0%be%d0%b3%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b" aria-label="Heading self-link"></a></h3> <ul> -<li><strong>this</strong> - Текущий объект (<strong>$0</strong>)</li> -<li><strong>parent</strong> - Родительский объект (<strong>$$</strong>)</li> -<li><strong>last</strong> - Результат выполнения последнего оператора (<strong>$^</strong>)</li> +<li><em>@and</em> - Логическое <strong>И</strong></li> +<li><em>@or</em> - Логическое <strong>ИЛИ</strong></li> +<li><em>@xor</em> - Логическое <strong>Исключающее ИЛИ</strong></li> +<li><em>@not(value)</em> - Логическое отрицание</li> </ul> -<p>!!!!!!!!- <strong>args</strong> - Все аргументы функции (<strong>$*</strong>)</p> -<p>!!!!!!!!- <strong>sys</strong> - Системный контекст запущенной программы (<strong>@@</strong>) -!!!!!!!!- <strong>current</strong> - Текущий модуль (<strong>@$</strong>) -!!!!!!!!- <strong>cmd</strong> - Все аргументы выполняющегося приложения из командной строки (<strong>@*</strong>)</p> -<p>!!!!!!!!!!1### Типовые функции и проверки -!!!!!!!!!!- <strong>run(&lsquo;filename&rsquo;)</strong> - Выполнить указанный файл (<strong>@@(&lsquo;filename&rsquo;)</strong>) -!!!!!!!!!!- <strong>ifmain</strong> - Проверка, если текущий модуль основной (<strong>[@$.$0] &ndash;&gt;</strong> { &hellip; }) -!!!!!!!!!!- <strong>ifload</strong> - Проверка, если текущий модуль загружается впервые (<strong>[@$.<strong>load</strong>] &ndash;&gt;</strong> { &hellip; })</p> <h3 id="операторы">Операторы<a class="td-heading-self-link" href="#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b" aria-label="Heading self-link"></a></h3> <ul> <li> -<p><strong>match(cond)</strong> - Оператор <a href="https://newlang.net/ops.html#%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B0-%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F">оценки выражения</a></p> +<p><em>@if(&hellip;)</em> - Первый условный оператор</p> </li> <li> -<p><strong>if(&hellip;)</strong> - Первый условный оператор (<strong>[$*]&ndash;&gt;</strong> { &hellip; })</p> +<p><em>@elif(&hellip;)</em> - Второй и все последующие условные операторы</p> </li> <li> -<p><strong>elif(&hellip;)</strong> - Второй и все последующие (<strong>,[$*]&ndash;&gt;</strong> { &hellip; })</p> +<p><em>@else</em> - Оператор <em>иначе</em></p> </li> <li> -<p><strong>else</strong> - Оператор <em>иначе</em> (<strong>,[_]&ndash;&gt;</strong> { &hellip; })</p> +<p><em>@while(&hellip;)</em> - Оператор цикла с предусловием</p> </li> <li> -<p><strong>while(cond)</strong> - Оператор цикла с предусловием (<strong>[@$cond] &lt;-&gt;</strong> { &hellip; } )</p> +<p><em>@dowhile(&hellip;)</em> - Оператор цикла с постусловием</p> </li> <li> -<p><strong>dowhile(cond)</strong> - Оператор цикла с постусловием ({ &hellip; } <strong>&lt;-&gt;[@$cond]</strong>)</p> +<p><em>@loop</em> - Оператор безконечного цикла</p> </li> <li> -<p><strong>iter(obj, &hellip; )</strong> - Создание итератора ( <strong>@$obj</strong> ? (@$*) )</p> +<p><em>@break $label</em> - Оператор выхода из именованного именованного блока кода</p> </li> <li> -<p><strong>next(obj, &hellip; )</strong> - Следующий элемент итератора ( <strong>@$obj</strong> ! ($*) )</p> +<p><em>@continue $label</em> - Оператор прехода на начало именованного блока кода</p> </li> <li> -<p><strong>curr(obj, &hellip; )</strong> - Текущий элемент итератора ( <strong>@$obj</strong> !? ($*) )</p> +<p><em>@return( result )</em> - Оператор возврата значения и выхода из функции</p> </li> <li> -<p><strong>first(obj)</strong> - Перейти на первый элемент итератора ( <strong>@$obj</strong> !! )</p> +<p><em>@throw( error )</em> - Оператор создания исключения и возврата ошибки</p> </li> <li> -<p><strong>all(obj)</strong> - Получить сразу все элементы итератора ( <strong>@$obj</strong> ??)</p> +<p><em>@match( &hellip; )</em> - Оператор оценки выражения</p> </li> -</ul> -<h3 id="прерывания">Прерывания<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b5%d1%80%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h3> -<ul> <li> -<p><strong>return</strong> - Положительное прерывание (<strong>++</strong>)</p> +<p><em>@case( &hellip; )</em> - Оператор сравнения с образцом</p> </li> <li> -<p><strong>return(&hellip;)</strong>- Положительное прерывание с возвратом значения (<strong>++</strong> @$value <strong>++</strong>)</p> +<p><em>@default</em> - Оператор выбора по улочанию</p> </li> <li> -<p><strong>error</strong> - Отрицательное прерывание (<strong>--</strong>)</p> +<p><em>@iter(obj, &hellip; )</em> - Создание итератора</p> </li> <li> -<p><strong>error(&hellip;)</strong> - Отрицательное прерывание с возвратом значения (<strong>--</strong> @$value <strong>--</strong>)</p> +<p><em>@next(obj, &hellip; )</em> - Получить следующий элемент итератора</p> </li> <li> -<p><strong>break+</strong> и <strong>break-</strong> - Выход из цикла:</p> +<p><em>@curr(obj, &hellip; )</em> - Получить текущий элемент итератора</p> +</li> +<li> +<p><em>@first(obj)</em> - Перейти на первый элемент итератора</p> +</li> +<li> +<p><em>@all(obj)</em> - Получить сразу все элементы итератора</p> </li> </ul> -<pre tabindex="0"><code> while(...) {+ - ++ :Break ++ - +} - while(...) {- - -- :Break -- - -} -</code></pre><ul> -<li><strong>continue+</strong> и <strong>continue-</strong> - В начало цикла:</li> -</ul> -<pre tabindex="0"><code> while(...) {+ - ++ :Continue ++ - +} - while(...) {- - -- :Continue -- - -} -</code></pre><p>obj { -.field = 1; -.prop(); -};</p> -<p>#Python</p> -<h1 id="1-without-using-with-statement">1) without using with statement<a class="td-heading-self-link" href="#1-without-using-with-statement" aria-label="Heading self-link"></a></h1> -<p>file = open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) -file.write(&lsquo;hello world !&rsquo;) -file.close()</p> -<h1 id="2-without-using-with-statement">2) without using with statement<a class="td-heading-self-link" href="#2-without-using-with-statement" aria-label="Heading self-link"></a></h1> -<p>file = open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) -try: -file.write(&lsquo;hello world&rsquo;) -finally: -file.close()</p> -<p>open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) { -.write(&lsquo;hello world !&rsquo;); -.close(); -}</p> -<p>Python3</p> -<h1 id="using-with-statement">using with statement<a class="td-heading-self-link" href="#using-with-statement" aria-label="Heading self-link"></a></h1> -<p>with open(&lsquo;file_path&rsquo;, &lsquo;w&rsquo;) as file: -file.write(&lsquo;hello world !&rsquo;)</p> -<h1 id="a-simple-file-writer-object">a simple file writer object<a class="td-heading-self-link" href="#a-simple-file-writer-object" aria-label="Heading self-link"></a></h1> -<p>class MessageWriter(object): -def <strong>init</strong>(self, file_name): -self.file_name = file_name</p> -<pre><code>def __enter__(self): - self.file = open(self.file_name, 'w') - return self.file - -def __exit__(self, *args): - self.file.close() -</code></pre> -<h1 id="using-with-statement-with-messagewriter">using with statement with MessageWriter<a class="td-heading-self-link" href="#using-with-statement-with-messagewriter" aria-label="Heading self-link"></a></h1> -<p>with MessageWriter(&lsquo;my_file.txt&rsquo;) as xfile: -xfile.write(&lsquo;hello world&rsquo;)</p> -<h1 id="a-simple-file-writer-object-1">a simple file writer object<a class="td-heading-self-link" href="#a-simple-file-writer-object-1" aria-label="Heading self-link"></a></h1> -<p>:MessageWriter { -def <strong>init</strong>(self, file_name): -self.file_name = file_name</p> -<pre><code>def __enter__(self): - self.file = open(self.file_name, 'w') - return self.file - -def __exit__(self, *args): - self.file.close() -</code></pre> -<p>}</p> -<h1 id="using-with-statement-with-messagewriter-1">using with statement with MessageWriter<a class="td-heading-self-link" href="#using-with-statement-with-messagewriter-1" aria-label="Heading self-link"></a></h1> -<p>MessageWriter(&lsquo;my_file.txt&rsquo;) { -.write(&lsquo;hello world&rsquo;); -};</p> -<p>from contextlib import contextmanager</p> -<p>class MessageWriter(object): -def <strong>init</strong>(self, filename): -self.file_name = filename</p> -<pre><code>@contextmanager -def open_file(self): - try: - file = open(self.file_name, 'w') - yield file - finally: - file.close() -</code></pre> -<h1 id="usage">usage<a class="td-heading-self-link" href="#usage" aria-label="Heading self-link"></a></h1> -<p>message_writer = MessageWriter(&lsquo;hello.txt&rsquo;) -with message_writer.open_file() as my_file: -my_file.write(&lsquo;hello world&rsquo;)</p> -<p>:MessageWriter(object) { -def <strong>init</strong>(self, filename): -self.file_name = filename</p> -<pre><code>@contextmanager -def open_file(self): - try: - file = open(self.file_name, 'w') - yield file - finally: - file.close() -</code></pre> -<p>}</p> -<h1 id="usage-1">usage<a class="td-heading-self-link" href="#usage-1" aria-label="Heading self-link"></a></h1> -<p>message_writer = MessageWriter(&lsquo;hello.txt&rsquo;) -with message_writer.open_file() as my_file: -my_file.write(&lsquo;hello world&rsquo;)</p> -<h1 id="приложения">Приложения<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b8%d0%bb%d0%be%d0%b6%d0%b5%d0%bd%d0%b8%d1%8f" aria-label="Heading self-link"></a></h1> <h2 id="предопределенные-макросы">Предопределенные макросы<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b5%d0%b4%d0%be%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%bd%d1%8b%d0%b5-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b" aria-label="Heading self-link"></a></h2> -<p>При работе парсера <em>NewLang</em> автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. +<p>При работе парсера <em>NewLang</em> автоматически формируются несколько зарезервированных макросов, +часть из которых соответствуют макросам препроцессора у С/С++. Данные предопределенные макросы можно использовать как обычные константы.</p> <ul> <li> diff --git a/docs/ru/docs/syntax/index.xml b/docs/ru/docs/syntax/index.xml index 216b5608..c4ece522 100644 --- a/docs/ru/docs/syntax/index.xml +++ b/docs/ru/docs/syntax/index.xml @@ -569,7 +569,8 @@ <description> - &lt;p&gt;Макросы в &lt;strong&gt;NewLang&lt;/strong&gt;, это один или несколько последовательных терминов, которые заменяются на другой термин + &lt;p&gt;Макросы используются и для превращеня исходного кода &lt;em&gt;NewLang&lt;/em&gt; в более привычный синтаксис на основе &lt;a href=&#34;https://newlang.net/syntax_dsl.html&#34;&gt;ключевых слов&lt;/a&gt;, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода.&lt;/p&gt; +&lt;p&gt;Макросы в &lt;strong&gt;NewLang&lt;/strong&gt;, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем).&lt;/p&gt; &lt;p&gt;Макросы обработываются во время работы &lt;strong&gt;лексера&lt;/strong&gt;, т.е. перед передачей последовательности лексем в парсер, что позволяет с помощью маросов изменять фрагменты синтаксиса языка, например, при реализации собственных диалектов DSL.&lt;/p&gt; @@ -604,13 +605,13 @@ с одинаковыми именами, один из которых будет с аргументами (скобками), а другой без них.&lt;/p&gt; &lt;p&gt;Поэтому, если требуется использовать макрос в двух разных вариантах (с аргументами и без оных), следует определять макрос без аргументов и в этом случае контроль параметров будет выполнятся компилятором.&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@macro@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; term&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Макрос без аргументов&lt;/span&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@ macro @@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; term&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Макрос без аргументов&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; macro&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;args&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# ОК -&amp;gt; term(args);&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; macro&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# ОК -&amp;gt; term;&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Но &lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; term&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@ call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt; @@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; term&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# ОК -&amp;gt; term();&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; call&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Ошибка (@call определен с аргументами) &lt;/span&gt; @@ -623,286 +624,49 @@ &lt;p&gt;По аналогии с препроцессором С/С++, для соединения двух лексем в одну, в теле макроса используется оператор &lt;strong&gt;&amp;quot;@##&amp;quot;&lt;/strong&gt;, а для преобразование лексемы в текстову строку применяется операторы &lt;strong&gt;@#&lt;/strong&gt;, &lt;strong&gt;@#&amp;quot;&lt;/strong&gt; или &lt;strong&gt;@#&amp;rsquo;&lt;/strong&gt;, например, &lt;code&gt;@@macro($arg)@@ := @@ func_ @## @$arg( @#&amp;quot; arg ) @;&lt;/code&gt;, тогда вызов &lt;code&gt;macro(name);&lt;/code&gt; будет преобразован в &lt;code&gt;func_name (&amp;quot;name&amp;quot;);&lt;/code&gt;&lt;/p&gt; - - -&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; -&lt;h4 id=&#34;ограничения-макропроцессора-в-текущей-версии&#34;&gt;Ограничения макропроцессора в текущей версии&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%b3%d1%80%d0%b0%d0%bd%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d0%bf%d1%80%d0%be%d1%86%d0%b5%d1%81%d1%81%d0%be%d1%80%d0%b0-%d0%b2-%d1%82%d0%b5%d0%ba%d1%83%d1%89%d0%b5%d0%b9-%d0%b2%d0%b5%d1%80%d1%81%d0%b8%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h4&gt; -&lt;p&gt;На текущий момент макросы реализованы в минимальном объеме для самых простых сценариев использования:&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;DSL для keyword based syntax (if, else, return, match, while и т.д.) - (1 термин с произвольными аргументами и без) - требуется сейчас !!!&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;&lt;em&gt;Парсер при обработке макросов может анализировать информацию о типах данных, если она указана.&lt;/em&gt; -&lt;em&gt;Но на текущий момент типы данных в макросах никак не обрабатываются и это одна из обязательных фич, которая будет реализована в будущем.&lt;/em&gt;&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Определения (func, class) - (несколько терминов с аргументами и без аргументов) - Реализация ООП и импорт С++ классов&lt;/li&gt; -&lt;li&gt;Модификации при определениях (override) - (несколько терминов и шаблоны с аргументами и без аргументов) - Реализация ООП и импорт С++ классов&lt;/li&gt; -&lt;/ul&gt; - -&lt;/div&gt; - -&lt;h1 id=&#34;макросы-без-аргументов-или-все-аргументы-сразу-&#34;&gt;МАКРОСЫ БЕЗ АРГУМЕНТОВ ИЛИ ВСЕ АРГУМЕНТЫ СРАЗУ !!!!!&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b1%d0%b5%d0%b7-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d0%b8%d0%bb%d0%b8-%d0%b2%d1%81%d0%b5-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d1%8b-%d1%81%d1%80%d0%b0%d0%b7%d1%83-&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;h1 id=&#34;анализа-аргументов-или-их-типов-не-производится-&#34;&gt;анализа аргументов или их типов не производится !!!&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b0%d0%bd%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d0%b8%d0%bb%d0%b8-%d0%b8%d1%85-%d1%82%d0%b8%d0%bf%d0%be%d0%b2-%d0%bd%d0%b5-%d0%bf%d1%80%d0%be%d0%b8%d0%b7%d0%b2%d0%be%d0%b4%d0%b8%d1%82%d1%81%d1%8f-&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;Lambda -@@ lambda $name(&amp;hellip;) @@ ::= @@ @$name( @$&amp;hellip; ) ::= ( _( @$&amp;hellip; ) ::= @&lt;strong&gt;PRAGMA_FINALIZE&lt;/strong&gt;( @), {, {+, {-, {* ) @@&lt;/p&gt; -&lt;h3 id=&#34;примеры-использования-макросов&#34;&gt;Примеры использования макросов&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80%d1%8b-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Обычные макросы (тело макроса корректное выражение)&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@macro@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; replace&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@macro2&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;arg&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt; call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;@&lt;span style=&#34;color:#000&#34;&gt;$arg&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; call&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;()}&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;p&gt;Примеры использования макросов:&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Обычные макросы (тело макроса корректное выражение)&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;macro&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;replace&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;();&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;macro2&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;arg&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;call&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;arg&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;);&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;call&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;()};&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Тело макросов из последовательности лексем&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@if&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;...&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@ &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;\$&lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;*&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;--&amp;gt; @@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Выражение может быть не полным&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@elif&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;...&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt;@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@ ,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#4e9a06&#34;&gt;\$&lt;/span&gt;&lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;elif&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt;*&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;--&amp;gt; @@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@else@@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@ ,&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;[&lt;/span&gt;_&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;]&lt;/span&gt;--&amp;gt; @@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Выражение может быть не полным&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;elif&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,[&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#a40000&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,[&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;@@&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# Запись условного оператора с использованием &lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#8f5902;font-style:italic&#34;&gt;# определенных выше макросов&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt; condition &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;){&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ... -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;elif&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;(&lt;/span&gt; condition2 &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ... -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#204a87;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;{&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ... -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Зачем нужна трансформация синтаксиса? -Нативная поддержка других языков нужна чтобы не переписывать легаси код на этих языках.&lt;/p&gt; -&lt;p&gt;Чтобы можно было использовать существующие исходники как собственные требуется настройка работы -препроцессора и лексера под конкретный язык программирования (описание DSL). -Для &lt;strong&gt;С/С++&lt;/strong&gt; потребуется выделять лексером комментарии из-за пересечения синтаксиса (которые сейчас игнорируются). -Для &lt;strong&gt;Python&lt;/strong&gt; требуется выделять лексером отступы (которые сейчас тоже игнорируются), причем потребуется реализация не только синтаксиса, -но и зависимых пакетов с последующая трансляцией этого кода в С++, что в настоящий момент делать не целесообразно (cython ???).&lt;/p&gt; -&lt;p&gt;Но так как возможность трансформации кода с других языков программирования принципиальная возможна, -стоит над этим думать только после полноценного релиза NewLang и его перехода в прод.&lt;/p&gt; -&lt;p&gt;Для реализации DSL требуется передача команд в парсер для управления его работой (по аналогии с командой #pragma) -Но так как обработка таких команд должна происходить в лексере до передачи данных в парсер (анализатор), -то команды для макропроцессора должны быть в максимально простом виде и состоять из элементов, -которые лексер может самостоятельно идентифицировать, т.е. термины, строки и цифры (без выражений и именованных аргументов).&lt;/p&gt; -&lt;p&gt;После обработки такой команды она анализируется макропроцессором и удаляется из потока лексем, т.е. в парсер (анализатор) не передается. -Но в случае ошибки с синтаксисе, данные команды нужно уметь однозначно идентифировать и самый простой способ, -комбинация признака макроса и системного имени, т.е. что-то вроде&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; @__PRAGMA_DIAG__(push) - @__PRAGMA_DIAG__(ignored, &amp;#34;-Wundef&amp;#34;) - @__PRAGMA_DIAG__(warning, &amp;#34;-Wformat&amp;#34;) - @__PRAGMA_DIAG__(error &amp;#34;-Wuninitialized&amp;#34;) - @__PRAGMA_DIAG__(pop) - - #pragma message &amp;#34;Compiling &amp;#34; __FILE__ &amp;#34;...&amp;#34; - @__PRAGMA_MESSAGE__(&amp;#34;Compiling &amp;#34;, __FILE__, &amp;#34;...&amp;#34;) - - #pragma error &amp;#34;Error &amp;#34; __FILE__ &amp;#34;...&amp;#34; - @__PRAGMA_ERROR__(&amp;#34;Error &amp;#34;, __FILE__, &amp;#34;...&amp;#34;) - - -#define DO_PRAGMA(x) _Pragma (#x) -#define TODO(x) DO_PRAGMA(message (&amp;#34;TODO - &amp;#34; #x)) - -@@TODO( ... )@@ := @__PRAGMA_MESSAGE__(&amp;#34;TODO - &amp;#34;, @*) - -@TODO(Remember to fix this) # note: TODO - Remember to fix this - -\\.__lexer__ignore_space__ = 1; -\\.__lexer__ignore_indent__ = 1; -\\.__lexer__ignore_comment__ = 1; -\\.__lexer__ignore_crlf__ = 1; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Таким образом можно трансформировать условный оператор на питоне в синтаксис NewLang следующим макросом:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; -#pragma clang attribute push -#pragma clang diagnostic ignored &amp;#34;-Wundef&amp;#34; -#pragma clang diagnostic ignored &amp;#34;-Wunused-variable&amp;#34; - - -#elif __GNUC__ - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored &amp;#34;-Wuninitialized&amp;#34; - -#pragma GCC diagnostic ignored &amp;#34;-Wall&amp;#34; -#pragma GCC diagnostic ignored &amp;#34;-Wextra&amp;#34; - - @pragma warning(pop) - - @@ pragma warning(...) @@ := __PRAGMA_TERM_DIAG_WARNING__(); -@__PRAGMA_DIAG__(warning, pop); +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@if&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;condition&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;){&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@elif&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;condition2&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@else&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Например цикл до 5:&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;lt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;5&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;42&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;--&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;+=&lt;/span&gt;&lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Будет выглядеть более привычно:&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@while&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;true&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@if&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;5&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;{&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#5c35cc;font-weight:bold&#34;&gt;@return&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;42&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#0000cf;font-weight:bold&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;};&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; -Обработка терминов в макропроцессоре в максимально простом виде. -Агрументы только термины, строки и цифры без вложенных выражений и именованных аргументов, -т.е. только элементы, которые может самостоятельно идентифицировать лексер. +&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; +&lt;h3 id=&#34;далее-идеи-на-будущее&#34;&gt;Далее идеи на будущее&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b4%d0%b0%d0%bb%d0%b5%d0%b5-%d0%b8%d0%b4%d0%b5%d0%b8-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; +&lt;h3 id=&#34;символьное-программирование&#34;&gt;Символьное программирование&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d0%bc%d0%b2%d0%be%d0%bb%d1%8c%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -@warning(&amp;#34;--&amp;#34;) - @@ if ... : @@ := @@ [ @$* ]-&amp;gt; __TERM_BLOCK_INDENT__(&amp;#34;{&amp;#34;, force_semicolon=1) @@ - - if __name__ == &amp;#34;__main__&amp;#34;: - run1() - run2() +&lt;/div&gt; - [ __name__ == &amp;#34;__main__&amp;#34; ]-&amp;gt; { - run1(); - run2(); - }; - - -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ключ &amp;ndash;parser-syntax-only только текстовый парсинг исходного кода без загрузки модулей, раскрытия макросов и проверки имен.&lt;/p&gt; -&lt;p&gt;Ключ &amp;ndash;parser-no-macros - без раскрытия макросов -Ключ &amp;ndash;parser-no-module - без загрузки модулей (и мокросов, если они в них определяются) -Ключ &amp;ndash;parser-no-check-prototype - без проверки имен при обращении&lt;/p&gt; -&lt;p&gt;prototype -@&lt;strong&gt;PRAGMA_PROTOTYPE&lt;/strong&gt;(define) -@&lt;strong&gt;PRAGMA_PROTOTYPE&lt;/strong&gt;(implement)&lt;/p&gt; -&lt;p&gt;$$&lt;/p&gt; -&lt;p&gt;\$ - корень системы (система)&lt;/p&gt; -&lt;p&gt;$ - текущий модуль&lt;/p&gt; -&lt;h1 id=&#34;макросы-для-конвертора-проверки-в-python&#34;&gt;Макросы для конвертора проверки в Python&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b4%d0%bb%d1%8f-%d0%ba%d0%be%d0%bd%d0%b2%d0%b5%d1%80%d1%82%d0%be%d1%80%d0%b0-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b8-%d0%b2-python&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;h1 id=&#34;if-__name__--__main__&#34;&gt;if &lt;strong&gt;name&lt;/strong&gt; == &amp;ldquo;&lt;strong&gt;main&lt;/strong&gt;&amp;rdquo;:&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#if-__name__--__main__&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;@@ &lt;strong&gt;name&lt;/strong&gt; @@ ::= @@ $. @&lt;strong&gt;PRAGMA_NO_MACRO&lt;/strong&gt;() &lt;strong&gt;name&lt;/strong&gt; @@ -@@ if $&amp;hellip; @: @@ ::= @@ [ @$&amp;hellip; ] &amp;ndash;&amp;gt; @@&lt;/p&gt; -&lt;p&gt;@if( $.&lt;strong&gt;name&lt;/strong&gt; == &amp;ldquo;&lt;strong&gt;main&lt;/strong&gt;&amp;rdquo; ) {&lt;/p&gt; -&lt;p&gt;}&lt;/p&gt; -&lt;p&gt;\каталог\модуль() - статический импорт модуля -\(&amp;ldquo;каталог\модуль&amp;rdquo;)() - динамический импорт модуля&lt;/p&gt; -&lt;p&gt;printf := :Pointer(&amp;lsquo;printf(format:FmtChar, &amp;hellip;):Int32&amp;rsquo;); -printf := %printf(format:FmtChar, &amp;hellip;):Int32;&lt;/p&gt; -&lt;h1 id=&#34;регистрация-прототипа-нативной-функции&#34;&gt;Регистрация прототипа нативной функции&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%80%d0%b5%d0%b3%d0%b8%d1%81%d1%82%d1%80%d0%b0%d1%86%d0%b8%d1%8f-%d0%bf%d1%80%d0%be%d1%82%d0%be%d1%82%d0%b8%d0%bf%d0%b0-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;@prototype -%puts(format:StrChar):Int32;&lt;/p&gt; -&lt;h1 id=&#34;импорт-нативной-функции-с-предварительной-проверкой-её-наличия-во-время-компиляции-статическая-линковка&#34;&gt;Импорт нативной функции с предварительной проверкой её наличия во время компиляции (статическая линковка)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b8%d0%bc%d0%bf%d0%be%d1%80%d1%82-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d1%81-%d0%bf%d1%80%d0%b5%d0%b4%d0%b2%d0%b0%d1%80%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d0%be%d0%b9-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%be%d0%b9-%d0%b5%d1%91-%d0%bd%d0%b0%d0%bb%d0%b8%d1%87%d0%b8%d1%8f-%d0%b2%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d1%8f-%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%86%d0%b8%d0%b8-%d1%81%d1%82%d0%b0%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bb%d0%b8%d0%bd%d0%ba%d0%be%d0%b2%d0%ba%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;puts2(format:StrChar):Int32 := %puts(format:StrChar):Int32;&lt;/p&gt; -&lt;h1 id=&#34;импорт-нативной-функции-по-её-прототипу-во-время-выполнения-динамическая-линковка&#34;&gt;Импорт нативной функции по её прототипу во время выполнения (динамическая линковка)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b8%d0%bc%d0%bf%d0%be%d1%80%d1%82-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d0%bf%d0%be-%d0%b5%d1%91-%d0%bf%d1%80%d0%be%d1%82%d0%be%d1%82%d0%b8%d0%bf%d1%83-%d0%b2%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d1%8f-%d0%b2%d1%8b%d0%bf%d0%be%d0%bb%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b4%d0%b8%d0%bd%d0%b0%d0%bc%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bb%d0%b8%d0%bd%d0%ba%d0%be%d0%b2%d0%ba%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;puts3(format:StrChar):Int32 := :Pointer(&amp;lsquo;puts(format:StrChar):Int32&amp;rsquo;);&lt;/p&gt; -&lt;p&gt;%puts(&amp;lsquo;Тест вывода строки&amp;rsquo;); # Линковка с нативной функцией во время компиляции и непосредственный вызов с оптимизацией передачи параметров -puts2(&amp;lsquo;Тест 2 вывода строки&amp;rsquo;); # Линковка с нативной функцией во время компиляции -puts3(&amp;lsquo;Тест 3 вывода строки&amp;rsquo;); # Линковка с нативной функцией во время выполнения при первом вызове puts3&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Парсинг исходного текста без раскрытия макросов и загрузки модулей&lt;/li&gt; -&lt;li&gt;Парсинг исходного текста с раскрытием макросов (требуется загрузка модулей для зависимых и переопределяемых макросов)&lt;/li&gt; -&lt;li&gt;Загружатся модули могут как в виде исходников (которые требуется парсить и компилировть/выполнять) -или в виде бинарников (в них должны быть список макросов, типов и имена объектов)&lt;/li&gt; -&lt;li&gt;После парсинга получается список &lt;strong&gt;имен&lt;/strong&gt; макросов, типов и объектов (TermPtr)&lt;/li&gt; -&lt;li&gt;После выполнения модуля - список &lt;strong&gt;имен&lt;/strong&gt; заполняется реальными объектами (ObjPtr).&lt;/li&gt; -&lt;/ul&gt; -&lt;h1 id=&#34;компиляция-файла&#34;&gt;Компиляция файла&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%86%d0%b8%d1%8f-%d1%84%d0%b0%d0%b9%d0%bb%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;ul&gt; -&lt;li&gt;Парсинг исходника для построения AST (без анализа имен, связей, загрузки модулей и пр. только исходые тексты с раскрытием макросов&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;/ul&gt; -&lt;h1 id=&#34;систематизация-реализации-макросов&#34;&gt;Систематизация реализации макросов&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0%d1%82%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d1%80%d0%b5%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d0%b8-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;последовательность лексем MACRO_SEQ мужду @@ @@ сохраняется в m_block, так как фрагменты блоков не могут быть идентификаторами&lt;/p&gt; -&lt;p&gt;Разбор макросов происходит в лексере. Определением макроса всегда является целая строка, -которая заканчивается точкой с запятой, а идентификатором макроса всегда выступает последовательность лексем:&lt;/p&gt; -&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@ id @@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; macro&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@ id @@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@ @@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; @@ id @@ :&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;=&lt;/span&gt; @@@ @@@&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Хранилищем текущих максросов является объект класса MacroBuffer. -Последовательность лексем идентификатора (id) макроса должна сохраняется в отдельном поле термина и однозначно его идентифицирует. -Первый термин в идентификаторе хранится как ключ hashmap, а дальше происходит поиск полным перебором. -Этапы работы с макросами&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt; -&lt;p&gt;Входные термины из лексера получаются вызовом GetNextToken, внутри которой и происходит раскрытие макросов. -Внутренний буфер заполняется до окончания строки (выражения), т.е. до символа &amp;lsquo;;&amp;rsquo; или &lt;END&gt;, после чего производится -поиск макросов в объекте MacroBuffer для текущей последовательности лексем в буфере.&lt;/p&gt; -&lt;/li&gt; -&lt;li&gt; -&lt;p&gt;Если макрос найден, то соответствющая ему последоваетльность заменяется на тело макроса и происходит переход -на повторный анализ входного буфера.&lt;/p&gt; -&lt;/li&gt; -&lt;li&gt; -&lt;p&gt;Если макрос не найден, то данные передаются в парсер для дальнейшего синтаксическго анализа.&lt;/p&gt; -&lt;/li&gt; -&lt;li&gt; -&lt;p&gt;Для этого во входном потоке лексем (parser.y) во время оператората создания/присвоения вызывается функция проверки на макрос. -MacroBuffer::CheckMacroAndConvertDel($$), и после этого выходному значению присваивается результат выполнения driver.MacroEval($$), -и в дальнейшем этот макрос никак не обработывается.&lt;/p&gt; -&lt;/li&gt; -&lt;li&gt; -&lt;p&gt;Создание макросов, проверка на дубликаты и логические ошибки в определении происходит путем обращения к методам объекта MacroBuffer.&lt;/p&gt; -&lt;p&gt;/*&lt;/p&gt; -&lt;ul&gt; -&lt;li&gt;Макросы хрянтся как фрагменты AST в виде объектов типа Term,&lt;/li&gt; -&lt;li&gt;так как создаются после обработки парсером по правилам стандратной грамматики.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Но анализ входных данных на предмет раскрытия макросов проиходит из потока (последовательности) лексем,&lt;/li&gt; -&lt;li&gt;т.е. &lt;strong&gt;ДО&lt;/strong&gt; обработки парсером, так как при раскрытии макросов может меняться грамматика выражений.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Функция \ref CompareMacro сравнивает входной буфер (последовательность лексем)&lt;/li&gt; -&lt;li&gt;на предмет возможного соответствия одному конкретному макросу.&lt;/li&gt; -&lt;li&gt;Сравниваются только ключевые словам без учета аргументов в скобках,&lt;/li&gt; -&lt;li&gt;но само наличие аргументов проверяется ??????????????????&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Проблема:&lt;/li&gt; -&lt;li&gt;К функции можно обратится с целью её вызова (указав после имени скобки),&lt;/li&gt; -&lt;li&gt;так и по имени без скобок (например для получения ссылки на объект).&lt;/li&gt; -&lt;li&gt;Так и к переменной можно обратиться только по имени,&lt;/li&gt; -&lt;li&gt;так и указав скобки после имени как к функции (при копировании объекта).&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Сделать один макрос под оба сценария (со скобками и без скобок) не получится, так как непонятно,&lt;/li&gt; -&lt;li&gt;что делать с аргументами при раскрытии тела макроса, когда они не указаны.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Но может быть следует переименовывать только одно имя без учета скобок,&lt;/li&gt; -&lt;li&gt;например, оставив такую возможность только для одиночных макросов.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;\name -&amp;gt; name или name (&amp;hellip;), hash: name&lt;/li&gt; -&lt;li&gt;но \name(&amp;hellip;) -&amp;gt; name(&amp;hellip;), а name - ошибка !!!! hash: name&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Или все же следует различать макросы со скобками и без скобок как два разных объекта???&lt;/li&gt; -&lt;li&gt;\name := name2; и \name(&amp;hellip;) := name2(&amp;hellip;); будут разными объектами&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Или добавить макросы-алиасы без аргументов только для переименования отдельных терминов?&lt;/li&gt; -&lt;li&gt;\alias :- name2; но как их отличать от обычных макросов в операции удаления?&lt;/li&gt; -&lt;li&gt;Или вообще не нужно отличать и оставить только один варинат (либо макрос, либо алиас)&lt;/li&gt; -&lt;li&gt;Тода вопрос со скобками закрывается сам собой, алиасы всегда без скобок,&lt;/li&gt; -&lt;li&gt;макросы со скбками или без скобок, но должно быть полное соответствие.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;@ name name2 @ -&amp;gt; name name2, но name name2(&amp;hellip;) - ошибка!!! (hash: name,name2)&lt;/li&gt; -&lt;li&gt;@ name name2(&amp;hellip;) @ -&amp;gt; name name2(&amp;hellip;), но name name2 - ошибка !!!! (hash: name,name2)&lt;/li&gt; -&lt;li&gt;@ name name2&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; @ -&amp;gt; name name2&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt;, но name name2 - ошибка !!!! ( hash: name,name2 )&lt;/li&gt; -&lt;li&gt;@ name $tmpl&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; name3@ -&amp;gt; name $tmpl&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Но!&lt;/li&gt; -&lt;li&gt;@ name name2 @ ::- -&amp;gt; name name2 - ок, но name name2(&amp;hellip;) - ок&lt;/li&gt; -&lt;li&gt;@ name $tmpl name3@ ::- -&amp;gt; name $tmpl&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; name3 - ок, name $tmpl(&amp;hellip;) name3[&amp;hellip;] - ок&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Для последовательности лексем требуется полное соответствие с учетом скобок ???&lt;/li&gt; -&lt;li&gt;и может ли быть несколько скобок одного типа (несколько крыглях, или несколько квардратных????&lt;/li&gt; -&lt;li&gt;&amp;lt;Может быть несколько скобок одного типа, например, при указании типа у аргументов или типа возвращаемого значения.&amp;gt;&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;@ name name2 @ -&amp;gt; name name2, но name name2(&amp;hellip;) - ошибка!!! (hash: name,name2)&lt;/li&gt; -&lt;li&gt;@ name name2(&amp;hellip;) @ -&amp;gt; name name2(&amp;hellip;), но name name2 - ошибка !!!! (hash: name,name2)&lt;/li&gt; -&lt;li&gt;@ name name2&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; @ -&amp;gt; name name2&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt;, но name name2 - ошибка !!!! ( hash: name,name2 )&lt;/li&gt; -&lt;li&gt;@ name $tmpl&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; name3@ -&amp;gt; name $tmpl&lt;a href=&#34;...&#34;&gt;&amp;hellip;&lt;/a&gt; name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;Проблема скобок возникает из-за сценария замены одного термина на другой,&lt;/li&gt; -&lt;li&gt;который есть в препроцессоре С/С++, но отсутствует при реализации с использованием шаблонов.&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;li&gt;&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;*/&lt;/p&gt; -&lt;/li&gt; -&lt;/ul&gt; -&lt;p&gt;Макросы используются и для превращеня исходного кода &lt;em&gt;NewLang&lt;/em&gt; в более привычный синтаксис на основе &lt;a href=&#34;https://newlang.net/syntax_dsl.html&#34;&gt;ключевых слов&lt;/a&gt;, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода.&lt;/p&gt; -&lt;p&gt;&lt;a href=&#34;https://newlang.net/syntax_dsl.html&#34;&gt;Например:&lt;/a&gt;.&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; @@if(...)@@ ::= @@ [ \$* ]--&amp;gt; @@; - @@while(...)@@ ::= @@ [\$*] &amp;lt;-&amp;gt; @@; - @@return $arg@@::= @@ -- \$arg -- @@; - @@true@@ ::= 1; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Тогда цикл до 5:&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;count:=1; -[ 1 ] &amp;lt;-&amp;gt; { - [count&amp;gt;5] --&amp;gt; { - -- 42 --; - }; - count+=1; -}; -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;будет выглядеть более привычно&lt;/p&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;count:=1; -while( true ) { - if(count&amp;gt;5) { - return 42; - }; - count+=1; -}; -&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;идеи-на-будущее&#34;&gt;Идеи на будущее&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%b8%d0%b4%d0%b5%d0%b8-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h3 id=&#34;символьное-программирование&#34;&gt;Символьное программирование&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d0%bc%d0%b2%d0%be%d0%bb%d1%8c%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; &lt;blockquote&gt; &lt;p&gt;Символьное программирование, часто называемое декларативным программированием, представляет собой парадигму программирования, которая использует математическую логику, отношения и символы для представления знаний и помощи в решении проблем. Вместо того, чтобы сосредотачиваться на описании последовательности операций, необходимых для выполнения вычислений, как в императивном программировании, символическое программирование делает упор на выражении отношений и ограничений между структурами данных, уделяя особое внимание «что», а не «как».&lt;/p&gt; &lt;p&gt;В контексте парадигм программирования символическое программирование часто противопоставляется процедурному или императивному программированию, где программы определяют пошаговые процедуры для достижения своих целей. В то время как императивное программирование фокусируется на описании потока управления с использованием таких конструкций, как циклы и условные выражения, для управления выполнением, символическое программирование сосредоточено на выражении фактов о проблеме и позволяет выполнению естественным образом выводить последующие последствия из предоставленной информации.&lt;/p&gt; @@ -1617,195 +1381,105 @@ my_file.write(&amp;lsquo;hello world&amp;rsquo;)&lt;/p&gt; <description> - &lt;h2 id=&#34;dsl&#34;&gt;DSL&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#dsl&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h3 id=&#34;особенности-ассоциативной-памяти&#34;&gt;Особенности ассоциативной памяти&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d1%81%d0%be%d0%b1%d0%b5%d0%bd%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b0%d1%81%d1%81%d0%be%d1%86%d0%b8%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; + &lt;h3 id=&#34;особенности-ассоциативной-памяти&#34;&gt;Особенности ассоциативной памяти&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d1%81%d0%be%d0%b1%d0%b5%d0%bd%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b0%d1%81%d1%81%d0%be%d1%86%d0%b8%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; &lt;p&gt;Синтаксис языка &lt;em&gt;NewLang&lt;/em&gt; основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например &lt;strong&gt;if&lt;/strong&gt;, чем комбинация &lt;em&gt;минус минус правая угловая скобка&lt;/em&gt; &lt;strong&gt;&amp;ndash;&amp;gt;&lt;/strong&gt;. Из-за этого имеет смысл использовать не &amp;ldquo;чистый&amp;rdquo; базовый синтаксис, а более привычный диалект с использованием ключевых слов.&lt;/p&gt; -&lt;h3 id=&#34;синтаксис-на-ключевых-словах&#34;&gt;Синтаксис на ключевых словах&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81-%d0%bd%d0%b0-%d0%ba%d0%bb%d1%8e%d1%87%d0%b5%d0%b2%d1%8b%d1%85-%d1%81%d0%bb%d0%be%d0%b2%d0%b0%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;В файле dsl.nlp находится набор макросов, которые расширяют базовый синтаксис &lt;em&gt;NewLang&lt;/em&gt;, основанный на правилах, -набором предопределенных ключевых слов как в классических языках программирования. -А при необходимости, их можно адаптировать или дополнить под собственную предметную область.&lt;/p&gt; -&lt;h2 id=&#34;константы&#34;&gt;Константы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%ba%d0%be%d0%bd%d1%81%d1%82%d0%b0%d0%bd%d1%82%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;h3 id=&#34;логические&#34;&gt;Логические&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bb%d0%be%d0%b3%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; +&lt;p&gt;&lt;em&gt;NewLang&lt;/em&gt; уже содержит набор макросов, которые расширяют базовый синтаксис &lt;em&gt;NewLang&lt;/em&gt;, основанный на правилах, +набором предопределенных ключевых слов как в классических языках программирования, +которые можно адаптировать или дополнить под собственную предметную область.&lt;/p&gt; +&lt;h3 id=&#34;константы&#34;&gt;Константы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%ba%d0%be%d0%bd%d1%81%d1%82%d0%b0%d0%bd%d1%82%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; -&lt;li&gt;&lt;strong&gt;true&lt;/strong&gt; - 1&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;yes&lt;/strong&gt; - 1&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;false&lt;/strong&gt; - 0&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;no&lt;/strong&gt; - 0&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@true&lt;/em&gt; - 1&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@yes&lt;/em&gt; - 1&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@false&lt;/em&gt; - 0&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@no&lt;/em&gt; - 0&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@this&lt;/em&gt; или &lt;em&gt;@self&lt;/em&gt; - Текущий объект&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@super&lt;/em&gt; - Родительский объект&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@latter&lt;/em&gt; или &lt;em&gt;@last&lt;/em&gt;- Результат выполенения последнего оператора Result of the last operation&lt;/p&gt; +&lt;/li&gt; &lt;/ul&gt; -&lt;h3 id=&#34;системные-имена&#34;&gt;Системные имена&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%8b%d0%b5-%d0%b8%d0%bc%d0%b5%d0%bd%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; +&lt;h3 id=&#34;логические-операторы&#34;&gt;Логические операторы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bb%d0%be%d0%b3%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b8%d0%b5-%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; -&lt;li&gt;&lt;strong&gt;this&lt;/strong&gt; - Текущий объект (&lt;strong&gt;$0&lt;/strong&gt;)&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;parent&lt;/strong&gt; - Родительский объект (&lt;strong&gt;$$&lt;/strong&gt;)&lt;/li&gt; -&lt;li&gt;&lt;strong&gt;last&lt;/strong&gt; - Результат выполнения последнего оператора (&lt;strong&gt;$^&lt;/strong&gt;)&lt;/li&gt; +&lt;li&gt;&lt;em&gt;@and&lt;/em&gt; - Логическое &lt;strong&gt;И&lt;/strong&gt;&lt;/li&gt; +&lt;li&gt;&lt;em&gt;@or&lt;/em&gt; - Логическое &lt;strong&gt;ИЛИ&lt;/strong&gt;&lt;/li&gt; +&lt;li&gt;&lt;em&gt;@xor&lt;/em&gt; - Логическое &lt;strong&gt;Исключающее ИЛИ&lt;/strong&gt;&lt;/li&gt; +&lt;li&gt;&lt;em&gt;@not(value)&lt;/em&gt; - Логическое отрицание&lt;/li&gt; &lt;/ul&gt; -&lt;p&gt;!!!!!!!!- &lt;strong&gt;args&lt;/strong&gt; - Все аргументы функции (&lt;strong&gt;$*&lt;/strong&gt;)&lt;/p&gt; -&lt;p&gt;!!!!!!!!- &lt;strong&gt;sys&lt;/strong&gt; - Системный контекст запущенной программы (&lt;strong&gt;@@&lt;/strong&gt;) -!!!!!!!!- &lt;strong&gt;current&lt;/strong&gt; - Текущий модуль (&lt;strong&gt;@$&lt;/strong&gt;) -!!!!!!!!- &lt;strong&gt;cmd&lt;/strong&gt; - Все аргументы выполняющегося приложения из командной строки (&lt;strong&gt;@*&lt;/strong&gt;)&lt;/p&gt; -&lt;p&gt;!!!!!!!!!!1### Типовые функции и проверки -!!!!!!!!!!- &lt;strong&gt;run(&amp;lsquo;filename&amp;rsquo;)&lt;/strong&gt; - Выполнить указанный файл (&lt;strong&gt;@@(&amp;lsquo;filename&amp;rsquo;)&lt;/strong&gt;) -!!!!!!!!!!- &lt;strong&gt;ifmain&lt;/strong&gt; - Проверка, если текущий модуль основной (&lt;strong&gt;[@$.$0] &amp;ndash;&amp;gt;&lt;/strong&gt; { &amp;hellip; }) -!!!!!!!!!!- &lt;strong&gt;ifload&lt;/strong&gt; - Проверка, если текущий модуль загружается впервые (&lt;strong&gt;[@$.&lt;strong&gt;load&lt;/strong&gt;] &amp;ndash;&amp;gt;&lt;/strong&gt; { &amp;hellip; })&lt;/p&gt; &lt;h3 id=&#34;операторы&#34;&gt;Операторы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%be%d0%bf%d0%b5%d1%80%d0%b0%d1%82%d0%be%d1%80%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; &lt;ul&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;match(cond)&lt;/strong&gt; - Оператор &lt;a href=&#34;https://newlang.net/ops.html#%D0%BE%D1%86%D0%B5%D0%BD%D0%BA%D0%B0-%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F&#34;&gt;оценки выражения&lt;/a&gt;&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@if(&amp;hellip;)&lt;/em&gt; - Первый условный оператор&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;if(&amp;hellip;)&lt;/strong&gt; - Первый условный оператор (&lt;strong&gt;[$*]&amp;ndash;&amp;gt;&lt;/strong&gt; { &amp;hellip; })&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@elif(&amp;hellip;)&lt;/em&gt; - Второй и все последующие условные операторы&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;elif(&amp;hellip;)&lt;/strong&gt; - Второй и все последующие (&lt;strong&gt;,[$*]&amp;ndash;&amp;gt;&lt;/strong&gt; { &amp;hellip; })&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@else&lt;/em&gt; - Оператор &lt;em&gt;иначе&lt;/em&gt;&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;else&lt;/strong&gt; - Оператор &lt;em&gt;иначе&lt;/em&gt; (&lt;strong&gt;,[_]&amp;ndash;&amp;gt;&lt;/strong&gt; { &amp;hellip; })&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@while(&amp;hellip;)&lt;/em&gt; - Оператор цикла с предусловием&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;while(cond)&lt;/strong&gt; - Оператор цикла с предусловием (&lt;strong&gt;[@$cond] &amp;lt;-&amp;gt;&lt;/strong&gt; { &amp;hellip; } )&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@dowhile(&amp;hellip;)&lt;/em&gt; - Оператор цикла с постусловием&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;dowhile(cond)&lt;/strong&gt; - Оператор цикла с постусловием ({ &amp;hellip; } &lt;strong&gt;&amp;lt;-&amp;gt;[@$cond]&lt;/strong&gt;)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@loop&lt;/em&gt; - Оператор безконечного цикла&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;iter(obj, &amp;hellip; )&lt;/strong&gt; - Создание итератора ( &lt;strong&gt;@$obj&lt;/strong&gt; ? (@$*) )&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@break $label&lt;/em&gt; - Оператор выхода из именованного именованного блока кода&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;next(obj, &amp;hellip; )&lt;/strong&gt; - Следующий элемент итератора ( &lt;strong&gt;@$obj&lt;/strong&gt; ! ($*) )&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@continue $label&lt;/em&gt; - Оператор прехода на начало именованного блока кода&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;curr(obj, &amp;hellip; )&lt;/strong&gt; - Текущий элемент итератора ( &lt;strong&gt;@$obj&lt;/strong&gt; !? ($*) )&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@return( result )&lt;/em&gt; - Оператор возврата значения и выхода из функции&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;first(obj)&lt;/strong&gt; - Перейти на первый элемент итератора ( &lt;strong&gt;@$obj&lt;/strong&gt; !! )&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@throw( error )&lt;/em&gt; - Оператор создания исключения и возврата ошибки&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;all(obj)&lt;/strong&gt; - Получить сразу все элементы итератора ( &lt;strong&gt;@$obj&lt;/strong&gt; ??)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@match( &amp;hellip; )&lt;/em&gt; - Оператор оценки выражения&lt;/p&gt; &lt;/li&gt; -&lt;/ul&gt; -&lt;h3 id=&#34;прерывания&#34;&gt;Прерывания&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b5%d1%80%d1%8b%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;ul&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;return&lt;/strong&gt; - Положительное прерывание (&lt;strong&gt;++&lt;/strong&gt;)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@case( &amp;hellip; )&lt;/em&gt; - Оператор сравнения с образцом&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;return(&amp;hellip;)&lt;/strong&gt;- Положительное прерывание с возвратом значения (&lt;strong&gt;++&lt;/strong&gt; @$value &lt;strong&gt;++&lt;/strong&gt;)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@default&lt;/em&gt; - Оператор выбора по улочанию&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;error&lt;/strong&gt; - Отрицательное прерывание (&lt;strong&gt;--&lt;/strong&gt;)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@iter(obj, &amp;hellip; )&lt;/em&gt; - Создание итератора&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;error(&amp;hellip;)&lt;/strong&gt; - Отрицательное прерывание с возвратом значения (&lt;strong&gt;--&lt;/strong&gt; @$value &lt;strong&gt;--&lt;/strong&gt;)&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@next(obj, &amp;hellip; )&lt;/em&gt; - Получить следующий элемент итератора&lt;/p&gt; &lt;/li&gt; &lt;li&gt; -&lt;p&gt;&lt;strong&gt;break+&lt;/strong&gt; и &lt;strong&gt;break-&lt;/strong&gt; - Выход из цикла:&lt;/p&gt; +&lt;p&gt;&lt;em&gt;@curr(obj, &amp;hellip; )&lt;/em&gt; - Получить текущий элемент итератора&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@first(obj)&lt;/em&gt; - Перейти на первый элемент итератора&lt;/p&gt; +&lt;/li&gt; +&lt;li&gt; +&lt;p&gt;&lt;em&gt;@all(obj)&lt;/em&gt; - Получить сразу все элементы итератора&lt;/p&gt; &lt;/li&gt; &lt;/ul&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; while(...) {+ - ++ :Break ++ - +} - while(...) {- - -- :Break -- - -} -&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt; -&lt;li&gt;&lt;strong&gt;continue+&lt;/strong&gt; и &lt;strong&gt;continue-&lt;/strong&gt; - В начало цикла:&lt;/li&gt; -&lt;/ul&gt; -&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; while(...) {+ - ++ :Continue ++ - +} - while(...) {- - -- :Continue -- - -} -&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;obj { -.field = 1; -.prop(); -};&lt;/p&gt; -&lt;p&gt;#Python&lt;/p&gt; -&lt;h1 id=&#34;1-without-using-with-statement&#34;&gt;1) without using with statement&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#1-without-using-with-statement&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;file = open(&amp;lsquo;file_path&amp;rsquo;, &amp;lsquo;w&amp;rsquo;) -file.write(&amp;lsquo;hello world !&amp;rsquo;) -file.close()&lt;/p&gt; -&lt;h1 id=&#34;2-without-using-with-statement&#34;&gt;2) without using with statement&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#2-without-using-with-statement&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;file = open(&amp;lsquo;file_path&amp;rsquo;, &amp;lsquo;w&amp;rsquo;) -try: -file.write(&amp;lsquo;hello world&amp;rsquo;) -finally: -file.close()&lt;/p&gt; -&lt;p&gt;open(&amp;lsquo;file_path&amp;rsquo;, &amp;lsquo;w&amp;rsquo;) { -.write(&amp;lsquo;hello world !&amp;rsquo;); -.close(); -}&lt;/p&gt; -&lt;p&gt;Python3&lt;/p&gt; -&lt;h1 id=&#34;using-with-statement&#34;&gt;using with statement&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#using-with-statement&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;with open(&amp;lsquo;file_path&amp;rsquo;, &amp;lsquo;w&amp;rsquo;) as file: -file.write(&amp;lsquo;hello world !&amp;rsquo;)&lt;/p&gt; -&lt;h1 id=&#34;a-simple-file-writer-object&#34;&gt;a simple file writer object&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#a-simple-file-writer-object&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;class MessageWriter(object): -def &lt;strong&gt;init&lt;/strong&gt;(self, file_name): -self.file_name = file_name&lt;/p&gt; -&lt;pre&gt;&lt;code&gt;def __enter__(self): - self.file = open(self.file_name, &#39;w&#39;) - return self.file - -def __exit__(self, *args): - self.file.close() -&lt;/code&gt;&lt;/pre&gt; -&lt;h1 id=&#34;using-with-statement-with-messagewriter&#34;&gt;using with statement with MessageWriter&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#using-with-statement-with-messagewriter&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;with MessageWriter(&amp;lsquo;my_file.txt&amp;rsquo;) as xfile: -xfile.write(&amp;lsquo;hello world&amp;rsquo;)&lt;/p&gt; -&lt;h1 id=&#34;a-simple-file-writer-object-1&#34;&gt;a simple file writer object&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#a-simple-file-writer-object-1&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;:MessageWriter { -def &lt;strong&gt;init&lt;/strong&gt;(self, file_name): -self.file_name = file_name&lt;/p&gt; -&lt;pre&gt;&lt;code&gt;def __enter__(self): - self.file = open(self.file_name, &#39;w&#39;) - return self.file - -def __exit__(self, *args): - self.file.close() -&lt;/code&gt;&lt;/pre&gt; -&lt;p&gt;}&lt;/p&gt; -&lt;h1 id=&#34;using-with-statement-with-messagewriter-1&#34;&gt;using with statement with MessageWriter&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#using-with-statement-with-messagewriter-1&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;MessageWriter(&amp;lsquo;my_file.txt&amp;rsquo;) { -.write(&amp;lsquo;hello world&amp;rsquo;); -};&lt;/p&gt; -&lt;p&gt;from contextlib import contextmanager&lt;/p&gt; -&lt;p&gt;class MessageWriter(object): -def &lt;strong&gt;init&lt;/strong&gt;(self, filename): -self.file_name = filename&lt;/p&gt; -&lt;pre&gt;&lt;code&gt;@contextmanager -def open_file(self): - try: - file = open(self.file_name, &#39;w&#39;) - yield file - finally: - file.close() -&lt;/code&gt;&lt;/pre&gt; -&lt;h1 id=&#34;usage&#34;&gt;usage&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#usage&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;message_writer = MessageWriter(&amp;lsquo;hello.txt&amp;rsquo;) -with message_writer.open_file() as my_file: -my_file.write(&amp;lsquo;hello world&amp;rsquo;)&lt;/p&gt; -&lt;p&gt;:MessageWriter(object) { -def &lt;strong&gt;init&lt;/strong&gt;(self, filename): -self.file_name = filename&lt;/p&gt; -&lt;pre&gt;&lt;code&gt;@contextmanager -def open_file(self): - try: - file = open(self.file_name, &#39;w&#39;) - yield file - finally: - file.close() -&lt;/code&gt;&lt;/pre&gt; -&lt;p&gt;}&lt;/p&gt; -&lt;h1 id=&#34;usage-1&#34;&gt;usage&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#usage-1&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; -&lt;p&gt;message_writer = MessageWriter(&amp;lsquo;hello.txt&amp;rsquo;) -with message_writer.open_file() as my_file: -my_file.write(&amp;lsquo;hello world&amp;rsquo;)&lt;/p&gt; -&lt;h1 id=&#34;приложения&#34;&gt;Приложения&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b8%d0%bb%d0%be%d0%b6%d0%b5%d0%bd%d0%b8%d1%8f&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h1&gt; &lt;h2 id=&#34;предопределенные-макросы&#34;&gt;Предопределенные макросы&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d1%80%d0%b5%d0%b4%d0%be%d0%bf%d1%80%d0%b5%d0%b4%d0%b5%d0%bb%d0%b5%d0%bd%d0%bd%d1%8b%d0%b5-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;При работе парсера &lt;em&gt;NewLang&lt;/em&gt; автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. +&lt;p&gt;При работе парсера &lt;em&gt;NewLang&lt;/em&gt; автоматически формируются несколько зарезервированных макросов, +часть из которых соответствуют макросам препроцессора у С/С++. Данные предопределенные макросы можно использовать как обычные константы.&lt;/p&gt; &lt;ul&gt; &lt;li&gt; diff --git a/docs/ru/docs/syntax/macros/index.html b/docs/ru/docs/syntax/macros/index.html index 132af6c9..89bca278 100644 --- a/docs/ru/docs/syntax/macros/index.html +++ b/docs/ru/docs/syntax/macros/index.html @@ -18,27 +18,27 @@ <link rel="icon" type="image/png" href="/favicons/android-192x192.png" sizes="192x192"> <title>Макросы | NewLang</title> -<meta name="description" content="Макросы в NewLang, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем). -Макросы обработываются во время работы лексера, т.е. перед передачей последовательности лексем в парсер, что позволяет с помощью маросов изменять фрагменты синтаксиса языка, например, при реализации собственных диалектов DSL. -Определение макросов Определение макросов аналогично определению других объектов и состоит из трех частей &amp;lt;имя макроса&amp;gt; &amp;lt;оператор создания/присвоения&amp;gt; &amp;lt;тело макроса&amp;gt; и завершающая точка с запятой &amp;ldquo;;&amp;rdquo;, т."> +<meta name="description" content="Макросы используются и для превращеня исходного кода NewLang в более привычный синтаксис на основе ключевых слов, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода. +Макросы в NewLang, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем). +Макросы обработываются во время работы лексера, т.е. перед передачей последовательности лексем в парсер, что позволяет с помощью маросов изменять фрагменты синтаксиса языка, например, при реализации собственных диалектов DSL."> <meta property="og:title" content="Макросы" /> -<meta property="og:description" content="Макросы в NewLang, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем). -Макросы обработываются во время работы лексера, т.е. перед передачей последовательности лексем в парсер, что позволяет с помощью маросов изменять фрагменты синтаксиса языка, например, при реализации собственных диалектов DSL. -Определение макросов Определение макросов аналогично определению других объектов и состоит из трех частей &lt;имя макроса&gt; &lt;оператор создания/присвоения&gt; &lt;тело макроса&gt; и завершающая точка с запятой &ldquo;;&rdquo;, т." /> +<meta property="og:description" content="Макросы используются и для превращеня исходного кода NewLang в более привычный синтаксис на основе ключевых слов, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода. +Макросы в NewLang, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем). +Макросы обработываются во время работы лексера, т.е. перед передачей последовательности лексем в парсер, что позволяет с помощью маросов изменять фрагменты синтаксиса языка, например, при реализации собственных диалектов DSL." /> <meta property="og:type" content="article" /> <meta property="og:url" content="http://localhost:1313/ru/docs/syntax/macros/" /><meta property="article:section" content="docs" /> -<meta property="article:modified_time" content="2024-03-22T23:57:08+03:00" /><meta property="og:site_name" content="NewLang" /> +<meta property="article:modified_time" content="2024-03-23T22:03:23+03:00" /><meta property="og:site_name" content="NewLang" /> <meta itemprop="name" content="Макросы"> -<meta itemprop="description" content="Макросы в NewLang, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем). -Макросы обработываются во время работы лексера, т.е. перед передачей последовательности лексем в парсер, что позволяет с помощью маросов изменять фрагменты синтаксиса языка, например, при реализации собственных диалектов DSL. -Определение макросов Определение макросов аналогично определению других объектов и состоит из трех частей &lt;имя макроса&gt; &lt;оператор создания/присвоения&gt; &lt;тело макроса&gt; и завершающая точка с запятой &ldquo;;&rdquo;, т."> -<meta itemprop="dateModified" content="2024-03-22T23:57:08+03:00" /> -<meta itemprop="wordCount" content="3012"> +<meta itemprop="description" content="Макросы используются и для превращеня исходного кода NewLang в более привычный синтаксис на основе ключевых слов, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода. +Макросы в NewLang, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем). +Макросы обработываются во время работы лексера, т.е. перед передачей последовательности лексем в парсер, что позволяет с помощью маросов изменять фрагменты синтаксиса языка, например, при реализации собственных диалектов DSL."> +<meta itemprop="dateModified" content="2024-03-23T22:03:23+03:00" /> +<meta itemprop="wordCount" content="1456"> <meta itemprop="keywords" content="" /><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Макросы"/> -<meta name="twitter:description" content="Макросы в NewLang, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем). -Макросы обработываются во время работы лексера, т.е. перед передачей последовательности лексем в парсер, что позволяет с помощью маросов изменять фрагменты синтаксиса языка, например, при реализации собственных диалектов DSL. -Определение макросов Определение макросов аналогично определению других объектов и состоит из трех частей &lt;имя макроса&gt; &lt;оператор создания/присвоения&gt; &lt;тело макроса&gt; и завершающая точка с запятой &ldquo;;&rdquo;, т."/> +<meta name="twitter:description" content="Макросы используются и для превращеня исходного кода NewLang в более привычный синтаксис на основе ключевых слов, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода. +Макросы в NewLang, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем). +Макросы обработываются во время работы лексера, т.е. перед передачей последовательности лексем в парсер, что позволяет с помощью маросов изменять фрагменты синтаксиса языка, например, при реализации собственных диалектов DSL."/> @@ -240,22 +240,6 @@ </ul> </li> </ul> - - <ul> - <li> - <ul> - <li><a href="#примеры-использования-макросов">Примеры использования макросов</a></li> - </ul> - </li> - </ul> - - <ul> - <li><a href="#идеи-на-будущее">Идеи на будущее</a> - <ul> - <li><a href="#символьное-программирование">Символьное программирование</a></li> - </ul> - </li> - </ul> </nav> </div> @@ -295,7 +279,8 @@ <h1>Макросы</h1> <header class="article-meta"> </header> - <p>Макросы в <strong>NewLang</strong>, это один или несколько последовательных терминов, которые заменяются на другой термин + <p>Макросы используются и для превращеня исходного кода <em>NewLang</em> в более привычный синтаксис на основе <a href="https://newlang.net/syntax_dsl.html">ключевых слов</a>, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода.</p> +<p>Макросы в <strong>NewLang</strong>, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем).</p> <p>Макросы обработываются во время работы <strong>лексера</strong>, т.е. перед передачей последовательности лексем в парсер, что позволяет с помощью маросов изменять фрагменты синтаксиса языка, например, при реализации собственных диалектов DSL.</p> @@ -330,13 +315,13 @@ <h3 id="определение-макросов">Определение макр с одинаковыми именами, один из которых будет с аргументами (скобками), а другой без них.</p> <p>Поэтому, если требуется использовать макрос в двух разных вариантах (с аргументами и без оных), следует определять макрос без аргументов и в этом случае контроль параметров будет выполнятся компилятором.</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> @@macro@@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Макрос без аргументов</span> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> @@ macro @@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Макрос без аргументов</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> macro<span style="color:#ce5c00;font-weight:bold">(</span>args<span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># ОК -&gt; term(args);</span> </span></span><span style="display:flex;"><span> macro<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># ОК -&gt; term;</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Но </span> -</span></span><span style="display:flex;"><span> @@call<span style="color:#ce5c00;font-weight:bold">()</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> @@ call<span style="color:#ce5c00;font-weight:bold">()</span> @@ :<span style="color:#ce5c00;font-weight:bold">=</span> term<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> call<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># ОК -&gt; term();</span> </span></span><span style="display:flex;"><span> call<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Ошибка (@call определен с аргументами) </span> @@ -349,286 +334,49 @@ <h3 id="определение-макросов">Определение макр <p>По аналогии с препроцессором С/С++, для соединения двух лексем в одну, в теле макроса используется оператор <strong>&quot;@##&quot;</strong>, а для преобразование лексемы в текстову строку применяется операторы <strong>@#</strong>, <strong>@#&quot;</strong> или <strong>@#&rsquo;</strong>, например, <code>@@macro($arg)@@ := @@ func_ @## @$arg( @#&quot; arg ) @;</code>, тогда вызов <code>macro(name);</code> будет преобразован в <code>func_name (&quot;name&quot;);</code></p> - - -<div class="pageinfo pageinfo-primary"> -<h4 id="ограничения-макропроцессора-в-текущей-версии">Ограничения макропроцессора в текущей версии<a class="td-heading-self-link" href="#%d0%be%d0%b3%d1%80%d0%b0%d0%bd%d0%b8%d1%87%d0%b5%d0%bd%d0%b8%d1%8f-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d0%bf%d1%80%d0%be%d1%86%d0%b5%d1%81%d1%81%d0%be%d1%80%d0%b0-%d0%b2-%d1%82%d0%b5%d0%ba%d1%83%d1%89%d0%b5%d0%b9-%d0%b2%d0%b5%d1%80%d1%81%d0%b8%d0%b8" aria-label="Heading self-link"></a></h4> -<p>На текущий момент макросы реализованы в минимальном объеме для самых простых сценариев использования:</p> -<ul> -<li>DSL для keyword based syntax (if, else, return, match, while и т.д.) - (1 термин с произвольными аргументами и без) - требуется сейчас !!!</li> -</ul> -<p><em>Парсер при обработке макросов может анализировать информацию о типах данных, если она указана.</em> -<em>Но на текущий момент типы данных в макросах никак не обрабатываются и это одна из обязательных фич, которая будет реализована в будущем.</em></p> -<ul> -<li>Определения (func, class) - (несколько терминов с аргументами и без аргументов) - Реализация ООП и импорт С++ классов</li> -<li>Модификации при определениях (override) - (несколько терминов и шаблоны с аргументами и без аргументов) - Реализация ООП и импорт С++ классов</li> -</ul> - -</div> - -<h1 id="макросы-без-аргументов-или-все-аргументы-сразу-">МАКРОСЫ БЕЗ АРГУМЕНТОВ ИЛИ ВСЕ АРГУМЕНТЫ СРАЗУ !!!!!<a class="td-heading-self-link" href="#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b1%d0%b5%d0%b7-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d0%b8%d0%bb%d0%b8-%d0%b2%d1%81%d0%b5-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d1%8b-%d1%81%d1%80%d0%b0%d0%b7%d1%83-" aria-label="Heading self-link"></a></h1> -<h1 id="анализа-аргументов-или-их-типов-не-производится-">анализа аргументов или их типов не производится !!!<a class="td-heading-self-link" href="#%d0%b0%d0%bd%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0-%d0%b0%d1%80%d0%b3%d1%83%d0%bc%d0%b5%d0%bd%d1%82%d0%be%d0%b2-%d0%b8%d0%bb%d0%b8-%d0%b8%d1%85-%d1%82%d0%b8%d0%bf%d0%be%d0%b2-%d0%bd%d0%b5-%d0%bf%d1%80%d0%be%d0%b8%d0%b7%d0%b2%d0%be%d0%b4%d0%b8%d1%82%d1%81%d1%8f-" aria-label="Heading self-link"></a></h1> -<p>Lambda -@@ lambda $name(&hellip;) @@ ::= @@ @$name( @$&hellip; ) ::= ( _( @$&hellip; ) ::= @<strong>PRAGMA_FINALIZE</strong>( @), {, {+, {-, {* ) @@</p> -<h3 id="примеры-использования-макросов">Примеры использования макросов<a class="td-heading-self-link" href="#%d0%bf%d1%80%d0%b8%d0%bc%d0%b5%d1%80%d1%8b-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d1%8f-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2" aria-label="Heading self-link"></a></h3> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Обычные макросы (тело макроса корректное выражение)</span> -</span></span><span style="display:flex;"><span> @@macro@@ :<span style="color:#ce5c00;font-weight:bold">=</span> replace<span style="color:#ce5c00;font-weight:bold">()</span><span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@macro2<span style="color:#ce5c00;font-weight:bold">(</span>arg<span style="color:#ce5c00;font-weight:bold">)</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#ce5c00;font-weight:bold">{</span> call<span style="color:#ce5c00;font-weight:bold">(</span>@<span style="color:#000">$arg</span><span style="color:#ce5c00;font-weight:bold">)</span><span style="color:#000;font-weight:bold">;</span> call<span style="color:#ce5c00;font-weight:bold">()}</span><span style="color:#000;font-weight:bold">;</span> +<p>Примеры использования макросов:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Обычные макросы (тело макроса корректное выражение)</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000">macro</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000">replace</span><span style="color:#000;font-weight:bold">();</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000">macro2</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">arg</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000;font-weight:bold">{</span> <span style="color:#000">call</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#a40000">$</span><span style="color:#000">arg</span><span style="color:#000;font-weight:bold">);</span> <span style="color:#000">call</span><span style="color:#000;font-weight:bold">()};</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Тело макросов из последовательности лексем</span> -</span></span><span style="display:flex;"><span> @@if<span style="color:#ce5c00;font-weight:bold">(</span>...<span style="color:#ce5c00;font-weight:bold">)</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ <span style="color:#ce5c00;font-weight:bold">[</span> <span style="color:#4e9a06">\$</span><span style="color:#204a87;font-weight:bold">if</span><span style="color:#ce5c00;font-weight:bold">(</span>*<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">]</span>--&gt; @@<span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Выражение может быть не полным</span> -</span></span><span style="display:flex;"><span> @@elif<span style="color:#ce5c00;font-weight:bold">(</span>...<span style="color:#ce5c00;font-weight:bold">)</span>@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ ,<span style="color:#ce5c00;font-weight:bold">[</span> <span style="color:#4e9a06">\$</span><span style="color:#204a87;font-weight:bold">elif</span><span style="color:#ce5c00;font-weight:bold">(</span>*<span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">]</span>--&gt; @@<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@else@@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ ,<span style="color:#ce5c00;font-weight:bold">[</span>_<span style="color:#ce5c00;font-weight:bold">]</span>--&gt; @@<span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#204a87;font-weight:bold">if</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000;font-weight:bold">[</span> <span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#a40000">$</span><span style="color:#ce5c00;font-weight:bold">...</span> <span style="color:#000;font-weight:bold">]</span><span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#ce5c00;font-weight:bold">@@</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#8f5902;font-style:italic"># Выражение может быть не полным</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#204a87;font-weight:bold">elif</span><span style="color:#000;font-weight:bold">(</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000;font-weight:bold">,[</span> <span style="color:#ce5c00;font-weight:bold">@</span><span style="color:#a40000">$</span><span style="color:#ce5c00;font-weight:bold">...</span> <span style="color:#000;font-weight:bold">]</span><span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#ce5c00;font-weight:bold">@@</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">@@</span> <span style="color:#000;font-weight:bold">,[</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">]</span><span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#ce5c00;font-weight:bold">@@</span><span style="color:#000;font-weight:bold">;</span> </span></span><span style="display:flex;"><span> </span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># Запись условного оператора с использованием </span> </span></span><span style="display:flex;"><span> <span style="color:#8f5902;font-style:italic"># определенных выше макросов</span> -</span></span><span style="display:flex;"><span> <span style="color:#204a87;font-weight:bold">if</span><span style="color:#ce5c00;font-weight:bold">(</span> condition <span style="color:#ce5c00;font-weight:bold">){</span> -</span></span><span style="display:flex;"><span> ... -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">elif</span><span style="color:#ce5c00;font-weight:bold">(</span> condition2 <span style="color:#ce5c00;font-weight:bold">)</span> <span style="color:#ce5c00;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> ... -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span> <span style="color:#204a87;font-weight:bold">else</span> <span style="color:#ce5c00;font-weight:bold">{</span> -</span></span><span style="display:flex;"><span> ... -</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">}</span><span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>Зачем нужна трансформация синтаксиса? -Нативная поддержка других языков нужна чтобы не переписывать легаси код на этих языках.</p> -<p>Чтобы можно было использовать существующие исходники как собственные требуется настройка работы -препроцессора и лексера под конкретный язык программирования (описание DSL). -Для <strong>С/С++</strong> потребуется выделять лексером комментарии из-за пересечения синтаксиса (которые сейчас игнорируются). -Для <strong>Python</strong> требуется выделять лексером отступы (которые сейчас тоже игнорируются), причем потребуется реализация не только синтаксиса, -но и зависимых пакетов с последующая трансляцией этого кода в С++, что в настоящий момент делать не целесообразно (cython ???).</p> -<p>Но так как возможность трансформации кода с других языков программирования принципиальная возможна, -стоит над этим думать только после полноценного релиза NewLang и его перехода в прод.</p> -<p>Для реализации DSL требуется передача команд в парсер для управления его работой (по аналогии с командой #pragma) -Но так как обработка таких команд должна происходить в лексере до передачи данных в парсер (анализатор), -то команды для макропроцессора должны быть в максимально простом виде и состоять из элементов, -которые лексер может самостоятельно идентифицировать, т.е. термины, строки и цифры (без выражений и именованных аргументов).</p> -<p>После обработки такой команды она анализируется макропроцессором и удаляется из потока лексем, т.е. в парсер (анализатор) не передается. -Но в случае ошибки с синтаксисе, данные команды нужно уметь однозначно идентифировать и самый простой способ, -комбинация признака макроса и системного имени, т.е. что-то вроде</p> -<pre tabindex="0"><code> @__PRAGMA_DIAG__(push) - @__PRAGMA_DIAG__(ignored, &#34;-Wundef&#34;) - @__PRAGMA_DIAG__(warning, &#34;-Wformat&#34;) - @__PRAGMA_DIAG__(error &#34;-Wuninitialized&#34;) - @__PRAGMA_DIAG__(pop) - - #pragma message &#34;Compiling &#34; __FILE__ &#34;...&#34; - @__PRAGMA_MESSAGE__(&#34;Compiling &#34;, __FILE__, &#34;...&#34;) - - #pragma error &#34;Error &#34; __FILE__ &#34;...&#34; - @__PRAGMA_ERROR__(&#34;Error &#34;, __FILE__, &#34;...&#34;) - - -#define DO_PRAGMA(x) _Pragma (#x) -#define TODO(x) DO_PRAGMA(message (&#34;TODO - &#34; #x)) - -@@TODO( ... )@@ := @__PRAGMA_MESSAGE__(&#34;TODO - &#34;, @*) - -@TODO(Remember to fix this) # note: TODO - Remember to fix this - -\\.__lexer__ignore_space__ = 1; -\\.__lexer__ignore_indent__ = 1; -\\.__lexer__ignore_comment__ = 1; -\\.__lexer__ignore_crlf__ = 1; -</code></pre><p>Таким образом можно трансформировать условный оператор на питоне в синтаксис NewLang следующим макросом:</p> -<pre tabindex="0"><code> -#pragma clang attribute push -#pragma clang diagnostic ignored &#34;-Wundef&#34; -#pragma clang diagnostic ignored &#34;-Wunused-variable&#34; - - -#elif __GNUC__ - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored &#34;-Wuninitialized&#34; - -#pragma GCC diagnostic ignored &#34;-Wall&#34; -#pragma GCC diagnostic ignored &#34;-Wextra&#34; - - @pragma warning(pop) +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@if</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">condition</span> <span style="color:#000;font-weight:bold">){</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">...</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> <span style="color:#5c35cc;font-weight:bold">@elif</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">condition2</span> <span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">...</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">}</span> <span style="color:#5c35cc;font-weight:bold">@else</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">...</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span></code></pre></div><p>Например цикл до 5:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">[</span> <span style="color:#0000cf;font-weight:bold">1</span> <span style="color:#000;font-weight:bold">]</span> <span style="color:#ce5c00;font-weight:bold">&lt;-&gt;</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">[</span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#0000cf;font-weight:bold">5</span> <span style="color:#000;font-weight:bold">]</span> <span style="color:#ce5c00;font-weight:bold">--&gt;</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#ce5c00;font-weight:bold">--</span> <span style="color:#0000cf;font-weight:bold">42</span> <span style="color:#ce5c00;font-weight:bold">--</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span><span style="display:flex;"><span> <span style="color:#000">count</span><span style="color:#ce5c00;font-weight:bold">+=</span><span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span></code></pre></div><p>Будет выглядеть более привычно:</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@while</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">true</span> <span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@if</span><span style="color:#000;font-weight:bold">(</span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">&gt;</span> <span style="color:#0000cf;font-weight:bold">5</span> <span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">{</span> +</span></span><span style="display:flex;"><span> <span style="color:#5c35cc;font-weight:bold">@return</span> <span style="color:#0000cf;font-weight:bold">42</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span><span style="display:flex;"><span> <span style="color:#000">count</span> <span style="color:#ce5c00;font-weight:bold">+=</span> <span style="color:#0000cf;font-weight:bold">1</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> <span style="color:#000;font-weight:bold">};</span> +</span></span></code></pre></div> - @@ pragma warning(...) @@ := __PRAGMA_TERM_DIAG_WARNING__(); -@__PRAGMA_DIAG__(warning, pop); +<div class="pageinfo pageinfo-primary"> +<h3 id="далее-идеи-на-будущее">Далее идеи на будущее<a class="td-heading-self-link" href="#%d0%b4%d0%b0%d0%bb%d0%b5%d0%b5-%d0%b8%d0%b4%d0%b5%d0%b8-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5" aria-label="Heading self-link"></a></h3> +<h3 id="символьное-программирование">Символьное программирование<a class="td-heading-self-link" href="#%d1%81%d0%b8%d0%bc%d0%b2%d0%be%d0%bb%d1%8c%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> -Обработка терминов в макропроцессоре в максимально простом виде. -Агрументы только термины, строки и цифры без вложенных выражений и именованных аргументов, -т.е. только элементы, которые может самостоятельно идентифицировать лексер. +</div> -@warning(&#34;--&#34;) - @@ if ... : @@ := @@ [ @$* ]-&gt; __TERM_BLOCK_INDENT__(&#34;{&#34;, force_semicolon=1) @@ - - if __name__ == &#34;__main__&#34;: - run1() - run2() - - [ __name__ == &#34;__main__&#34; ]-&gt; { - run1(); - run2(); - }; - - -</code></pre><p>Ключ &ndash;parser-syntax-only только текстовый парсинг исходного кода без загрузки модулей, раскрытия макросов и проверки имен.</p> -<p>Ключ &ndash;parser-no-macros - без раскрытия макросов -Ключ &ndash;parser-no-module - без загрузки модулей (и мокросов, если они в них определяются) -Ключ &ndash;parser-no-check-prototype - без проверки имен при обращении</p> -<p>prototype -@<strong>PRAGMA_PROTOTYPE</strong>(define) -@<strong>PRAGMA_PROTOTYPE</strong>(implement)</p> -<p>$$</p> -<p>\$ - корень системы (система)</p> -<p>$ - текущий модуль</p> -<h1 id="макросы-для-конвертора-проверки-в-python">Макросы для конвертора проверки в Python<a class="td-heading-self-link" href="#%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d1%8b-%d0%b4%d0%bb%d1%8f-%d0%ba%d0%be%d0%bd%d0%b2%d0%b5%d1%80%d1%82%d0%be%d1%80%d0%b0-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b8-%d0%b2-python" aria-label="Heading self-link"></a></h1> -<h1 id="if-__name__--__main__">if <strong>name</strong> == &ldquo;<strong>main</strong>&rdquo;:<a class="td-heading-self-link" href="#if-__name__--__main__" aria-label="Heading self-link"></a></h1> -<p>@@ <strong>name</strong> @@ ::= @@ $. @<strong>PRAGMA_NO_MACRO</strong>() <strong>name</strong> @@ -@@ if $&hellip; @: @@ ::= @@ [ @$&hellip; ] &ndash;&gt; @@</p> -<p>@if( $.<strong>name</strong> == &ldquo;<strong>main</strong>&rdquo; ) {</p> -<p>}</p> -<p>\каталог\модуль() - статический импорт модуля -\(&ldquo;каталог\модуль&rdquo;)() - динамический импорт модуля</p> -<p>printf := :Pointer(&lsquo;printf(format:FmtChar, &hellip;):Int32&rsquo;); -printf := %printf(format:FmtChar, &hellip;):Int32;</p> -<h1 id="регистрация-прототипа-нативной-функции">Регистрация прототипа нативной функции<a class="td-heading-self-link" href="#%d1%80%d0%b5%d0%b3%d0%b8%d1%81%d1%82%d1%80%d0%b0%d1%86%d0%b8%d1%8f-%d0%bf%d1%80%d0%be%d1%82%d0%be%d1%82%d0%b8%d0%bf%d0%b0-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8" aria-label="Heading self-link"></a></h1> -<p>@prototype -%puts(format:StrChar):Int32;</p> -<h1 id="импорт-нативной-функции-с-предварительной-проверкой-её-наличия-во-время-компиляции-статическая-линковка">Импорт нативной функции с предварительной проверкой её наличия во время компиляции (статическая линковка)<a class="td-heading-self-link" href="#%d0%b8%d0%bc%d0%bf%d0%be%d1%80%d1%82-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d1%81-%d0%bf%d1%80%d0%b5%d0%b4%d0%b2%d0%b0%d1%80%d0%b8%d1%82%d0%b5%d0%bb%d1%8c%d0%bd%d0%be%d0%b9-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%be%d0%b9-%d0%b5%d1%91-%d0%bd%d0%b0%d0%bb%d0%b8%d1%87%d0%b8%d1%8f-%d0%b2%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d1%8f-%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%86%d0%b8%d0%b8-%d1%81%d1%82%d0%b0%d1%82%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bb%d0%b8%d0%bd%d0%ba%d0%be%d0%b2%d0%ba%d0%b0" aria-label="Heading self-link"></a></h1> -<p>puts2(format:StrChar):Int32 := %puts(format:StrChar):Int32;</p> -<h1 id="импорт-нативной-функции-по-её-прототипу-во-время-выполнения-динамическая-линковка">Импорт нативной функции по её прототипу во время выполнения (динамическая линковка)<a class="td-heading-self-link" href="#%d0%b8%d0%bc%d0%bf%d0%be%d1%80%d1%82-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d0%be%d0%b9-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%b8-%d0%bf%d0%be-%d0%b5%d1%91-%d0%bf%d1%80%d0%be%d1%82%d0%be%d1%82%d0%b8%d0%bf%d1%83-%d0%b2%d0%be-%d0%b2%d1%80%d0%b5%d0%bc%d1%8f-%d0%b2%d1%8b%d0%bf%d0%be%d0%bb%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b4%d0%b8%d0%bd%d0%b0%d0%bc%d0%b8%d1%87%d0%b5%d1%81%d0%ba%d0%b0%d1%8f-%d0%bb%d0%b8%d0%bd%d0%ba%d0%be%d0%b2%d0%ba%d0%b0" aria-label="Heading self-link"></a></h1> -<p>puts3(format:StrChar):Int32 := :Pointer(&lsquo;puts(format:StrChar):Int32&rsquo;);</p> -<p>%puts(&lsquo;Тест вывода строки&rsquo;); # Линковка с нативной функцией во время компиляции и непосредственный вызов с оптимизацией передачи параметров -puts2(&lsquo;Тест 2 вывода строки&rsquo;); # Линковка с нативной функцией во время компиляции -puts3(&lsquo;Тест 3 вывода строки&rsquo;); # Линковка с нативной функцией во время выполнения при первом вызове puts3</p> -<ul> -<li>Парсинг исходного текста без раскрытия макросов и загрузки модулей</li> -<li>Парсинг исходного текста с раскрытием макросов (требуется загрузка модулей для зависимых и переопределяемых макросов)</li> -<li>Загружатся модули могут как в виде исходников (которые требуется парсить и компилировть/выполнять) -или в виде бинарников (в них должны быть список макросов, типов и имена объектов)</li> -<li>После парсинга получается список <strong>имен</strong> макросов, типов и объектов (TermPtr)</li> -<li>После выполнения модуля - список <strong>имен</strong> заполняется реальными объектами (ObjPtr).</li> -</ul> -<h1 id="компиляция-файла">Компиляция файла<a class="td-heading-self-link" href="#%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%86%d0%b8%d1%8f-%d1%84%d0%b0%d0%b9%d0%bb%d0%b0" aria-label="Heading self-link"></a></h1> -<ul> -<li>Парсинг исходника для построения AST (без анализа имен, связей, загрузки модулей и пр. только исходые тексты с раскрытием макросов</li> -<li></li> -</ul> -<h1 id="систематизация-реализации-макросов">Систематизация реализации макросов<a class="td-heading-self-link" href="#%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%b0%d1%82%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d1%80%d0%b5%d0%b0%d0%bb%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d0%b8-%d0%bc%d0%b0%d0%ba%d1%80%d0%be%d1%81%d0%be%d0%b2" aria-label="Heading self-link"></a></h1> -<p>последовательность лексем MACRO_SEQ мужду @@ @@ сохраняется в m_block, так как фрагменты блоков не могут быть идентификаторами</p> -<p>Разбор макросов происходит в лексере. Определением макроса всегда является целая строка, -которая заканчивается точкой с запятой, а идентификатором макроса всегда выступает последовательность лексем:</p> -<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span> @@ id @@ :<span style="color:#ce5c00;font-weight:bold">=</span> macro<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@ id @@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@ @@<span style="color:#000;font-weight:bold">;</span> -</span></span><span style="display:flex;"><span> @@ id @@ :<span style="color:#ce5c00;font-weight:bold">=</span> @@@ @@@<span style="color:#000;font-weight:bold">;</span> -</span></span></code></pre></div><p>Хранилищем текущих максросов является объект класса MacroBuffer. -Последовательность лексем идентификатора (id) макроса должна сохраняется в отдельном поле термина и однозначно его идентифицирует. -Первый термин в идентификаторе хранится как ключ hashmap, а дальше происходит поиск полным перебором. -Этапы работы с макросами</p> -<ul> -<li> -<p>Входные термины из лексера получаются вызовом GetNextToken, внутри которой и происходит раскрытие макросов. -Внутренний буфер заполняется до окончания строки (выражения), т.е. до символа &lsquo;;&rsquo; или <END>, после чего производится -поиск макросов в объекте MacroBuffer для текущей последовательности лексем в буфере.</p> -</li> -<li> -<p>Если макрос найден, то соответствющая ему последоваетльность заменяется на тело макроса и происходит переход -на повторный анализ входного буфера.</p> -</li> -<li> -<p>Если макрос не найден, то данные передаются в парсер для дальнейшего синтаксическго анализа.</p> -</li> -<li> -<p>Для этого во входном потоке лексем (parser.y) во время оператората создания/присвоения вызывается функция проверки на макрос. -MacroBuffer::CheckMacroAndConvertDel($$), и после этого выходному значению присваивается результат выполнения driver.MacroEval($$), -и в дальнейшем этот макрос никак не обработывается.</p> -</li> -<li> -<p>Создание макросов, проверка на дубликаты и логические ошибки в определении происходит путем обращения к методам объекта MacroBuffer.</p> -<p>/*</p> -<ul> -<li>Макросы хрянтся как фрагменты AST в виде объектов типа Term,</li> -<li>так как создаются после обработки парсером по правилам стандратной грамматики.</li> -<li></li> -<li>Но анализ входных данных на предмет раскрытия макросов проиходит из потока (последовательности) лексем,</li> -<li>т.е. <strong>ДО</strong> обработки парсером, так как при раскрытии макросов может меняться грамматика выражений.</li> -<li></li> -<li>Функция \ref CompareMacro сравнивает входной буфер (последовательность лексем)</li> -<li>на предмет возможного соответствия одному конкретному макросу.</li> -<li>Сравниваются только ключевые словам без учета аргументов в скобках,</li> -<li>но само наличие аргументов проверяется ??????????????????</li> -<li></li> -<li>Проблема:</li> -<li>К функции можно обратится с целью её вызова (указав после имени скобки),</li> -<li>так и по имени без скобок (например для получения ссылки на объект).</li> -<li>Так и к переменной можно обратиться только по имени,</li> -<li>так и указав скобки после имени как к функции (при копировании объекта).</li> -<li></li> -<li>Сделать один макрос под оба сценария (со скобками и без скобок) не получится, так как непонятно,</li> -<li>что делать с аргументами при раскрытии тела макроса, когда они не указаны.</li> -<li></li> -<li>Но может быть следует переименовывать только одно имя без учета скобок,</li> -<li>например, оставив такую возможность только для одиночных макросов.</li> -<li></li> -<li>\name -&gt; name или name (&hellip;), hash: name</li> -<li>но \name(&hellip;) -&gt; name(&hellip;), а name - ошибка !!!! hash: name</li> -<li></li> -<li>Или все же следует различать макросы со скобками и без скобок как два разных объекта???</li> -<li>\name := name2; и \name(&hellip;) := name2(&hellip;); будут разными объектами</li> -<li></li> -<li>Или добавить макросы-алиасы без аргументов только для переименования отдельных терминов?</li> -<li>\alias :- name2; но как их отличать от обычных макросов в операции удаления?</li> -<li>Или вообще не нужно отличать и оставить только один варинат (либо макрос, либо алиас)</li> -<li>Тода вопрос со скобками закрывается сам собой, алиасы всегда без скобок,</li> -<li>макросы со скбками или без скобок, но должно быть полное соответствие.</li> -<li></li> -<li>@ name name2 @ -&gt; name name2, но name name2(&hellip;) - ошибка!!! (hash: name,name2)</li> -<li>@ name name2(&hellip;) @ -&gt; name name2(&hellip;), но name name2 - ошибка !!!! (hash: name,name2)</li> -<li>@ name name2<a href="...">&hellip;</a> @ -&gt; name name2<a href="...">&hellip;</a>, но name name2 - ошибка !!!! ( hash: name,name2 )</li> -<li>@ name $tmpl<a href="...">&hellip;</a> name3@ -&gt; name $tmpl<a href="...">&hellip;</a> name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )</li> -<li></li> -<li>Но!</li> -<li>@ name name2 @ ::- -&gt; name name2 - ок, но name name2(&hellip;) - ок</li> -<li>@ name $tmpl name3@ ::- -&gt; name $tmpl<a href="...">&hellip;</a> name3 - ок, name $tmpl(&hellip;) name3[&hellip;] - ок</li> -<li></li> -<li></li> -<li></li> -<li>Для последовательности лексем требуется полное соответствие с учетом скобок ???</li> -<li>и может ли быть несколько скобок одного типа (несколько крыглях, или несколько квардратных????</li> -<li>&lt;Может быть несколько скобок одного типа, например, при указании типа у аргументов или типа возвращаемого значения.&gt;</li> -<li></li> -<li>@ name name2 @ -&gt; name name2, но name name2(&hellip;) - ошибка!!! (hash: name,name2)</li> -<li>@ name name2(&hellip;) @ -&gt; name name2(&hellip;), но name name2 - ошибка !!!! (hash: name,name2)</li> -<li>@ name name2<a href="...">&hellip;</a> @ -&gt; name name2<a href="...">&hellip;</a>, но name name2 - ошибка !!!! ( hash: name,name2 )</li> -<li>@ name $tmpl<a href="...">&hellip;</a> name3@ -&gt; name $tmpl<a href="...">&hellip;</a> name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 )</li> -<li></li> -<li>Проблема скобок возникает из-за сценария замены одного термина на другой,</li> -<li>который есть в препроцессоре С/С++, но отсутствует при реализации с использованием шаблонов.</li> -<li></li> -<li></li> -</ul> -<p>*/</p> -</li> -</ul> -<p>Макросы используются и для превращеня исходного кода <em>NewLang</em> в более привычный синтаксис на основе <a href="https://newlang.net/syntax_dsl.html">ключевых слов</a>, так как такой тест гораздо легче воспринимается при последующем чтении исходного кода.</p> -<p><a href="https://newlang.net/syntax_dsl.html">Например:</a>.</p> -<pre tabindex="0"><code> @@if(...)@@ ::= @@ [ \$* ]--&gt; @@; - @@while(...)@@ ::= @@ [\$*] &lt;-&gt; @@; - @@return $arg@@::= @@ -- \$arg -- @@; - @@true@@ ::= 1; -</code></pre><p>Тогда цикл до 5:</p> -<pre tabindex="0"><code>count:=1; -[ 1 ] &lt;-&gt; { - [count&gt;5] --&gt; { - -- 42 --; - }; - count+=1; -}; -</code></pre><p>будет выглядеть более привычно</p> -<pre tabindex="0"><code>count:=1; -while( true ) { - if(count&gt;5) { - return 42; - }; - count+=1; -}; -</code></pre><h2 id="идеи-на-будущее">Идеи на будущее<a class="td-heading-self-link" href="#%d0%b8%d0%b4%d0%b5%d0%b8-%d0%bd%d0%b0-%d0%b1%d1%83%d0%b4%d1%83%d1%89%d0%b5%d0%b5" aria-label="Heading self-link"></a></h2> -<h3 id="символьное-программирование">Символьное программирование<a class="td-heading-self-link" href="#%d1%81%d0%b8%d0%bc%d0%b2%d0%be%d0%bb%d1%8c%d0%bd%d0%be%d0%b5-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5" aria-label="Heading self-link"></a></h3> <blockquote> <p>Символьное программирование, часто называемое декларативным программированием, представляет собой парадигму программирования, которая использует математическую логику, отношения и символы для представления знаний и помощи в решении проблем. Вместо того, чтобы сосредотачиваться на описании последовательности операций, необходимых для выполнения вычислений, как в императивном программировании, символическое программирование делает упор на выражении отношений и ограничений между структурами данных, уделяя особое внимание «что», а не «как».</p> <p>В контексте парадигм программирования символическое программирование часто противопоставляется процедурному или императивному программированию, где программы определяют пошаговые процедуры для достижения своих целей. В то время как императивное программирование фокусируется на описании потока управления с использованием таких конструкций, как циклы и условные выражения, для управления выполнением, символическое программирование сосредоточено на выражении фактов о проблеме и позволяет выполнению естественным образом выводить последующие последствия из предоставленной информации.</p> diff --git a/docs/ru/docs/types/_print/index.html b/docs/ru/docs/types/_print/index.html index 9c1b220f..6aa11111 100644 --- a/docs/ru/docs/types/_print/index.html +++ b/docs/ru/docs/types/_print/index.html @@ -946,11 +946,34 @@ <h3 id="еще-пример-возможностей-для-расширения <h1 id="pg-cf08b42ee4f3746e6fd20919aa6660c8">9 - Нативные типы</h1> <h2 id="нативные-типы-данных">Нативные типы данных<a class="td-heading-self-link" href="#%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85" aria-label="Heading self-link"></a></h2> -<p>Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &ldquo;<strong>%</strong>&rdquo;. -В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат.</p> +<p>Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &ldquo;<strong>%</strong>&rdquo;.</p> +<p>В случае переменных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определенный формат.</p> +<p>Чтобы использовать уже существующие библиотеки, нужно импортировать нативный объект, +тем самым создав объкт NewLang, но с реализацией на другом языке, например на С/С++.</p> +<p>Синтаксис импорта нативных объектов такой же, как и для <a href="/ru/docs/ops/create/">создания</a> обычных объектов языка, +только в качестве правого операнда в операторе создания требуется указать имя нативнного объекта.</p> +<p>При импорте нативного объекта необходимо всегда указывать типы переменных, а также типы аргументов и возвращаемых значений для функций.</p> +<p>Если типы данных у создаваемого и нативного объекта совпадают (т.е. не требуется преобразование типов), +то нативное имя объекта можно указать с многоточием, которое означает, что типы данных будут повторять заданные у левого операнда.</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#000">Plain</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#000">fopen</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">filename</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">StrChar</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">modes</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">StrChar</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">FILE</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fopen</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">fclose</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">f</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fclose</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">fflush</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">f</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fflush</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">fprintf</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">f</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#204a87">format</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FmtChar</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fprintf</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#000">fremove</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">filename</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">String</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">remove</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">frename</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">old</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">String</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">new</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">String</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">rename</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span></code></pre></div> + +<div class="pageinfo pageinfo-primary"> +<p>Последующее описание находится в процессе разработки.</p> + +</div> + <h3 id="pointer--указатель-на-системную-область-памяти-или-нативную-функцию">:Pointer — указатель на системную область памяти или нативную функцию<a class="td-heading-self-link" href="#pointer--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%83%d1%8e-%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8-%d0%b8%d0%bb%d0%b8-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%83%d1%8e-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8e" aria-label="Heading self-link"></a></h3> -<p>Так как любой программе приходится взаимодействовать с внешним миром, т -о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, +<p>Так как любой программе приходится взаимодействовать с внешним миром, +то по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип <em>:Pointer</em>. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. Но можно вывести его значение, например для отладки.</p> <h3 id="plain--указатель-на-представление-данных-в-бинарном-виде">:Plain — указатель на представление данных в бинарном виде<a class="td-heading-self-link" href="#plain--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d0%bf%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%be%d0%bc-%d0%b2%d0%b8%d0%b4%d0%b5" aria-label="Heading self-link"></a></h3> diff --git a/docs/ru/docs/types/index.xml b/docs/ru/docs/types/index.xml index 2ea3088c..f2661f99 100644 --- a/docs/ru/docs/types/index.xml +++ b/docs/ru/docs/types/index.xml @@ -674,11 +674,34 @@ Number 5 from the thread!&lt;/p&gt; &lt;h2 id=&#34;нативные-типы-данных&#34;&gt;Нативные типы данных&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &amp;ldquo;&lt;strong&gt;%&lt;/strong&gt;&amp;rdquo;. -В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат.&lt;/p&gt; +&lt;p&gt;Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &amp;ldquo;&lt;strong&gt;%&lt;/strong&gt;&amp;rdquo;.&lt;/p&gt; +&lt;p&gt;В случае переменных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определенный формат.&lt;/p&gt; +&lt;p&gt;Чтобы использовать уже существующие библиотеки, нужно импортировать нативный объект, +тем самым создав объкт NewLang, но с реализацией на другом языке, например на С/С++.&lt;/p&gt; +&lt;p&gt;Синтаксис импорта нативных объектов такой же, как и для &lt;a href=&#34;http://localhost:1313/ru/docs/ops/create/&#34;&gt;создания&lt;/a&gt; обычных объектов языка, +только в качестве правого операнда в операторе создания требуется указать имя нативнного объекта.&lt;/p&gt; +&lt;p&gt;При импорте нативного объекта необходимо всегда указывать типы переменных, а также типы аргументов и возвращаемых значений для функций.&lt;/p&gt; +&lt;p&gt;Если типы данных у создаваемого и нативного объекта совпадают (т.е. не требуется преобразование типов), +то нативное имя объекта можно указать с многоточием, которое означает, что типы данных будут повторять заданные у левого операнда.&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Plain&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fopen&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;filename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;StrChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;modes&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;StrChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fopen&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fclose&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fclose&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fflush&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fflush&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fprintf&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#204a87&#34;&gt;format&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FmtChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fprintf&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fremove&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;filename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;remove&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;frename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;old&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;new&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;rename&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; + +&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; +&lt;p&gt;Последующее описание находится в процессе разработки.&lt;/p&gt; + +&lt;/div&gt; + &lt;h3 id=&#34;pointer--указатель-на-системную-область-памяти-или-нативную-функцию&#34;&gt;:Pointer — указатель на системную область памяти или нативную функцию&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#pointer--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%83%d1%8e-%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8-%d0%b8%d0%bb%d0%b8-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%83%d1%8e-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8e&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Так как любой программе приходится взаимодействовать с внешним миром, т -о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, +&lt;p&gt;Так как любой программе приходится взаимодействовать с внешним миром, +то по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип &lt;em&gt;:Pointer&lt;/em&gt;. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. Но можно вывести его значение, например для отладки.&lt;/p&gt; &lt;h3 id=&#34;plain--указатель-на-представление-данных-в-бинарном-виде&#34;&gt;:Plain — указатель на представление данных в бинарном виде&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#plain--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d0%bf%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%be%d0%bc-%d0%b2%d0%b8%d0%b4%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; diff --git a/docs/ru/docs/types/native/index.html b/docs/ru/docs/types/native/index.html index a53d8289..4eea691a 100644 --- a/docs/ru/docs/types/native/index.html +++ b/docs/ru/docs/types/native/index.html @@ -18,23 +18,31 @@ <link rel="icon" type="image/png" href="/favicons/android-192x192.png" sizes="192x192"> <title>Нативные типы | NewLang</title> -<meta name="description" content="Нативные типы данных Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &amp;ldquo;%&amp;rdquo;. В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат. -:Pointer — указатель на системную область памяти или нативную функцию Так как любой программе приходится взаимодействовать с внешним миром, т о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип :Pointer."> +<meta name="description" content="Нативные типы данных Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &amp;ldquo;%&amp;rdquo;. +В случае переменных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определенный формат. +Чтобы использовать уже существующие библиотеки, нужно импортировать нативный объект, тем самым создав объкт NewLang, но с реализацией на другом языке, например на С/С&#43;&#43;. +Синтаксис импорта нативных объектов такой же, как и для создания обычных объектов языка, только в качестве правого операнда в операторе создания требуется указать имя нативнного объекта."> <meta property="og:title" content="Нативные типы" /> -<meta property="og:description" content="Нативные типы данных Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &ldquo;%&rdquo;. В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат. -:Pointer — указатель на системную область памяти или нативную функцию Так как любой программе приходится взаимодействовать с внешним миром, т о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип :Pointer." /> +<meta property="og:description" content="Нативные типы данных Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &ldquo;%&rdquo;. +В случае переменных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определенный формат. +Чтобы использовать уже существующие библиотеки, нужно импортировать нативный объект, тем самым создав объкт NewLang, но с реализацией на другом языке, например на С/С&#43;&#43;. +Синтаксис импорта нативных объектов такой же, как и для создания обычных объектов языка, только в качестве правого операнда в операторе создания требуется указать имя нативнного объекта." /> <meta property="og:type" content="article" /> <meta property="og:url" content="http://localhost:1313/ru/docs/types/native/" /><meta property="article:section" content="docs" /> -<meta property="article:modified_time" content="2024-03-22T23:57:08+03:00" /><meta property="og:site_name" content="NewLang" /> +<meta property="article:modified_time" content="2024-03-23T22:03:23+03:00" /><meta property="og:site_name" content="NewLang" /> <meta itemprop="name" content="Нативные типы"> -<meta itemprop="description" content="Нативные типы данных Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &ldquo;%&rdquo;. В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат. -:Pointer — указатель на системную область памяти или нативную функцию Так как любой программе приходится взаимодействовать с внешним миром, т о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип :Pointer."> -<meta itemprop="dateModified" content="2024-03-22T23:57:08+03:00" /> -<meta itemprop="wordCount" content="214"> +<meta itemprop="description" content="Нативные типы данных Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &ldquo;%&rdquo;. +В случае переменных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определенный формат. +Чтобы использовать уже существующие библиотеки, нужно импортировать нативный объект, тем самым создав объкт NewLang, но с реализацией на другом языке, например на С/С&#43;&#43;. +Синтаксис импорта нативных объектов такой же, как и для создания обычных объектов языка, только в качестве правого операнда в операторе создания требуется указать имя нативнного объекта."> +<meta itemprop="dateModified" content="2024-03-23T22:03:23+03:00" /> +<meta itemprop="wordCount" content="344"> <meta itemprop="keywords" content="типы данных,системые типы,коллекции," /><meta name="twitter:card" content="summary"/><meta name="twitter:title" content="Нативные типы"/> -<meta name="twitter:description" content="Нативные типы данных Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &ldquo;%&rdquo;. В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат. -:Pointer — указатель на системную область памяти или нативную функцию Так как любой программе приходится взаимодействовать с внешним миром, т о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип :Pointer."/> +<meta name="twitter:description" content="Нативные типы данных Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &ldquo;%&rdquo;. +В случае переменных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определенный формат. +Чтобы использовать уже существующие библиотеки, нужно импортировать нативный объект, тем самым создав объкт NewLang, но с реализацией на другом языке, например на С/С&#43;&#43;. +Синтаксис импорта нативных объектов такой же, как и для создания обычных объектов языка, только в качестве правого операнда в операторе создания требуется указать имя нативнного объекта."/> @@ -285,11 +293,34 @@ <h5 class="taxonomy-title">Tags:</h5> </header> <h2 id="нативные-типы-данных">Нативные типы данных<a class="td-heading-self-link" href="#%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85" aria-label="Heading self-link"></a></h2> -<p>Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &ldquo;<strong>%</strong>&rdquo;. -В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат.</p> +<p>Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &ldquo;<strong>%</strong>&rdquo;.</p> +<p>В случае переменных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определенный формат.</p> +<p>Чтобы использовать уже существующие библиотеки, нужно импортировать нативный объект, +тем самым создав объкт NewLang, но с реализацией на другом языке, например на С/С++.</p> +<p>Синтаксис импорта нативных объектов такой же, как и для <a href="/ru/docs/ops/create/">создания</a> обычных объектов языка, +только в качестве правого операнда в операторе создания требуется указать имя нативнного объекта.</p> +<p>При импорте нативного объекта необходимо всегда указывать типы переменных, а также типы аргументов и возвращаемых значений для функций.</p> +<p>Если типы данных у создаваемого и нативного объекта совпадают (т.е. не требуется преобразование типов), +то нативное имя объекта можно указать с многоточием, которое означает, что типы данных будут повторять заданные у левого операнда.</p> +<div class="highlight"><pre tabindex="0" style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#000">Plain</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#000">fopen</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">filename</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">StrChar</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">modes</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">StrChar</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">FILE</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fopen</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">fclose</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">f</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fclose</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">fflush</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">f</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fflush</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">fprintf</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">f</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FILE</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#204a87">format</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">FmtChar</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">fprintf</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span> +</span></span><span style="display:flex;"><span><span style="color:#000">fremove</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">filename</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">String</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">remove</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span><span style="display:flex;"><span><span style="color:#000">frename</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">old</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">String</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">new</span><span style="color:#000;font-weight:bold">:</span><span style="color:#000">String</span><span style="color:#000;font-weight:bold">):</span><span style="color:#000">Int32</span> <span style="color:#000;font-weight:bold">:</span><span style="color:#ce5c00;font-weight:bold">:=</span> <span style="color:#ce5c00;font-weight:bold">%</span><span style="color:#000">rename</span><span style="color:#ce5c00;font-weight:bold">...</span><span style="color:#000;font-weight:bold">;</span> +</span></span></code></pre></div> + +<div class="pageinfo pageinfo-primary"> +<p>Последующее описание находится в процессе разработки.</p> + +</div> + <h3 id="pointer--указатель-на-системную-область-памяти-или-нативную-функцию">:Pointer — указатель на системную область памяти или нативную функцию<a class="td-heading-self-link" href="#pointer--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%83%d1%8e-%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8-%d0%b8%d0%bb%d0%b8-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%83%d1%8e-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8e" aria-label="Heading self-link"></a></h3> -<p>Так как любой программе приходится взаимодействовать с внешним миром, т -о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, +<p>Так как любой программе приходится взаимодействовать с внешним миром, +то по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип <em>:Pointer</em>. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. Но можно вывести его значение, например для отладки.</p> <h3 id="plain--указатель-на-представление-данных-в-бинарном-виде">:Plain — указатель на представление данных в бинарном виде<a class="td-heading-self-link" href="#plain--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d0%bf%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%be%d0%bc-%d0%b2%d0%b8%d0%b4%d0%b5" aria-label="Heading self-link"></a></h3> diff --git a/docs/ru/index.xml b/docs/ru/index.xml index 0afac002..9b818448 100644 --- a/docs/ru/index.xml +++ b/docs/ru/index.xml @@ -14,7 +14,7 @@ <item> - <title>Blog: Релиз языка программрования NewLang 0.4</title> + <title>Blog: Релиз языка программирования NewLang 0.4</title> <link>http://localhost:1313/ru/blog/release-v0.4/</link> <pubDate>Tue, 06 Jun 2023 00:00:00 +0000</pubDate> @@ -22,17 +22,26 @@ <description> - &lt;p&gt;&lt;img alt=&#34;КДПВ&#34; src=&#34;http://localhost:1313/ru/blog/langs.jpeg&#34;&gt;&lt;/p&gt; - - -&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; -&lt;p&gt;Внимание!!!&lt;/p&gt; -&lt;p&gt;&amp;ldquo;nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии.&lt;/p&gt; -&lt;p&gt;Актуальную версию синтаксиса языка можно посмотреть &lt;a href=&#34;http://localhost:1313/ru/docs/&#34;&gt;тут&lt;/a&gt;.&lt;/p&gt; - -&lt;/div&gt; - -&lt;p&gt;ssssssssssssssssssssssssssssssssssssssssssssss&lt;/p&gt; + &lt;h2 id=&#34;новые-возможности-и-изменения-в-синтаксисе-newlang&#34;&gt;Новые возможности и изменения в синтаксисе NewLang&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bd%d0%be%d0%b2%d1%8b%d0%b5-%d0%b2%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b8-%d0%b8%d0%b7%d0%bc%d0%b5%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f-%d0%b2-%d1%81%d0%b8%d0%bd%d1%82%d0%b0%d0%ba%d1%81%d0%b8%d1%81%d0%b5-newlang&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; +&lt;ul&gt; +&lt;li&gt;Переработано определение типов объектов с помощью &lt;a href=&#34;https://newlang.net/docs/syntax/naming/&#34;&gt;префикса имен (сигила)&lt;/a&gt;&lt;/li&gt; +&lt;li&gt;Прерывание потока выполнения и возврат теперь может выполняться для &lt;a href=&#34;https://newlang.net/docs/ops/throw/&#34;&gt;именованных блоков кода&lt;/a&gt;.&lt;/li&gt; +&lt;li&gt;Упрощен синтаксис импорта &lt;a href=&#34;https://newlang.net/docs/types/native/&#34;&gt;нативных переменных и функций (С/С++)&lt;/a&gt;&lt;/li&gt; +&lt;li&gt;Стабилизирован синтаксис для &lt;a href=&#34;https://newlang.net/docs/ops/create/#comprehensions&#34;&gt;заполнение начальными данными&lt;/a&gt; значений тензоров, словарей и аргументов при вызове функций.&lt;/li&gt; +&lt;li&gt;Появились встроенные макросы для написания кода с использованием ключевых слов в стиле &lt;a href=&#34;https://newlang.net/docs/syntax/dsl/&#34;&gt;DSL&lt;/a&gt;&lt;/li&gt; +&lt;/ul&gt; +&lt;h2 id=&#34;новые-возможности-компилятора-nlc&#34;&gt;Новые возможности компилятора (nlc)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bd%d0%be%d0%b2%d1%8b%d0%b5-%d0%b2%d0%be%d0%b7%d0%bc%d0%be%d0%b6%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d1%8f%d1%82%d0%be%d1%80%d0%b0-nlc&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; +&lt;ul&gt; +&lt;li&gt;Полностью переделан макропроцессор.&lt;/li&gt; +&lt;li&gt;Переработана архитектура компилятора с разделением на парсер, макропроцессор, синтаксический анализатор, интерпретатор и генератор кода.&lt;/li&gt; +&lt;/ul&gt; +&lt;h2 id=&#34;разное&#34;&gt;Разное&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%80%d0%b0%d0%b7%d0%bd%d0%be%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; +&lt;ul&gt; +&lt;li&gt;&lt;a href=&#34;http://newlang.net&#34;&gt;Сайт&lt;/a&gt; с документацией переведен на &lt;a href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt; и сделан двуязычным.&lt;/li&gt; +&lt;li&gt;Вместо бинарных сборок на сайт добавлен раздел &lt;a href=&#34;https://newlang.net/playground/&#34;&gt;Playground and example code&lt;/a&gt; для небольших экспериментов.&lt;/li&gt; +&lt;li&gt;Выполнен переход на clang-16 (переход на clang-17 и старше планируется после полной реализации корутин и поддержки расширенных форматов чисел с плавающей запятой).&lt;/li&gt; +&lt;li&gt;Количество контрибуторов проекта стало больше одного!&lt;/li&gt; +&lt;/ul&gt; </description> </item> diff --git a/docs/ru/playground/_print/index.html b/docs/ru/playground/_print/index.html index ead3c8bc..22ca37a5 100644 --- a/docs/ru/playground/_print/index.html +++ b/docs/ru/playground/_print/index.html @@ -91,8 +91,7 @@ </header> <div class="container-fluid td-default td-outer"> <main role="main" class="td-main"> - <p>Примеры программ на NewLang</p> -<style> + <style> .rownr {width: 5%; overflow-y: hidden; background-color: rgb(105,105,105); color: white; text-align: right; vertical-align:top; resize: none;} .txt {width: 90%; overflow-x: scroll; resize: none; font-family: monospace;} @@ -100,6 +99,9 @@ .error {background-color: rgb(255, 180, 180); } .pgbox {margin-top: 4rem;} </style> +<p> +<br> +</p> <div class="pgbox"> <select class="c10" style="width: 95%;" onchange="SelectExample(this);" id="example_list"> <option selected="selected" value="" id="example_start">Select an exmaple...</option> @@ -145,18 +147,6 @@ </div> <script> -if(window.location.search){ - const params = new Proxy(new URLSearchParams(window.location.search), { - get: (searchParams, prop) => searchParams.get(prop), - }); - // Get the value of "src" in eg "https://example.com/?src=source" - if(params.src){ - document.getElementById('playground').value = unescape(params.src); - } - //alert(escape('#!../output/nlc \n\nprint(\'Hello, world!\\n\');\n')); - // %23%21../output/nlc%20%0A%0Aprint%28%27Hello%2C%20world%21%5Cn%27%29%3B%0A -} - locations =[ "", "#!../output/nlc \n\nprint('Hello, world!\\n');\n", "#!../output/nlc \n\nfact := 1\\1; # Rational value support bigint\nmult := @iter(1000..1..-1); # Iterator from range\n@while( @curr(mult) ) {\n fact *= @next(mult);\n};\n\n# Check factorial 1000!\n@assert( fact == 402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\\1 );\n\n# Return result\nfact", @@ -165,14 +155,17 @@ "#!../output/nlc --eval\n\n# Create a tensor and fill it with values. \n# The last value is repeated up to the required tensor size\ntensor := :Single[2,5](-1, 0, 1, 2, 3, ... );\nprint('1: tensor = %s\\n', :StrChar(tensor));\n\nmult := tensor * 10;\nprint('2: tensor *= 10 -> %s\\n', :StrChar(mult));\n\nmult += 11;\nprint('3: tensor += 11 -> %s\\n', :StrChar(mult));\n\n# Import srand function and init random generator\nsrand(seed:Int32):None := %srand ...;\nsrand(100);\n\n# Import rand function to get random values\nrnd():Int32 := %rand ...;\nprint('4: %d, %d, %d, %d\\n', rnd(), rnd(), rnd(), rnd());\n\n# Create a tensor where the rand function is called for every element except the first\nmatrix := :Tensor[10,10]( 0, 42, ... rnd() ...);\nprint('5: matrix = %s\\n', :StrChar(matrix));\n\nmatrix //= 42;\nprint('6: matrix %%= 2 -> %s\\n', :StrChar(matrix));\nprint('7: matrix %%= 2 -> %s\\n', :StrChar(:Bool(matrix)));\n", ]; -function SelectExample(sel){ - - srcLocation = locations[sel.selectedIndex]; - if (srcLocation != undefined && srcLocation != "") { - obj = document.getElementById('playground'); - obj.value = locations[sel.selectedIndex]; - input_changed(obj); - } +function SelectExample(sel){ + obj = document.getElementById('playground'); + if(Number.isInteger(sel) && locations[sel]){ + obj.value = locations[sel]; + } else { + srcLocation = locations[sel.selectedIndex]; + if (srcLocation != undefined && srcLocation != "") { + obj.value = locations[sel.selectedIndex]; + } + } + input_changed(obj); } @@ -327,7 +320,7 @@ clearInterval(downloadTimer); document.getElementById('progress').style.display = "none"; document.getElementById('playground_out').classList.add("error"); - alert("Request failed!"); + alert("Request failed!\n\nCheck the connection protocol!\n\nThe site should open using the regular HTTP protocol without using SSL! Because browsers typically block unsecured connections on HTTPS pages."); }; xhr.ontimeout = (e) => { @@ -336,6 +329,22 @@ alert("Run query timeout!"); }; } + + +if(window.location.search){ + const params = new Proxy(new URLSearchParams(window.location.search), { + get: (searchParams, prop) => searchParams.get(prop), + }); + // Get the value of "src" in eg "https://example.com/?src=source" + if(params.id){ + SelectExample(parseInt(params.id)); + } else if(params.src){ + document.getElementById('playground').value = unescape(params.src); + } + //alert(escape('#!../output/nlc \n\nprint(\'Hello, world!\\n\');\n')); + // %23%21../output/nlc%20%0A%0Aprint%28%27Hello%2C%20world%21%5Cn%27%29%3B%0A +} + </script> </main> <footer class="td-footer row d-print-none"> diff --git a/docs/ru/playground/index.html b/docs/ru/playground/index.html index d06253ba..49a38dd1 100644 --- a/docs/ru/playground/index.html +++ b/docs/ru/playground/index.html @@ -91,8 +91,7 @@ </header> <div class="container-fluid td-default td-outer"> <main role="main" class="td-main"> - <p>Примеры программ на NewLang</p> -<style> + <style> .rownr {width: 5%; overflow-y: hidden; background-color: rgb(105,105,105); color: white; text-align: right; vertical-align:top; resize: none;} .txt {width: 90%; overflow-x: scroll; resize: none; font-family: monospace;} @@ -100,6 +99,9 @@ .error {background-color: rgb(255, 180, 180); } .pgbox {margin-top: 4rem;} </style> +<p> +<br> +</p> <div class="pgbox"> <select class="c10" style="width: 95%;" onchange="SelectExample(this);" id="example_list"> <option selected="selected" value="" id="example_start">Select an exmaple...</option> @@ -145,18 +147,6 @@ </div> <script> -if(window.location.search){ - const params = new Proxy(new URLSearchParams(window.location.search), { - get: (searchParams, prop) => searchParams.get(prop), - }); - // Get the value of "src" in eg "https://example.com/?src=source" - if(params.src){ - document.getElementById('playground').value = unescape(params.src); - } - //alert(escape('#!../output/nlc \n\nprint(\'Hello, world!\\n\');\n')); - // %23%21../output/nlc%20%0A%0Aprint%28%27Hello%2C%20world%21%5Cn%27%29%3B%0A -} - locations =[ "", "#!../output/nlc \n\nprint('Hello, world!\\n');\n", "#!../output/nlc \n\nfact := 1\\1; # Rational value support bigint\nmult := @iter(1000..1..-1); # Iterator from range\n@while( @curr(mult) ) {\n fact *= @next(mult);\n};\n\n# Check factorial 1000!\n@assert( fact == 402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\\1 );\n\n# Return result\nfact", @@ -165,14 +155,17 @@ "#!../output/nlc --eval\n\n# Create a tensor and fill it with values. \n# The last value is repeated up to the required tensor size\ntensor := :Single[2,5](-1, 0, 1, 2, 3, ... );\nprint('1: tensor = %s\\n', :StrChar(tensor));\n\nmult := tensor * 10;\nprint('2: tensor *= 10 -> %s\\n', :StrChar(mult));\n\nmult += 11;\nprint('3: tensor += 11 -> %s\\n', :StrChar(mult));\n\n# Import srand function and init random generator\nsrand(seed:Int32):None := %srand ...;\nsrand(100);\n\n# Import rand function to get random values\nrnd():Int32 := %rand ...;\nprint('4: %d, %d, %d, %d\\n', rnd(), rnd(), rnd(), rnd());\n\n# Create a tensor where the rand function is called for every element except the first\nmatrix := :Tensor[10,10]( 0, 42, ... rnd() ...);\nprint('5: matrix = %s\\n', :StrChar(matrix));\n\nmatrix //= 42;\nprint('6: matrix %%= 2 -> %s\\n', :StrChar(matrix));\nprint('7: matrix %%= 2 -> %s\\n', :StrChar(:Bool(matrix)));\n", ]; -function SelectExample(sel){ - - srcLocation = locations[sel.selectedIndex]; - if (srcLocation != undefined && srcLocation != "") { - obj = document.getElementById('playground'); - obj.value = locations[sel.selectedIndex]; - input_changed(obj); - } +function SelectExample(sel){ + obj = document.getElementById('playground'); + if(Number.isInteger(sel) && locations[sel]){ + obj.value = locations[sel]; + } else { + srcLocation = locations[sel.selectedIndex]; + if (srcLocation != undefined && srcLocation != "") { + obj.value = locations[sel.selectedIndex]; + } + } + input_changed(obj); } @@ -327,7 +320,7 @@ clearInterval(downloadTimer); document.getElementById('progress').style.display = "none"; document.getElementById('playground_out').classList.add("error"); - alert("Request failed!"); + alert("Request failed!\n\nCheck the connection protocol!\n\nThe site should open using the regular HTTP protocol without using SSL! Because browsers typically block unsecured connections on HTTPS pages."); }; xhr.ontimeout = (e) => { @@ -336,6 +329,22 @@ alert("Run query timeout!"); }; } + + +if(window.location.search){ + const params = new Proxy(new URLSearchParams(window.location.search), { + get: (searchParams, prop) => searchParams.get(prop), + }); + // Get the value of "src" in eg "https://example.com/?src=source" + if(params.id){ + SelectExample(parseInt(params.id)); + } else if(params.src){ + document.getElementById('playground').value = unescape(params.src); + } + //alert(escape('#!../output/nlc \n\nprint(\'Hello, world!\\n\');\n')); + // %23%21../output/nlc%20%0A%0Aprint%28%27Hello%2C%20world%21%5Cn%27%29%3B%0A +} + </script> </main> <footer class="td-footer row d-print-none"> diff --git a/docs/ru/sitemap.xml b/docs/ru/sitemap.xml index 4c2186b3..8ffcc260 100644 --- a/docs/ru/sitemap.xml +++ b/docs/ru/sitemap.xml @@ -42,7 +42,7 @@ /> </url><url> <loc>http://localhost:1313/ru/docs/arch/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="en" @@ -133,7 +133,7 @@ /> </url><url> <loc>http://localhost:1313/ru/docs/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="en" @@ -198,7 +198,7 @@ /> </url><url> <loc>http://localhost:1313/ru/playground/</loc> - <lastmod>2024-03-23T12:49:56+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="en" @@ -315,7 +315,7 @@ /> </url><url> <loc>http://localhost:1313/ru/docs/syntax/macros/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="en" @@ -341,7 +341,7 @@ /> </url><url> <loc>http://localhost:1313/ru/docs/types/native/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="en" @@ -419,7 +419,7 @@ /> </url><url> <loc>http://localhost:1313/ru/docs/syntax/dsl/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="en" @@ -498,16 +498,6 @@ </url><url> <loc>http://localhost:1313/ru/blog/parser-nuances/</loc> <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/parser-nuances/" - /> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/parser-nuances/" - /> </url><url> <loc>http://localhost:1313/ru/blog/dsl-with-macros/</loc> <lastmod>2024-03-22T23:57:08+03:00</lastmod> @@ -524,133 +514,33 @@ </url><url> <loc>http://localhost:1313/ru/blog/release-v0.3/</loc> <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/release-v0.3/" - /> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/release-v0.3/" - /> </url><url> <loc>http://localhost:1313/ru/blog/release-v0.2/</loc> <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/release-v0.2/" - /> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/release-v0.2/" - /> </url><url> <loc>http://localhost:1313/ru/blog/release-v0.1/</loc> <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/release-v0.1/" - /> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/release-v0.1/" - /> </url><url> <loc>http://localhost:1313/ru/blog/newlang/</loc> <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/newlang/" - /> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/newlang/" - /> </url><url> <loc>http://localhost:1313/ru/blog/prog-styles-same-time/</loc> <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/prog-styles-same-time/" - /> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/prog-styles-same-time/" - /> </url><url> <loc>http://localhost:1313/ru/blog/unusual-prog/</loc> <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/unusual-prog/" - /> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/unusual-prog/" - /> </url><url> <loc>http://localhost:1313/ru/blog/complex-prog/</loc> <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/complex-prog/" - /> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/complex-prog/" - /> </url><url> <loc>http://localhost:1313/ru/blog/lang-final/</loc> <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/lang-final/" - /> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/lang-final/" - /> </url><url> <loc>http://localhost:1313/ru/blog/logic-prog/</loc> <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/logic-prog/" - /> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/logic-prog/" - /> </url><url> <loc>http://localhost:1313/ru/blog/inter-prog/</loc> <lastmod>2024-03-22T23:57:08+03:00</lastmod> - <xhtml:link - rel="alternate" - hreflang="en" - href="http://localhost:1313/blog/inter-prog/" - /> - <xhtml:link - rel="alternate" - hreflang="ru" - href="http://localhost:1313/ru/blog/inter-prog/" - /> </url><url> <loc>http://localhost:1313/ru/categories/</loc> <xhtml:link @@ -691,7 +581,7 @@ /> </url><url> <loc>http://localhost:1313/ru/tags/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="en" @@ -717,7 +607,7 @@ /> </url><url> <loc>http://localhost:1313/ru/tags/%D0%BA%D0%BE%D0%BB%D0%BB%D0%B5%D0%BA%D1%86%D0%B8%D0%B8/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="en" @@ -743,7 +633,7 @@ /> </url><url> <loc>http://localhost:1313/ru/tags/%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="en" @@ -759,7 +649,7 @@ <lastmod>2024-03-22T23:57:08+03:00</lastmod> </url><url> <loc>http://localhost:1313/ru/tags/%D1%82%D0%B8%D0%BF%D1%8B-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85/</loc> - <lastmod>2024-03-22T23:57:08+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> <xhtml:link rel="alternate" hreflang="en" diff --git "a/docs/ru/tags/\320\272\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270/index.xml" "b/docs/ru/tags/\320\272\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270/index.xml" index d3395b67..9b619b21 100644 --- "a/docs/ru/tags/\320\272\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270/index.xml" +++ "b/docs/ru/tags/\320\272\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270/index.xml" @@ -235,11 +235,34 @@ dict3 := dict2(99, name=0); # Копия объекта dict2 (99, two=42, name= &lt;h2 id=&#34;нативные-типы-данных&#34;&gt;Нативные типы данных&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &amp;ldquo;&lt;strong&gt;%&lt;/strong&gt;&amp;rdquo;. -В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат.&lt;/p&gt; +&lt;p&gt;Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &amp;ldquo;&lt;strong&gt;%&lt;/strong&gt;&amp;rdquo;.&lt;/p&gt; +&lt;p&gt;В случае переменных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определенный формат.&lt;/p&gt; +&lt;p&gt;Чтобы использовать уже существующие библиотеки, нужно импортировать нативный объект, +тем самым создав объкт NewLang, но с реализацией на другом языке, например на С/С++.&lt;/p&gt; +&lt;p&gt;Синтаксис импорта нативных объектов такой же, как и для &lt;a href=&#34;http://localhost:1313/ru/docs/ops/create/&#34;&gt;создания&lt;/a&gt; обычных объектов языка, +только в качестве правого операнда в операторе создания требуется указать имя нативнного объекта.&lt;/p&gt; +&lt;p&gt;При импорте нативного объекта необходимо всегда указывать типы переменных, а также типы аргументов и возвращаемых значений для функций.&lt;/p&gt; +&lt;p&gt;Если типы данных у создаваемого и нативного объекта совпадают (т.е. не требуется преобразование типов), +то нативное имя объекта можно указать с многоточием, которое означает, что типы данных будут повторять заданные у левого операнда.&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Plain&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fopen&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;filename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;StrChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;modes&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;StrChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fopen&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fclose&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fclose&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fflush&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fflush&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fprintf&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#204a87&#34;&gt;format&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FmtChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fprintf&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fremove&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;filename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;remove&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;frename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;old&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;new&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;rename&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; + +&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; +&lt;p&gt;Последующее описание находится в процессе разработки.&lt;/p&gt; + +&lt;/div&gt; + &lt;h3 id=&#34;pointer--указатель-на-системную-область-памяти-или-нативную-функцию&#34;&gt;:Pointer — указатель на системную область памяти или нативную функцию&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#pointer--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%83%d1%8e-%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8-%d0%b8%d0%bb%d0%b8-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%83%d1%8e-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8e&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Так как любой программе приходится взаимодействовать с внешним миром, т -о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, +&lt;p&gt;Так как любой программе приходится взаимодействовать с внешним миром, +то по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип &lt;em&gt;:Pointer&lt;/em&gt;. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. Но можно вывести его значение, например для отладки.&lt;/p&gt; &lt;h3 id=&#34;plain--указатель-на-представление-данных-в-бинарном-виде&#34;&gt;:Plain — указатель на представление данных в бинарном виде&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#plain--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d0%bf%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%be%d0%bc-%d0%b2%d0%b8%d0%b4%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; diff --git "a/docs/ru/tags/\321\201\320\270\321\201\321\202\320\265\320\274\321\213\320\265-\321\202\320\270\320\277\321\213/index.xml" "b/docs/ru/tags/\321\201\320\270\321\201\321\202\320\265\320\274\321\213\320\265-\321\202\320\270\320\277\321\213/index.xml" index 4b6bfa54..be041556 100644 --- "a/docs/ru/tags/\321\201\320\270\321\201\321\202\320\265\320\274\321\213\320\265-\321\202\320\270\320\277\321\213/index.xml" +++ "b/docs/ru/tags/\321\201\320\270\321\201\321\202\320\265\320\274\321\213\320\265-\321\202\320\270\320\277\321\213/index.xml" @@ -24,11 +24,34 @@ &lt;h2 id=&#34;нативные-типы-данных&#34;&gt;Нативные типы данных&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &amp;ldquo;&lt;strong&gt;%&lt;/strong&gt;&amp;rdquo;. -В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат.&lt;/p&gt; +&lt;p&gt;Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &amp;ldquo;&lt;strong&gt;%&lt;/strong&gt;&amp;rdquo;.&lt;/p&gt; +&lt;p&gt;В случае переменных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определенный формат.&lt;/p&gt; +&lt;p&gt;Чтобы использовать уже существующие библиотеки, нужно импортировать нативный объект, +тем самым создав объкт NewLang, но с реализацией на другом языке, например на С/С++.&lt;/p&gt; +&lt;p&gt;Синтаксис импорта нативных объектов такой же, как и для &lt;a href=&#34;http://localhost:1313/ru/docs/ops/create/&#34;&gt;создания&lt;/a&gt; обычных объектов языка, +только в качестве правого операнда в операторе создания требуется указать имя нативнного объекта.&lt;/p&gt; +&lt;p&gt;При импорте нативного объекта необходимо всегда указывать типы переменных, а также типы аргументов и возвращаемых значений для функций.&lt;/p&gt; +&lt;p&gt;Если типы данных у создаваемого и нативного объекта совпадают (т.е. не требуется преобразование типов), +то нативное имя объекта можно указать с многоточием, которое означает, что типы данных будут повторять заданные у левого операнда.&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Plain&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fopen&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;filename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;StrChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;modes&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;StrChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fopen&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fclose&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fclose&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fflush&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fflush&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fprintf&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#204a87&#34;&gt;format&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FmtChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fprintf&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fremove&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;filename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;remove&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;frename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;old&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;new&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;rename&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; + +&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; +&lt;p&gt;Последующее описание находится в процессе разработки.&lt;/p&gt; + +&lt;/div&gt; + &lt;h3 id=&#34;pointer--указатель-на-системную-область-памяти-или-нативную-функцию&#34;&gt;:Pointer — указатель на системную область памяти или нативную функцию&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#pointer--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%83%d1%8e-%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8-%d0%b8%d0%bb%d0%b8-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%83%d1%8e-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8e&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Так как любой программе приходится взаимодействовать с внешним миром, т -о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, +&lt;p&gt;Так как любой программе приходится взаимодействовать с внешним миром, +то по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип &lt;em&gt;:Pointer&lt;/em&gt;. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. Но можно вывести его значение, например для отладки.&lt;/p&gt; &lt;h3 id=&#34;plain--указатель-на-представление-данных-в-бинарном-виде&#34;&gt;:Plain — указатель на представление данных в бинарном виде&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#plain--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d0%bf%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%be%d0%bc-%d0%b2%d0%b8%d0%b4%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; diff --git "a/docs/ru/tags/\321\202\320\270\320\277\321\213-\320\264\320\260\320\275\320\275\321\213\321\205/index.xml" "b/docs/ru/tags/\321\202\320\270\320\277\321\213-\320\264\320\260\320\275\320\275\321\213\321\205/index.xml" index 6431dbfc..45cf3b1c 100644 --- "a/docs/ru/tags/\321\202\320\270\320\277\321\213-\320\264\320\260\320\275\320\275\321\213\321\205/index.xml" +++ "b/docs/ru/tags/\321\202\320\270\320\277\321\213-\320\264\320\260\320\275\320\275\321\213\321\205/index.xml" @@ -609,11 +609,34 @@ Number 5 from the thread!&lt;/p&gt; &lt;h2 id=&#34;нативные-типы-данных&#34;&gt;Нативные типы данных&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &amp;ldquo;&lt;strong&gt;%&lt;/strong&gt;&amp;rdquo;. -В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат.&lt;/p&gt; +&lt;p&gt;Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &amp;ldquo;&lt;strong&gt;%&lt;/strong&gt;&amp;rdquo;.&lt;/p&gt; +&lt;p&gt;В случае переменных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определенный формат.&lt;/p&gt; +&lt;p&gt;Чтобы использовать уже существующие библиотеки, нужно импортировать нативный объект, +тем самым создав объкт NewLang, но с реализацией на другом языке, например на С/С++.&lt;/p&gt; +&lt;p&gt;Синтаксис импорта нативных объектов такой же, как и для &lt;a href=&#34;http://localhost:1313/ru/docs/ops/create/&#34;&gt;создания&lt;/a&gt; обычных объектов языка, +только в качестве правого операнда в операторе создания требуется указать имя нативнного объекта.&lt;/p&gt; +&lt;p&gt;При импорте нативного объекта необходимо всегда указывать типы переменных, а также типы аргументов и возвращаемых значений для функций.&lt;/p&gt; +&lt;p&gt;Если типы данных у создаваемого и нативного объекта совпадают (т.е. не требуется преобразование типов), +то нативное имя объекта можно указать с многоточием, которое означает, что типы данных будут повторять заданные у левого операнда.&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Plain&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fopen&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;filename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;StrChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;modes&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;StrChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fopen&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fclose&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fclose&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fflush&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fflush&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fprintf&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#204a87&#34;&gt;format&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FmtChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fprintf&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fremove&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;filename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;remove&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;frename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;old&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;new&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;rename&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; + +&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; +&lt;p&gt;Последующее описание находится в процессе разработки.&lt;/p&gt; + +&lt;/div&gt; + &lt;h3 id=&#34;pointer--указатель-на-системную-область-памяти-или-нативную-функцию&#34;&gt;:Pointer — указатель на системную область памяти или нативную функцию&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#pointer--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%83%d1%8e-%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8-%d0%b8%d0%bb%d0%b8-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%83%d1%8e-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8e&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Так как любой программе приходится взаимодействовать с внешним миром, т -о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, +&lt;p&gt;Так как любой программе приходится взаимодействовать с внешним миром, +то по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип &lt;em&gt;:Pointer&lt;/em&gt;. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. Но можно вывести его значение, например для отладки.&lt;/p&gt; &lt;h3 id=&#34;plain--указатель-на-представление-данных-в-бинарном-виде&#34;&gt;:Plain — указатель на представление данных в бинарном виде&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#plain--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d0%bf%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%be%d0%bc-%d0%b2%d0%b8%d0%b4%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; diff --git a/docs/sitemap.xml b/docs/sitemap.xml index 5daabc63..ed12a9ee 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -4,14 +4,14 @@ <sitemap> <loc>http://localhost:1313/en/sitemap.xml</loc> - <lastmod>2024-03-23T12:49:56+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> </sitemap> <sitemap> <loc>http://localhost:1313/ru/sitemap.xml</loc> - <lastmod>2024-03-23T12:49:56+03:00</lastmod> + <lastmod>2024-03-23T22:03:23+03:00</lastmod> </sitemap> diff --git "a/docs/tags/\320\272\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270/index.html" "b/docs/tags/\320\272\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270/index.html" index 9cc84605..7879296b 100644 --- "a/docs/tags/\320\272\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270/index.html" +++ "b/docs/tags/\320\272\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270/index.html" @@ -179,7 +179,7 @@ <h5 class="taxonomy-title">Tags:</h5> <article class="card article-teaser article-type-docs"> - <h3><a href="/docs/types/native/">Нативные типы</a></h3> + <h3><a href="/docs/types/native/">Native Data Types</a></h3> <nav class="td-breadcrumbs"> <ol class="breadcrumb"> <li class="breadcrumb-item"> @@ -187,7 +187,7 @@ <h3><a href="/docs/types/native/">Нативные типы</a></h3> <li class="breadcrumb-item"> <a href="/docs/types/">Типы данных</a></li> <li class="breadcrumb-item"> - Нативные типы</li> + Native Data Types</li> </ol> </nav><p></p> <header class="article-meta"> diff --git "a/docs/tags/\320\272\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270/index.xml" "b/docs/tags/\320\272\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270/index.xml" index 9fc56618..3877a515 100644 --- "a/docs/tags/\320\272\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270/index.xml" +++ "b/docs/tags/\320\272\320\276\320\273\320\273\320\265\320\272\321\206\320\270\320\270/index.xml" @@ -226,7 +226,7 @@ dict3 := dict2(99, name=0); # Копия объекта dict2 (99, two=42, name= </item> <item> - <title>Docs: Нативные типы</title> + <title>Docs: Native Data Types</title> <link>http://localhost:1313/docs/types/native/</link> <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate> @@ -234,20 +234,33 @@ dict3 := dict2(99, name=0); # Копия объекта dict2 (99, two=42, name= <description> - &lt;h2 id=&#34;нативные-типы-данных&#34;&gt;Нативные типы данных&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &amp;ldquo;&lt;strong&gt;%&lt;/strong&gt;&amp;rdquo;. -В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат.&lt;/p&gt; -&lt;h3 id=&#34;pointer--указатель-на-системную-область-памяти-или-нативную-функцию&#34;&gt;:Pointer — указатель на системную область памяти или нативную функцию&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#pointer--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%83%d1%8e-%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8-%d0%b8%d0%bb%d0%b8-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%83%d1%8e-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8e&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Так как любой программе приходится взаимодействовать с внешним миром, т -о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, -и для этих целей служит тип &lt;em&gt;:Pointer&lt;/em&gt;. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. -Но можно вывести его значение, например для отладки.&lt;/p&gt; -&lt;h3 id=&#34;plain--указатель-на-представление-данных-в-бинарном-виде&#34;&gt;:Plain — указатель на представление данных в бинарном виде&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#plain--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d0%bf%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%be%d0%bc-%d0%b2%d0%b8%d0%b4%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Для взаимодействия с внешними библиотеками требуется еще и обмен данными. -И для этих целей служит тип данных &lt;em&gt;:Plain&lt;/em&gt; — который также является указателем, но на двоичное представление данных в области памяти. -Конечно, если их можно представить в виде одного фрагмента.&lt;/p&gt; -&lt;h3 id=&#34;перечисление-структура-и-объединение&#34;&gt;Перечисление, структура и объединение&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d0%b5%d1%80%d0%b5%d1%87%d0%b8%d1%81%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d0%b8-%d0%be%d0%b1%d1%8a%d0%b5%d0%b4%d0%b8%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;&lt;em&gt;:Enum&lt;/em&gt;, &lt;em&gt;:Struct&lt;/em&gt; и &lt;em&gt;:Union&lt;/em&gt; — это такие же &lt;a href=&#34;http://localhost:1313/docs/types/dicts/#%D0%BF%D0%B5%D1%80%D0%B5%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D0%B0-%D0%B8-%D0%BE%D0%B1%D1%8A%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5&#34;&gt;словари&lt;/a&gt;, только на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера. Эти типы данных так же относятся к группе &lt;em&gt;:Plain&lt;/em&gt; и могут быть представлены в двоичном виде в одной области машинной памяти.&lt;/p&gt; + &lt;p&gt;Native (machine) data can be variables or functions, and the names of native objects start with the percent symbol &amp;ldquo;&lt;strong&gt;%&lt;/strong&gt;&amp;rdquo;.&lt;/p&gt; +&lt;p&gt;In the case of variables, these are binary data located in a single continuous area of machine memory at a specific address and have a strictly defined format.&lt;/p&gt; +&lt;p&gt;To use existing libraries, you need to import the native object, thereby creating an object NewLang, +but with an implementation in another language, for example, in C/C++.&lt;/p&gt; +&lt;p&gt;The syntax for importing native objects is the same as for &lt;a href=&#34;http://localhost:1313/docs/ops/create/&#34;&gt;creating&lt;/a&gt; regular language objects, +only the name of the native object needs to be specified as the right operand in the creation operator.&lt;/p&gt; +&lt;p&gt;When importing a native object, it is necessary to always specify the variable types, +as well as the types of arguments and return values for functions.&lt;/p&gt; +&lt;p&gt;If the data types of the created object and the native object match (i.e., no type conversion is required), +then the native object name can be specified with an ellipsis, +which means that the data types will replicate those specified at the left operand.&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Plain&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fopen&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;filename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;StrChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;modes&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;StrChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fopen&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fclose&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fclose&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fflush&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fflush&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fprintf&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#204a87&#34;&gt;format&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FmtChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fprintf&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fremove&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;filename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;remove&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;frename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;old&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;new&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;rename&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; + +&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; +&lt;p&gt;The following description is under development.&lt;/p&gt; + +&lt;/div&gt; + </description> </item> diff --git "a/docs/tags/\321\201\320\270\321\201\321\202\320\265\320\274\321\213\320\265-\321\202\320\270\320\277\321\213/index.html" "b/docs/tags/\321\201\320\270\321\201\321\202\320\265\320\274\321\213\320\265-\321\202\320\270\320\277\321\213/index.html" index ba293ed0..85fda011 100644 --- "a/docs/tags/\321\201\320\270\321\201\321\202\320\265\320\274\321\213\320\265-\321\202\320\270\320\277\321\213/index.html" +++ "b/docs/tags/\321\201\320\270\321\201\321\202\320\265\320\274\321\213\320\265-\321\202\320\270\320\277\321\213/index.html" @@ -101,7 +101,7 @@ <h1>Tag: <span>Системые Типы</span></h1> <article class="card article-teaser article-type-docs"> - <h3><a href="/docs/types/native/">Нативные типы</a></h3> + <h3><a href="/docs/types/native/">Native Data Types</a></h3> <nav class="td-breadcrumbs"> <ol class="breadcrumb"> <li class="breadcrumb-item"> @@ -109,7 +109,7 @@ <h3><a href="/docs/types/native/">Нативные типы</a></h3> <li class="breadcrumb-item"> <a href="/docs/types/">Типы данных</a></li> <li class="breadcrumb-item"> - Нативные типы</li> + Native Data Types</li> </ol> </nav><p></p> <header class="article-meta"> diff --git "a/docs/tags/\321\201\320\270\321\201\321\202\320\265\320\274\321\213\320\265-\321\202\320\270\320\277\321\213/index.xml" "b/docs/tags/\321\201\320\270\321\201\321\202\320\265\320\274\321\213\320\265-\321\202\320\270\320\277\321\213/index.xml" index 0e4ff5d1..776ff704 100644 --- "a/docs/tags/\321\201\320\270\321\201\321\202\320\265\320\274\321\213\320\265-\321\202\320\270\320\277\321\213/index.xml" +++ "b/docs/tags/\321\201\320\270\321\201\321\202\320\265\320\274\321\213\320\265-\321\202\320\270\320\277\321\213/index.xml" @@ -15,7 +15,7 @@ <item> - <title>Docs: Нативные типы</title> + <title>Docs: Native Data Types</title> <link>http://localhost:1313/docs/types/native/</link> <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate> @@ -23,20 +23,33 @@ <description> - &lt;h2 id=&#34;нативные-типы-данных&#34;&gt;Нативные типы данных&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &amp;ldquo;&lt;strong&gt;%&lt;/strong&gt;&amp;rdquo;. -В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат.&lt;/p&gt; -&lt;h3 id=&#34;pointer--указатель-на-системную-область-памяти-или-нативную-функцию&#34;&gt;:Pointer — указатель на системную область памяти или нативную функцию&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#pointer--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%83%d1%8e-%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8-%d0%b8%d0%bb%d0%b8-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%83%d1%8e-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8e&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Так как любой программе приходится взаимодействовать с внешним миром, т -о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, -и для этих целей служит тип &lt;em&gt;:Pointer&lt;/em&gt;. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. -Но можно вывести его значение, например для отладки.&lt;/p&gt; -&lt;h3 id=&#34;plain--указатель-на-представление-данных-в-бинарном-виде&#34;&gt;:Plain — указатель на представление данных в бинарном виде&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#plain--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d0%bf%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%be%d0%bc-%d0%b2%d0%b8%d0%b4%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Для взаимодействия с внешними библиотеками требуется еще и обмен данными. -И для этих целей служит тип данных &lt;em&gt;:Plain&lt;/em&gt; — который также является указателем, но на двоичное представление данных в области памяти. -Конечно, если их можно представить в виде одного фрагмента.&lt;/p&gt; -&lt;h3 id=&#34;перечисление-структура-и-объединение&#34;&gt;Перечисление, структура и объединение&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d0%b5%d1%80%d0%b5%d1%87%d0%b8%d1%81%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d0%b8-%d0%be%d0%b1%d1%8a%d0%b5%d0%b4%d0%b8%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;&lt;em&gt;:Enum&lt;/em&gt;, &lt;em&gt;:Struct&lt;/em&gt; и &lt;em&gt;:Union&lt;/em&gt; — это такие же &lt;a href=&#34;http://localhost:1313/docs/types/dicts/#%D0%BF%D0%B5%D1%80%D0%B5%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D0%B0-%D0%B8-%D0%BE%D0%B1%D1%8A%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5&#34;&gt;словари&lt;/a&gt;, только на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера. Эти типы данных так же относятся к группе &lt;em&gt;:Plain&lt;/em&gt; и могут быть представлены в двоичном виде в одной области машинной памяти.&lt;/p&gt; + &lt;p&gt;Native (machine) data can be variables or functions, and the names of native objects start with the percent symbol &amp;ldquo;&lt;strong&gt;%&lt;/strong&gt;&amp;rdquo;.&lt;/p&gt; +&lt;p&gt;In the case of variables, these are binary data located in a single continuous area of machine memory at a specific address and have a strictly defined format.&lt;/p&gt; +&lt;p&gt;To use existing libraries, you need to import the native object, thereby creating an object NewLang, +but with an implementation in another language, for example, in C/C++.&lt;/p&gt; +&lt;p&gt;The syntax for importing native objects is the same as for &lt;a href=&#34;http://localhost:1313/docs/ops/create/&#34;&gt;creating&lt;/a&gt; regular language objects, +only the name of the native object needs to be specified as the right operand in the creation operator.&lt;/p&gt; +&lt;p&gt;When importing a native object, it is necessary to always specify the variable types, +as well as the types of arguments and return values for functions.&lt;/p&gt; +&lt;p&gt;If the data types of the created object and the native object match (i.e., no type conversion is required), +then the native object name can be specified with an ellipsis, +which means that the data types will replicate those specified at the left operand.&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Plain&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fopen&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;filename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;StrChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;modes&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;StrChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fopen&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fclose&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fclose&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fflush&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fflush&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fprintf&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#204a87&#34;&gt;format&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FmtChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fprintf&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fremove&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;filename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;remove&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;frename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;old&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;new&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;rename&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; + +&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; +&lt;p&gt;The following description is under development.&lt;/p&gt; + +&lt;/div&gt; + </description> </item> diff --git "a/docs/tags/\321\202\320\270\320\277\321\213-\320\264\320\260\320\275\320\275\321\213\321\205/index.html" "b/docs/tags/\321\202\320\270\320\277\321\213-\320\264\320\260\320\275\320\275\321\213\321\205/index.html" index ba5dd382..e64d3afc 100644 --- "a/docs/tags/\321\202\320\270\320\277\321\213-\320\264\320\260\320\275\320\275\321\213\321\205/index.html" +++ "b/docs/tags/\321\202\320\270\320\277\321\213-\320\264\320\260\320\275\320\275\321\213\321\205/index.html" @@ -253,7 +253,7 @@ <h5 class="taxonomy-title">Tags:</h5> <article class="card article-teaser article-type-docs"> - <h3><a href="/docs/types/native/">Нативные типы</a></h3> + <h3><a href="/docs/types/native/">Native Data Types</a></h3> <nav class="td-breadcrumbs"> <ol class="breadcrumb"> <li class="breadcrumb-item"> @@ -261,7 +261,7 @@ <h3><a href="/docs/types/native/">Нативные типы</a></h3> <li class="breadcrumb-item"> <a href="/docs/types/">Типы данных</a></li> <li class="breadcrumb-item"> - Нативные типы</li> + Native Data Types</li> </ol> </nav><p></p> <header class="article-meta"> diff --git "a/docs/tags/\321\202\320\270\320\277\321\213-\320\264\320\260\320\275\320\275\321\213\321\205/index.xml" "b/docs/tags/\321\202\320\270\320\277\321\213-\320\264\320\260\320\275\320\275\321\213\321\205/index.xml" index 717fefda..9ff3e763 100644 --- "a/docs/tags/\321\202\320\270\320\277\321\213-\320\264\320\260\320\275\320\275\321\213\321\205/index.xml" +++ "b/docs/tags/\321\202\320\270\320\277\321\213-\320\264\320\260\320\275\320\275\321\213\321\205/index.xml" @@ -537,7 +537,7 @@ Number 5 from the thread!&lt;/p&gt; </item> <item> - <title>Docs: Нативные типы</title> + <title>Docs: Native Data Types</title> <link>http://localhost:1313/docs/types/native/</link> <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate> @@ -545,20 +545,33 @@ Number 5 from the thread!&lt;/p&gt; <description> - &lt;h2 id=&#34;нативные-типы-данных&#34;&gt;Нативные типы данных&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%8b%d0%b5-%d1%82%d0%b8%d0%bf%d1%8b-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt; -&lt;p&gt;Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента &amp;ldquo;&lt;strong&gt;%&lt;/strong&gt;&amp;rdquo;. -В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат.&lt;/p&gt; -&lt;h3 id=&#34;pointer--указатель-на-системную-область-памяти-или-нативную-функцию&#34;&gt;:Pointer — указатель на системную область памяти или нативную функцию&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#pointer--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc%d0%bd%d1%83%d1%8e-%d0%be%d0%b1%d0%bb%d0%b0%d1%81%d1%82%d1%8c-%d0%bf%d0%b0%d0%bc%d1%8f%d1%82%d0%b8-%d0%b8%d0%bb%d0%b8-%d0%bd%d0%b0%d1%82%d0%b8%d0%b2%d0%bd%d1%83%d1%8e-%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d1%8e&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Так как любой программе приходится взаимодействовать с внешним миром, т -о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, -и для этих целей служит тип &lt;em&gt;:Pointer&lt;/em&gt;. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. -Но можно вывести его значение, например для отладки.&lt;/p&gt; -&lt;h3 id=&#34;plain--указатель-на-представление-данных-в-бинарном-виде&#34;&gt;:Plain — указатель на представление данных в бинарном виде&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#plain--%d1%83%d0%ba%d0%b0%d0%b7%d0%b0%d1%82%d0%b5%d0%bb%d1%8c-%d0%bd%d0%b0-%d0%bf%d1%80%d0%b5%d0%b4%d1%81%d1%82%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b2-%d0%b1%d0%b8%d0%bd%d0%b0%d1%80%d0%bd%d0%be%d0%bc-%d0%b2%d0%b8%d0%b4%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;Для взаимодействия с внешними библиотеками требуется еще и обмен данными. -И для этих целей служит тип данных &lt;em&gt;:Plain&lt;/em&gt; — который также является указателем, но на двоичное представление данных в области памяти. -Конечно, если их можно представить в виде одного фрагмента.&lt;/p&gt; -&lt;h3 id=&#34;перечисление-структура-и-объединение&#34;&gt;Перечисление, структура и объединение&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d0%bf%d0%b5%d1%80%d0%b5%d1%87%d0%b8%d1%81%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d1%81%d1%82%d1%80%d1%83%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d0%b8-%d0%be%d0%b1%d1%8a%d0%b5%d0%b4%d0%b8%d0%bd%d0%b5%d0%bd%d0%b8%d0%b5&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h3&gt; -&lt;p&gt;&lt;em&gt;:Enum&lt;/em&gt;, &lt;em&gt;:Struct&lt;/em&gt; и &lt;em&gt;:Union&lt;/em&gt; — это такие же &lt;a href=&#34;http://localhost:1313/docs/types/dicts/#%D0%BF%D0%B5%D1%80%D0%B5%D1%87%D0%B8%D1%81%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D0%B0-%D0%B8-%D0%BE%D0%B1%D1%8A%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5&#34;&gt;словари&lt;/a&gt;, только на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера. Эти типы данных так же относятся к группе &lt;em&gt;:Plain&lt;/em&gt; и могут быть представлены в двоичном виде в одной области машинной памяти.&lt;/p&gt; + &lt;p&gt;Native (machine) data can be variables or functions, and the names of native objects start with the percent symbol &amp;ldquo;&lt;strong&gt;%&lt;/strong&gt;&amp;rdquo;.&lt;/p&gt; +&lt;p&gt;In the case of variables, these are binary data located in a single continuous area of machine memory at a specific address and have a strictly defined format.&lt;/p&gt; +&lt;p&gt;To use existing libraries, you need to import the native object, thereby creating an object NewLang, +but with an implementation in another language, for example, in C/C++.&lt;/p&gt; +&lt;p&gt;The syntax for importing native objects is the same as for &lt;a href=&#34;http://localhost:1313/docs/ops/create/&#34;&gt;creating&lt;/a&gt; regular language objects, +only the name of the native object needs to be specified as the right operand in the creation operator.&lt;/p&gt; +&lt;p&gt;When importing a native object, it is necessary to always specify the variable types, +as well as the types of arguments and return values for functions.&lt;/p&gt; +&lt;p&gt;If the data types of the created object and the native object match (i.e., no type conversion is required), +then the native object name can be specified with an ellipsis, +which means that the data types will replicate those specified at the left operand.&lt;/p&gt; +&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Plain&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fopen&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;filename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;StrChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;modes&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;StrChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fopen&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fclose&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fclose&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fflush&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fflush&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fprintf&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FILE&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#204a87&#34;&gt;format&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;FmtChar&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;fprintf&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;fremove&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;filename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;remove&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#000&#34;&gt;frename&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;old&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;,&lt;/span&gt; &lt;span style=&#34;color:#000&#34;&gt;new&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;):&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;Int32&lt;/span&gt; &lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#000&#34;&gt;rename&lt;/span&gt;&lt;span style=&#34;color:#ce5c00;font-weight:bold&#34;&gt;...&lt;/span&gt;&lt;span style=&#34;color:#000;font-weight:bold&#34;&gt;;&lt;/span&gt; +&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; + +&lt;div class=&#34;pageinfo pageinfo-primary&#34;&gt; +&lt;p&gt;The following description is under development.&lt;/p&gt; + +&lt;/div&gt; + </description> </item> diff --git a/make_version.sh b/make_version.sh index 4638dd71..6fe8abc8 100755 --- a/make_version.sh +++ b/make_version.sh @@ -81,7 +81,7 @@ fi #done VERSION_MAJOR=0 -VERSION_MINOR=3 +VERSION_MINOR=4 VERSION_PATCH=0 VERSION_HEADER="$root/src/version.h" VERSION_FILE="$root/src/version.cpp" diff --git a/site.sh b/site.sh index 695ded46..f6b21c7c 100755 --- a/site.sh +++ b/site.sh @@ -32,5 +32,5 @@ done cd $root/site -hugo server --cleanDestinationDir -d ../docs +hugo server -d ../docs diff --git a/site/content/en/_index.html b/site/content/en/_index.html index a7048a17..f0521610 100644 --- a/site/content/en/_index.html +++ b/site/content/en/_index.html @@ -2,7 +2,7 @@ title: NewLang --- -{{< blocks/cover title="Добро пожаловать на сайт проекта NewLang!" image_anchor="top" height="auto" >}} +{{< blocks/cover title="Welcome to the NewLang project website!" image_anchor="top" height="auto" >}} <a class="btn btn-lg btn-primary me-3 mb-4" href="/docs/"> Documentation <i class="fas fa-arrow-alt-circle-right ms-2"></i> @@ -26,14 +26,14 @@ {{% blocks/lead %}} -<p class="lead"><em>NewLang</em> — это язык программирования высокого уровня общего назначения c базовым синтаксисом на основе грамматических правил. - С помощью макросов препроцесора, базовый синтаксис легко преобразуется в DSL на основе ключевых слов.</p> +<p class="lead"><em>NewLang</em> — NewLang is a general-purpose high-level programming language with a syntax based on a strict system of grammatical rules. +<br>But with the help of preprocessor macros, the syntax is turned into DSL based on keywords..</p> -<p class="lead">Тензорные вычисления и рациональные числа не ограниченной точности поддерживаются - на уровне синтаксиса языка и базовых типов данных без использования дополнительных библиотек.</p> +<p class="lead">Tensor calculations and rationals of unlimited precision are supported at the level of language syntax and basic + data types without the use of additional libraries.</p> -<p class="lead">Модель управления памятью на основе владения не трубет использования сборщика мусора - и исключет основные ошибки еще на этапе компиляции исходного текста программы.</p> +<p class="lead">The ownership-based memory management model does not require the use of + a garbage collector and eliminates major errors at the stage of compiling the source code of the program.</p> {{% /blocks/lead %}} @@ -41,107 +41,102 @@ {{% blocks/section %}} <h3> - Основные свойства и особенности языка: +The main properties and features: </h3> <ul> - <li>возможность работы как в режиме интерпретатора, так и компилятора<b>*</b> - </li> +<li>the ability to work both in interpreter and compiler mode<b>*</b> +</li> - <li>динамическая и статическая типизация с возможностью указания типов в явном виде - </li> +<li>dynamic and static typing with the ability to specify types explicitly +</li> - <li>статическая типизация является условно-строгой - <em>(автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных. - Например, целое число может быть автоматически преобразовано в вещественное или рациональное, но не наоборот)</em> - </li> +<li>static typing is conditionally strong (there is no automatic type casting, but conversion between some data types is allowed. + For example, an integer can be automatically converted to real or rational, but not vice versa) +</li> - <li>автоматическое управление памятью без сборщика мусора на основе владения<b>*</b> - </li> +<li>automatic memory management without garbage collector<b>*</b> +</li> - <li>ООП* в виде явного наследования классов и «утиная типизация» - </li> +<li>bject-oriented programming in the form of explicit class inheritance and "duck typing"<b>*</b> +</li> - <li>на уровне синтаксиса поддерживается несколько типов функций (обычные и чистые функции без побочных эффектов) - </li> +<li>several types of functions (regular and pure functions without side effects) are supported at the syntax level of the language +</li> - <li>необязательные и именованные параметры функций - </li> +<li>optional and named function arguments +</li> - <li>простая интеграция с уже существующими программными библиотеками - (в том числе импорт нативных переменных, функций и классов* из С/С++.) - </li> +<li>direct insertion of C/C++ code is possible<b>*</b> +</li> - <li>имеется <a href="https://ru.wikipedia.org/wiki/REPL">REPL (read-eval-print loop — «цикл: чтение — вычисление — вывод»)</a> - </li> - - <li>символьные вычисления<b>**</b> - </li> +<li>easy integration with existing software libraries (including import of native variables, functions and classes* from C/C++). +</li> + +<li>there is a <a href="https://en.wikipedia.org/wiki/REPL">REPL (read-eval-print loop)</a> +</li> + +<li>symbolic calculations<b>**</b> +</li> </ul> <hr> -<b>*</b>) Данные возможности запланированы к реализации +<b>*</b>) These features are planned for implementation when the compiler is created. <br> -<b>**</b>) Символьные вычисления поддерживаются на уровне синтаксиса, но не реализованы +<b>**</b>) Symbolic calculations are supported at the syntax level, but not implemented. {{% /blocks/section %}} {{% blocks/section %}} -<h2>Зачем нужен <em>NewLang</em>? +<h2>Why do we need <em>NewLang</em>? </h2> <p> - У всех современных языков программирования происходит постоянное <a href="/blog/complex-prog/">развитие (усложнение) синтаксиса</a> по мере выхода новых версий.<br> - Это является своего рода платой за появление новых возможностей языка и воспринимается пользователями как естественное явление. +All modern programming languages have a constant <a href="/blog/complex-prog/">development (complication) of syntax</a> as new versions are released.<br> +This is a kind of payment for the emergence of new features and is perceived by users as a natural process. <p> <p> - Но одновременно является и серьезной проблемой, так как с выходом новых версий языка в него добавляются новые ключевые слова и синтаксические конструкции, - что неизбежно повышает порог входа для всех новых пользователей. -<p> -<p> - Еще одним следствием этого процесса становится постоянное увеличение сложности разработки и поддержки уже созданных программных продуктов, - когда старый программный код дорабатывается с применением уже новых стандартов и постоянным увеличением старого легаси кода. +But at the same time it is also a serious problem, since with the release of versions new keywords and syntactic constructions are added, +which inevitably raises the entry threshold for new users. </p> <p> - У <em>NewLang</em> сложность языковых конструкций ограничена естественным образом - за счет разделения синтаксиса языка на несколько частей, что упрощает его изучение и использование. +Another consequence of this process is the constant increase in the complexity of developing and supporting already created software products, +when the old code is being finalized using the already new standards. </p> <p> - <em>Основной (базовый) синтаксис</em> — на системе строгих <a href="/docs/syntax/">грамматических правил</a>. +<em>NewLang</em> naturally limits the complexity of language constructs by splitting the syntax of the language into two parts, +making it easier to learn and use. </p> -<p> - <em>Синтаксис DSL (domain-specific language)</em> — хотя базовый синтаксис самодостаточен и полснотью покрывает все возможные сценарии использования, - но его применение разработчиками напрямую не всегда эффекстивно с точки зрения последующего чтения исходноиков. - <br> - Поэтому более правильным вариантом написания исходного кода программы будет применение <a href="/docs/syntax/dsl/">предметно-ориентированного языка</a>, - который реализуется с помощью макросов препроцессора и превращает базовый синтаксис на основе <a href="/docs/syntax/">грамматических правил</a> - в синтаксис на основе <a href="/docs/syntax/dsl/">ключевых слов</a>. -</p> <p> - <em>Расширенный синтаксис</em> — программные вставки на языке реализации (С/С++), когда основного или DSL синтаксиса становится недостаточно. +<em>Basic syntax</em> - for writing programs in object-oriented (imperative) and declarative styles, +which is based not on reserved keywords, but on a system of strict <a href="/docs/syntax/">grammar rules</a>. +It is possible to extend the basic syntax through the use of macros.<br> + +<em>Extended syntax</em> - program inserts in the implementation language (C / C ++), when the main syntax becomes insufficient. </p> + <br> <p> - Еще одно неудобство современных языков в том, что большинство из них были созданы еще до начала эпохи машинного обучения, - поэтому тензорные вычисления у них выполнены в виде отдельных библиотек. - Это же касается и вычислений с неограниченной точностью, которые также требуют использования дополнительных библиотечных функций. +Another disadvantage of modern languages is that most of them were created before the era of machine learning, +therefore, tensor calculations are performed in the form of separate libraries.<br> +The same applies to calculations with unlimited precision, which also require the use of additional library functions. </p> <p> - У <em>NewLang</em> тензорные вычисления и рациональные числа неограниченной точности доступны «из коробки». - Они поддерживаются на уровне синтаксиса для удобной записи литералов, - а простые арифметические типы данных являются скалярами (тензорами нулевой размерности). - <br> - <br> - Реализация тензорных вычислений сделана на базе библиотеки <a href="https://pytorch.org/">libtorch</a>, - а рациональные числа с использованием <a href="https://github.com/openssl/openssl/blob/master/crypto/bn/README.pod">OpenSSL</a>. +<em>NewLang</em> has tensor calculus and unlimited-precision rationals out of the box.<br> + +They are supported at the syntax level for writing literals of the corresponding types, +and simple arithmetic data types are scalars (tensors of dimension zero).<br> + +The implementation of tensor calculations is based on the library <a href="https://pytorch.org/">libtorch</a>, +and rational numbers using <a href="https://github.com/openssl/openssl/blob/master/crypto/bn/README.pod">OpenSSL</a>. </p> @@ -149,48 +144,46 @@ <h2>Зачем нужен <em>NewLang</em>? {{% blocks/section %}} -<h4>Пример скрипта Hello world! на NewLang</h4> +<h4>Hello world script example in NewLang</h4> <br> <code> <pre> - #!../output/nlc --eval - - hello(str) := { - # Импорт и вызов функции printf стандартной библиотеки - printf(format:FmtChar, ...):Int32 := %printf...; - printf('call: %s', $str); - $str; - }; - hello('Привет, мир!'); + #!../output/nlc + + printf('Hello, world!'); </pre> </code> -Вывод: +Output: <code><pre> - call: Привет, мир! - Привет, мир! - </pre></code> + Hello, world! + 14 +</pre></code> -<h4>Пример вычисления факториала 40 на NewLang (базовый синтаксис)</h4> +<h4>An example of calculating factorial 40 on NewLang (base syntax)</h4> <br> <code> <pre> - #!../output/nlc --eval + #!../output/nlc + + ### Example of calculating factorial of 40 using basic syntax + + fact := 1\1; # Rational number 1 (no precision limit) + mult := 40..1..-1?; # Iterator from range for factors from 40 to 2 + [mult ?!] <-> { # Loop until the iterator data runs out + fact *= mult !; # Get the current multiplier and move to the next iterator element + }; - fact := 1\1; # Рациональное число 1 (без ограничения точности) - mult := 40..1..-1?; # Итератор из диапазона для множителей от 40 до 2 - [mult ?!] <-> { # Цикл, пока не закончатся данные итератора - fact *= mult !; # Получить текущий множитель и перейти на следующий элемент итератора - }; + @assert(fact == 815915283247897734345611269596115894272000000000\1); - fact # Вывести итоговый результат + fact # Return final result </pre> </code> -Вывод: +Output: <code> <pre> 815915283247897734345611269596115894272000000000\1 @@ -198,25 +191,30 @@ <h4>Пример вычисления факториала 40 на NewLang (ба </code> -<h4>Тот же код с использованием DSL синтаксиса</h4> + +<h4>Same code using <a href="/docs/syntax/dsl/">DSL syntax</a></h4> <br> <code> <pre> - #!../output/nlc --eval + #!../output/nlc + + ### Example of calculating factorial 40 using DSL syntax + + fact := 1\1; # Rational number 1 (no precision limit) + mult := @iter( 40..1..-1 ); # Iterator from range for factors from 40 to 2 + @while( @curr(mult)) { # Loop until the iterator data runs out + fact *= @next(mult); # Get the current multiplier and move to the next iterator element + }; - fact := 1\1; - mult := iter( 40..1..-1 ); - while( curr(mult) ) { - fact *= next(mult); - }; + @assert(fact == 815915283247897734345611269596115894272000000000\1); - fact; + fact # Return final result </pre> </code> -Вывод: +Output: <code> <pre> 815915283247897734345611269596115894272000000000\1 @@ -227,16 +225,16 @@ <h4>Тот же код с использованием DSL синтаксиса< {{% blocks/section %}} -<a class="btn btn-lg btn-primary me-3 mb-4" href="/docs/examples/"> - Еще примеры кода<i class="fas fa-arrow-alt-circle-right ms-2"></i> +<a class="btn btn-lg btn-primary me-3 mb-4" href="/playground/"> + More code examples<i class="fas fa-arrow-alt-circle-right ms-2"></i> </a> <a class="btn btn-lg btn-primary me-3 mb-4" href="/docs/syntax/"> - Описание синтаксиса<i class="fas fa-arrow-alt-circle-right ms-2"></i> + Syntax description<i class="fas fa-arrow-alt-circle-right ms-2"></i> </a> <a class="btn btn-lg btn-primary me-3 mb-4" href="/docs/"> - Вся документация<i class="fas fa-arrow-alt-circle-right ms-2"></i> + All documentation<i class="fas fa-arrow-alt-circle-right ms-2"></i> </a> <a class="btn btn-lg btn-secondary me-3 mb-4" href="/blog/"> diff --git a/site/content/en/blog/complex-prog/bag.jpeg b/site/content/en/blog/complex-prog/bag.jpeg deleted file mode 100644 index c80334a26fe0bac80ae39a117bc853eb03db5094..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 204893 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 diff --git a/site/content/en/blog/complex-prog/complex-prog.jpeg b/site/content/en/blog/complex-prog/complex-prog.jpeg deleted file mode 100644 index 6fdc2fce6dbfed52ed0388b0351e7671d32e67c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106820 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 diff --git a/site/content/en/blog/complex-prog/drupal.jpeg b/site/content/en/blog/complex-prog/drupal.jpeg deleted file mode 100644 index a291c9bf5f3431baf75e6aa07b4fe47aeffb7fcd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24372 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 E*^cu{tN;K2 diff --git a/site/content/en/blog/complex-prog/graph1.jpeg b/site/content/en/blog/complex-prog/graph1.jpeg deleted file mode 100644 index 4081e1707e37dde0931598a898ff46978272a84d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 172763 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 diff --git a/site/content/en/blog/complex-prog/graph2.png b/site/content/en/blog/complex-prog/graph2.png deleted file mode 100644 index a0da5e64f5fe03f2fabf38cac4ae17a07a1a4b2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31535 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 diff --git a/site/content/en/blog/complex-prog/graph3.jpeg b/site/content/en/blog/complex-prog/graph3.jpeg deleted file mode 100644 index 50ffee66f4625c00bedbe331fedda40ca9cbeea0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61410 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%0D>me z9g*_l)BTg2GfDo{pWdD;FLud%^e9uHC=U{_mBFBYnj%jybT!OTnSQ-svhb~xRcMwi zOPTWgS1xRS8#_7>k{G?B0iXPAjVtBMNqlbi{@cZbj9}L|cez8ax#kPR8&AY4X}znI zaXHX;-m*^N^l}`MYLaKu?rcbU?Y4^l{N(gOtbNv4NbBhk!{;;h#;OHI(vv@tWSVA@ zf1(*Ijb_9z)p6|IFKbJ+M81Ut&+2|sTFL#|m)Uns<6D_dM!)OP*gw7OsWg}_E$x;4 z8$gs>pA`-U`F%$-A56^mg<r`CE679`h9DEnl+3<MNG0ie$h~NHCJtzPD_>lB9YP}T z^%#lDbsb(#jB|N}ve^mPuh2ht^CoWk2Crs;Z@V8I)p^%XuHPoGRHhnd&6`tDbe6H8 zVG?Yw+M8z?pso$X=O&qNdnk$7Q6H)41#j(LgA>(<z<*L#O4cA>)KVaEs$=@nZ-Ash zI$Whq?D6@|!iN;o#7>m`$JU|)=2w47ngFGBZK&oY?krEbS-2$cJXn?ITKQ*%H=j>@ zFTTnd-Q&=0Oc@*AVK-QiyFyRAiSp~TaJ;4Wd|Ep#_UJK{>)1`#teR($fBT@9A#{9- zgYHsyR=3W`+lF~&_1V756FJW5+-|#<9`e<f>V_NWWyEtY*)VaLset=TOS)Xf_ayat zBOi|Ys%S)L^%C;+?{dslZz}ZURPLs%h0OF4URaa()1D_X6b)Y?&;4b3at?Vn>&aJ? zr0Z9h$I;D><xVm;>9a;Yk#*eManu(&6%%4<ppw0E&+D>LBHxmlpP-6HdqN_Vc*wK2 zHxFeErSpjGob(gVQ=zmk4(OZ#Get|V&-B(<xR&xm&Obi+&EuDMAmO#&Cx-6+-03?z zMnMy&a&J`^ldZ6>C!18E{W!Na_`};*<g)lZMR^HDjJ3Dwt}uMs*BXWM8;*H+FHz)p zNeOeZ`r{#uD|RqPO;TC=)S3C%qQ%>kj)y{7Mx4Sp^qr6M#(Wjt`1!%Z=LVg}nfX&P zWfdPxMwBmp;Nai{+qI0@jE%Ib3JAPjHr)>8HBPYPkw>;*E|7B6HU6D8(B+YW6O1;} ztezvbs#ip8H_yOD5{yWD!}%knGO6%FNsgoID@h9Gmh8z&X$=M19z~fF6n$Kc-HX>0 z@#S8+!8xR84@IH_bF<)7nA@hIHOC{}x!~31Z~G>5X;<a=a1TnTk;>j_)1Ag4;?fjD zGd}$Z70bv(sxU_{O;wY@OJ8nLnb&JQ15D>K+a<yTy!@}KWgjA_M;=|dYwuUsX?soI z;;=>M-dlzuY52KyU;3P*#7LI@HTZzkl%&WR&Ut;GA$L=#?w34Y$1@hNBth@~9ftx( z(%}A~zj<>aFBOkGs?GHyASl<R3euJ*t1|r^4^ZAa$%Twh>LlYeRjDc!H)=ZeUlxSA z$*GUi-nMByGCSe6>o<Pk4p+yyyV)APtA$;~qQXSMF^dV;-vFOllsj?e4N^?y!s=r3 zH(T$@f{l>rIA)`+>Ye9oo)=sa=W0}GQY8C<jgGqUAVkiCnkT;jI?u<SR5sWRMl=QJ zgG$|AMlQwHYu6ChCxnf7q~ttz=O*=KjN#U2Od7Sf@))bZZXnFq2f1bo0tHjLN#^%O zf?S8=$_FQ&e#Nz^N93oZCgyjs>GdKhSII_^)0VSzLr?w$&Pl3sU>@pj2VJ5h&%WZw z@)F9IU$nPLQ-V_%pzSmkwGos0<>A8hh$nAxE`B&g1}TeIWXe^{%U*sq?;UrBC*|0O zXFyVosB~*t_qih?BqLW@6^R$NR{1GaQKYKfP`mbymbAaUWZm-?Kvc+kUcm;@t?cTx z+io7lGL{eQk>wT4<>OO_`Je+a))cpaN0HRcgfgDsO=C4?*9%INcH^N<gVQM)(&PSh z8&(Aqk|<BPsfQH_V%fzv?pwDIT*EX>Gq<i(T|Q(WZ+y@=UK=x#K4SHp_4E+Wu_TG! z9g&+4L#k@^RD~{LZkF5krW?o$7T#7#HqCw8Wh`hAk(PIE;)RuAS*N@0V+E&NX#Z*d zj@l#g%C}ezVGW*<)r0a<URU`3#y~hvb(gXJa-O}h`RAq<%Fdj5_i(2N53`pPb>3Xc zdR3nfsmZl5?XGY~SKeOO^jP~O@02`Of9zd@9_L`Q{nG8ai%1^GG1$rxWUSEu<WS^p zny}wNC)K3fAp!XwJkHN?=u}OZS2l-*rV_u1Z+GC|(~9vOY)!~;Bm31EUUr<?oe$rf zH*?~;=t{@PzN^_?WvDx4FAF+gm&)^C@8invi{`XAmFGbXDWo@wH9K8U1FD?AM!({- zUa)32>BY+gwe58~RZdw9pd?fi9-Ifrq$Q=IYy+zxeg-DA`y~V4>eq<O+*YQOJ+ga0 zI{~*NE^7-oz*?M7OtJi}9b$r#E_jxa6vu12B*%~<!C8h`fB)@A1tf;^iM!sw5ic%} zqPff3JZ`+MZFeXubn1rdHOthF?$g4y7Y;I^V*_)Bw#*$mCZ%_sEx{A<sGzg1&E9lv z`!lu+>l@c8V}mi&VmYqk;@anq2{J$6*^PKV+Yo2)AOf6>W8+p4<&+xF{9Yc)YY1|Q ztc5P*RrH9~6m>k)V{vGFWWi`OKHSNs0eR8>ZtcdfA*#4vSa5D=%h3jXfzRF`^Lul6 z(!99>f_`Z+MFRPlG$1V<y4LX8Dy#CA@gv;3cYLOc3!M4md)B1*WT-le+>2*!Dk>F2 zetD##0iT8vSzC+LFrR_`gPFbE!fLm7Z@pxdlO$@Wa_J<A=hh-WWtu)7F)3y1oRYb+ znd&Hv#NBr_31MvE?=01J9b3vOr)Y1X7gIz`ib>&G2I+d$|K?L{=bWTz(ulN<Ycgke zu4}of3LXSjWKEM!@?V{2<+5swD~!?#c62)A^WlcwT%ApZppkGvFIB4ZTlt;I=UsVb zMo5{<*G$<uDP5fJcsnvLA5X*78+Ox!+ukphjPPPPV^Nj|M5`=zd)2{5MZfm`yA2zx z7J6he`@KFi_}5ah+NIh@yWKUuiK`}YA{-0E=M-%J%~yQ{AeJNhN^W%wP5-CuhJ|$j zUd8fF0*T-%#tp6iYVqCGO{r{A_=0;(5Go_arsB-E5`PKrZmIOV0<QtJ3{)&HR-T+= zVYzUh$LFLma<bp&O>RRG#NvTaaM6*Q(rjUqCboHA1_-yf_!=H)?_L<)|B&~*mc~`B z(XNP^m9X*~Vyk1CbUVd7{Md8cV4;d(!eSRZ^np*l>3ZBp*IQSPa7%Pkb{K}5r#r@{ z@KVwtt&%A|GuocXT)jymD}JM@nRC#W9Txk(vQg>qU~O@~wMq%f!oJn@cSQq&S@s^? zyMtoN>#t*i9k$(NA|Gk&mIl6Hv#-kOc$-J{^fS8X@xo)@yPw`6rPdwvi=BCrhDrqu z#wUlm5Z%;nh4UZkQ#2|vFp+%`kDfNpbtZwIoomqG`97d+Ok=!kIV`v3XAO4*dJCou zCG2!*_t7yGHxSV;EH!u^$P0JE#7csp+IwO1^gZhrhOJ37$v$5}pI8%4(sKK$a*D9_ z(qk(&)1xGtiH1OgVq|<Lc57oQDS5-#RDkKA;&s`Ipg{>8>=3yxWXIx-Y%9j<^Ai&j zw{~v+o0ai#^;R(=)~=MDv*35%N~Ngs_ExsgrKFMi_5T;s*mj`W2Mw(=<KBHMubx}Y z+&g?L#??=-EQdJZ7}4*ghm{&3&^c`5v>D)uBK7eTN^u(-uM->Ylu}pU;XX5t@X=#L zGRgglWMW}vW@enC{YTO;5P%d{avj+qSg!|1mmty^5lmKXbBZoOe;uQ($B4)p5}cmS z@|uMt8bv->d7PIx&q^8}*UB+1`@mYojuVngTOGP7Tx^m<Q&bX=TZ>OKvQ`Yj46e`c zxSiy#ji<@Ex^tlH+q?M{{~P@ihsXf(1*Iol>89wKwMl~{dli<{0VHkS!0=K7J-9Ah zG1GL6(~j30=O8{=bW{zWu7q-NQ*d~@nmGZS;>95rg;iq;J(QAqK@U8=Vx_u0Fs?1( zoO6mD-SCB^9BP+{lB?on+WKX13e{(XHSMc|?k#6afsNk)+R-H@41h(&R(bTs1FyzZ zD;_0AD}ft50doVall~#q0eL}H6>%QUg~mWAMNBbV#IDmwW-b{TyXqCYj1B#9@7E~Q z=n6sL%*Ummd&vr<3eHF!$&lD}-NOuR9ar{NO`=7sTM%GyDwM#|qj%5foR<UVMT)QK zrv8ObD~GZUgb?w7hO{ADbMj4&y<CCk{XkUkh;E#@;esv+-+$ovS#ZD)lpC6O#M&B5 zwx)xy0<qR~G*5BaMB2HA&iv7?y(@Emal#ofWk^<E?B|u%iGUYxoaPOO!@>OWJAF%R z<#kAa<Dw=nL?8_s+>xt!_<9bow?MxP$xH6OloOq!Tm2F;^F^@}PxYnKO@UG(lgVM$ zQp-BkR(p`d9Dh(~ph}Qi()nfJo2!(x9YZ}q<6kzxS;>v9&U<4}UCnaLsWSBdSQN1L zPH~m8q)XcstR^<e_ZagQq?7)yW#>wkS$N-F8Nf*J)1C6K)_PhPLu3_DJ`WJ-=0}3P zMgLKZ2^`MR2J;+(NaB)syq@ixm;{9R!YBA?6^qBf0Xb~vhj=q7rI;BgYZ6P|jRJG9 z0qUV4Ie3ZR1&A%?;MD!dAoJ`{>6?meD62O@ia49m#u1RB_vVC*9`pRZ-nuddV7=+r zPE7J&sLBTzWRZ01fdD34HP`yMnq+I(cq;UPHb7*uSFDe<eQB;&Stp5CP6`<_DM*Qt z^7RbHAr#yu1wdj5BQ#1`Zow{ssuBf>z%E?*T};RWJU&GpL=z59ixSOrIw#BI)uPu7 z(NTod$Y?JR57c2x%Vj*>nWdb`@Kl#fX8M0NwsRfQzmW}~7k2x!_2QLQ?TB=A&?Eie zeDBhoq8I}uf59^Ayw9#k7~(LI*G!z(kr6`b{n(MtrVcTiC(uS!LXY)+QluSvK6ZQk z*ooPydu_*@W2&CA9E)PF+T%O6d+`6S{$Gfb3N04DcwF>^`(~nO&Vhqo*X>W(iwhz> za0Mo&QP=*<C<l~2=EtEFf~Qmaz^`i(&*>u)Lh{gYbFj9AqnIDw(OiSdY-88Y9H`#o z7EJaYz|dY@giu|gBhhpR2z?kpFdKe&wbtVN?B}GMNG~pvE@{Q24Dg@1U!*F-Nax9! zFwI!_W-l>5?}6ZfvEobT(2<@KoQ_2e@-X3BNjL6RBw{r$_iQ?sg}y+D3K?lbLf&LF z5xy$ieVz@sLjib<Y^;)Ig-2|eq1VjK+r^4GKypyH{DX?x)B@3GI7MWPhFh!455f8G ziJZ1RR2*xw`L<?c#M9ItvA!Rv`u$32ZsmDDsUV0D-AYRBu=h!?lG9NqT0h%j4_c=g zDEdYg^MYhReu<{_N3~z-8`Dq7Amv0sot<K?<~dIv$?!743>7`K{<-Hz^$bv{6mYpP zLt&|?V6XCVm4*S11#Kk`E;p^`n~urb*+GIFK#Yx36@Q<xak?l-Eo&G_@~8u&5vxh+ z<(wWK{3yk`XZE!(<<2LIy8ZVq<hfM$?(^p~A`f^7C$~fA->0tsr+AS*TSlCmwB(pD z+rCfqS6TQ%F2GQe$6E6#<tVBDu%~OXNq`KQRpkZOi-6w6bF2kvBG&4|$X#+)vJco5 z!E`&Jz#`mmDDJgIi7&m_Af^Z2|J}NdrIOmg3<_5JaVvS3VeY-UW}0gdrx}XqX-zxu zjtGXQUHEP$J0WnWF3-ahFZh+zypmg@3E&ET#@)4wVq@$euefnmXyBCKfnrh|Z@frV zq>UEL>DDfXUk<ThEMWwzEp@x7MMkh2lwZr5bYcC><42k0`kdq+8mEeXq~W2x#Wrpd zOemUQ%Bj_y7g!+~!jOml3w3<lEEo8gPEG;q0)+iqHH3+fCS{2x&2<*e=0q1379L*M zZ~RgGp*`UyE4RVLyABqNUjl1}msgw2q+O`tm+v1U6B)ry;5nIv6Zp8Y9+qZ40gB5u zhLVW<@}h~b474=`0X*0@5IUM56<#kfNz~`!F5boPr?-Qpfe1|HYUivP3U7DE1<wtO zR=&VC38a-N9R<v>qAo!&Hh1n383Pe(-gDqus@4SyuRsCG6eN6cl$YBz;*+d2coy!_ zr;(;2Sm7n&I;cf-VxH}C`eDE{bs?!Qpf10<{G)91f1iT44Su&MG^*ND@vDRROWX5V zGiTKPt}w#Kop5mgPCFvKM1Xyvf)vOP`>;y4w*NojiS_hPKEiAapvs~1O&zxQ?jUyE zsAp-)qqCkr>E-HkQ;i!fr?S<FTA3s()A)skvH~8mMyAX=e81OruWMNFspIL(oy9<o z!XXn66|Y#8CMAzf*E`_Et20Y#IXow=<b-6an7TcEVY+%#3>kRY4xd}Ii{;vg7=iW8 z#B3}h#0!;Djo&ghjPG`A;9Do(7{bL0K3_|gzv~lNkI+Z7BHkZ+e)}p9nFg|!hINDv z9wu*WfTn)_+I?IN>c!ctIzR4%=b1c8CE&AU>ne-~SL?6AGJp(wXa<dm+kM$iEFT?B zQ3E;yQs8Xd%=MuJx7l|5XXppItBWz)iezlAEap4p1AbupYetqMUO>P3EN@uAt#-20 zBs1MQF|gy;xBT&I{LC3K?`pPDfJQR`Oo5lVA<#WfD+t<cibj%rY}bx}(9eqZc<)+8 zn(^CM+N57Zr<B3oT3(PfECYoeDz7#6{BTKzW#&nakLT4;H!Y#+OSh!;Jce==d`!@X zr0BHkjEohSAhRclNmd>>C?!MYa2rDOcI*xKvf*&XX_iv+sO)an>lf2i1gSKq0tm(8 zupTLSLK7<`SzDATRv}~%ot*X&36^kKGfgvDCVVkWGMXW@+i6xMZn#zdl!*3kX*;9p zV4iJzCTsG)MIlX($&E1lg>aM^vPxynZkz<pL4;yp`1>Y-E28|BDYlc!RjT5eWp$b( z*Ny)d<Hm#Z_`6IrIVQy@=%jYKGQK!NM?q5xkc(tnrh3e8ZTCEmrR%$$6#S<2A-YT* z)da6a=&QmPbHOQb2LhWnt{m7QVi$$4p=9Pm#ZoiG`q<^fuJAElS64tuN+%a97n%6P zhXpdQ*N^KKaN|4hUCQD`b#6A+FNs0{B8Fqy5Gh)}B-3SUW;f#>jITxCZ<zGZ-<sSW zHBjM%Ceq9ocAHKW{|2~rB(@6a#-CYfhP-m8uwvvApNjV)={k&KCK(L>f|~#WHR*>q zwLfQ^^_Uja!1u%iEzOxEcoyWZ&#7W<USYCg*?p8DY6ifzLAz)iudVEG6TxCdnE8OB z=<qOTHE5K-u*YN;K#B$UVEffOFgA)fJ==V0(6F49)rL?XN_2+p-hwNJEqsGVcyz+D zV<P8TC8UYHCJ`9t#NGhI%d$|j0n->hRSfM=tP_-vqM%U!N^a-5PRP)y|9c8Oa|9+^ zZF*;PHB8{hZYYubGV17t>2(f6-Nmn@3_|0x8CXa0f%}C`UUwZnrsr&w5iOgQGZs-g z3<J;~mD&H>3YjpWj$k`4J^NlN!6nP#z2vb$q5F3~kiEU2uh7|D=}M1v;`VeB6CKl% z({4l3IIUio4&y(VemAwSuCTY`ZAAL=^WlIgpWNgaDV}yXlQ&WM{J;@bv3U!>T$y`2 zuwoK^HV$Q!j8<_Y(~M4@W<O!dB+8_0jI*7r%TEG%g~F*8V8fZ8+Ro4R#-8dkpQ{VK zaLTITnL@JZ57=QgeX>N=FkaH5leBl48*YV8;NHo+VW>x$XcV<Z;~|_^L=R<&rESRd z*gf0=&Pxd|-(xvc77dRUl*p4^oiy(P>YvUq<l`G~7pTM!1Ll+aFxO>HY^0h|;K7R4 zF`a!ff1ac_LD5qnv&6ZEDOt{)?$z8+&^MZ_uG~1Vcbds)8FHgau`8F`@a2tGwuPI2 zXrA`j`EId!rH+=m=JIc2nKRnVp8Eb=MxQBdxc^x!u~F~!?&Xg}K38V4@)7qh4S;Cl z&(eS!`Dy3`mS?xI#W}?D>}N<u^|>TpvxsuCTaGTziN^5lrjGBl9t=RyXh=WkK9;m< z0<;2jj1UkL*A64^72LJD+`~<tLug6A=P4y(BBdlJs~)U&3}{TYqwVLo2Q8o@(gG=? z89^2-M#K(5j;6en;BMXp93lO<L_;4!{;<uhHbcvpq#_nRUG{^Qc<pv&D%Y)TXX*dv zRU=E4J@PaTYAW9Wbsa@_KM#C;$g4jYJ{5Apm}&w;_k2qSvDV#IP_9$s6}j%9Yh{MV z54vpLWEME`D$tVUdU_r)6#{EC)<=KC<JYtpt_r_T8>xawlxi39G<t3sL-n(*`07E5 zw$|kl<wW2I^MKbC`91_L4s%3+>l{&hf}f}<9<-jMwu%2g6Hj{e_UXR?;l@tsd7onJ z$lv8;PvF%ovq7NNV@5m2or4&pMJO_K0BR2#W8^_~N9KpIyk{%a03wexi;}{?v4@^w zK7)fure~1skRXdh^%jO_Nlef|WhqpTQ~!R?8K-DE`bQj#ao~mg&cP}v#J4UHr%_~z zB+7zmgW%{8O<q%?mN>Szx!|ek%KW62&b;>A#KI?xmys<S=$qaNhVM4cHm(_Qp1?Ji zE<HvDBWC;gkT4p0m7)(O!*uX2OjhV(AMN|#o<1})vuu&uL6Q?|to&70$aW&M;mhPX zt`*(u4}Urf>a`}ZokV;)$^ZDL09mm3`#t#M$A!8*d&`fYDavU#?<Qf+fMY8=A1a=0 z+H-l22sp~?teT=N!7(vC^<??8&O^(AFeeSANq)2aMtwv9==EfFcDVZ99U(uqjZ46f z%F+B<IEcG7%kLh0)>n~An@^`Pu^17hQ}eN$j~ROAVIo?vl$prgrPl*!qK;x4&+tGl z&8H}=P@i$rq(KqIcjQ`I!%>}9cU)a+&_t75j?1r-clTOr(v_Ns<8Jn^RPGjV>3*~= zyr+eJA}R~7%zasoc@D4ZsIK`alP=c)vO^{RG|Uz~li=X`QeWfr%jSaftYwcUDi1Ep zm;lSA*9{w3i=5=FG*bj3hE;shsL%#V+DfI<1l()=#c4>+b|fG|7QQx%IM*Jl{er6x zdP%$|jL@F~JwX3B4P4nkMdoy&G4-278f(D=E?-&hWnD@|XX)A$<B*;|-ddxada}EL zRu@4j4Eoe9n@9(a0E+JF^x2TNK_;MH*KIPHhix1HgXxf0qw{FzYVZl)#y7*s-UzBj zx-4zm$?59#9@BlPehvfzM7%i5%?hvXc^IDe!9=<#YaI#}NH`Jo=w}0C^%`+BAmf!L z=cLV7$1D-bo_8y!+s&n|j#yb2k9Z__UY40*B6hk)Q=7a(<zkc*W25=QDa-lX6IqHT zJ-q)rEH>gajmb*tj_`D;{Smdk=*Hz@7gqrI-(VtgGAO=vayV8mr0no4K8l0<<}&EW z=@FDwjxMjY|4*!Oi@?f~Mf17s`%f#b_|O-{f{cDzVFKubky)U_-V8&Pbj*eRn19rG z|HoD=LxwIK5)`hP+K^y&Qfba^-o<zxW5ZefA6tB^?iA}7Pg0i<5O0EQKSjv_t=iwe z?lI9HM^a0fYmq`lv`q)wB2lFjIVrB%LayTU5l&6?3$c&VV;@%-`f+a6QDQNW0wWy2 zW8KVvTs((FOeU9G`HkYEOirNE+A)wt;;itheYkAJ<1!{TK5x!%C(^k2Yz(JTMbDS9 zvb!H@P`N0c4I&FgNilSFa6yPm?Li(5wlycb44|GA)URgMD`1s0P;X{rPU|6dM63z7 zyC%>?pYbUnlaM4<=3lzXnZ$HiP@Zj|Z@JU&kEM&@P#Lb*q@Ojv@!lTdwV0mNjj&V` zXJRQ|G~vL*f80Sl;<(koYa8aS7Dx1lUXpi7`4|ZdB5Pat4J2SLj{D1kcjtQqcT7tz zW`v9AK)%|X*W&t;;4{}zy8U8t;=!kV4IU66ElEeTC8r<W_y(zx)@WW;Biai1is$^W zW@#Q<dD|x?L<136vXSt6`b6RHvN#Na+^0~-+fx<kUKi$mgD3O!isp^Z?MGmYbt5rS zs^;_4?mtzlrCNb(&c%bk2Wz`#SZkJ{o=57kw}Cgkot^CSxt2-o`*HE}@lINr!?Rqk zb#x`4FwSrN2ygDVTl&0)bF+w;IPZqcb^=cd9yt5cxEFs3JkcYyls|n-Z*Zwq++1^M z<Z(|WTg1_8DQN&(JC84_H+4i}F22q5o7<_Vq#BouRE^jQwuy&VADIO`VB43*%T$1V zSmZL-G0$lztjK=j3b~Q~!D>s6s?7x3kC{uRC?M|Xpa1cs?|bsScl^i6aTu)icM>G- z)J#A_GF|lN(rA$)RTE=U_u}V5*gZt)`3>{ELm7HWVru8A&WP1mB6j2z*N%Fpy6_nN zSmX6><4s8dgMpN@BY-cO{~_lve+r+0YXyxRBkzNQas|W{e`n&xFGFxn7^#zSJq5Y- z-<haaI0BP?1NZ}YTAsuxcRI0z1aDiTIWkjA4@LvCjXPM76d@!g8o(Hjfn{0x*jYMK zty&aMp?`A4xD==snKG1cn;<PnrW;{!lsnK;V7(Ms?oh^Sd3o>y$B0QlLH>Nj*}FaE zZ*rKgN%qd@m87%UF+a^-X0vQE?7k_Q&iuOl6dz4$b(9-#auu<<r5`IaFaAbPAA(+c zdDK*&nQ854Uv<^ru84)1G2VeA*Bp*rGeU?fYY-q|jG}|xNBm$><Fj(BNNZ^8HX3o7 zb@){AU8@r^vhAwW!(&~2>~Mo(gw4v+GAGHHxq-D|8H_~zCCw4=a8dcO)Kh(?DNFCC zOT43CMb=d?iS2_4ljnb?t9x)F`o!5nF&u;YRW}i?myc7>zM@um)YQ0L9P5qY5Zw=@ zACKv}h012Y6PAzJY<PWQTG4M!7_Or8^i!Y<_ZS6W0er&HkKvPA;m^7}#<lz#uxs@s z-}yHnae9rMA>v!5bK&I*m`(KOft$jS>L`oOmoSAZ8|Qull8g2XfLbjc*}Op0C*xoX zYzzR3USS-}Vzvs;<$N~zM-yU6vNj!#4r*c~;27Fx^yFpgeb>{$$`<mTk(oztmr>tI zB#QY_*Q8&ZkU^OAh|nXN;#%84hf$$FMsrLvmlMaOwJ-r@A;>OitnDuwKcb5nJ^F{S zpCTj3n)AEWKMrw!mtXNABTKN`L4=$}yJpJsr0+-x)0q#A_vpZq2;M7@yTpR^PV<r^ zTuBAyeM0t7*0sK)OOm46Sg(<gjA)VGNFlxoY>a8&QOyXGA^MUe1n&K0K5mIyCuT{K zQycIa56PgziESB%Od(sI^o#LJ>XT%y$9C@ub_fuZqRWq-%10RB5#XW&!+9Qur)>)Y z!7wAuu9x=(gf`2>HkV7IuG!R7;8V)&4dV@kx2vwjlhObwp{S~jo03>tz_5T1!I<42 z(>#fNjjoMT!uQ}98zh~}wfJxUkfGG?NJ$zx{$49%2SJOz5hZ3T#=P9e)W*l5VUY&a zt}J)<4Bf?YT!hH>?edDh0oLy9MI%70o(;cZGD&aDzFi77gC|t}v_%oh53I?#^02xU zM@pa!eXcN`U$XtnkK&NoZcH~nz<2=W>gV>_crs)2gp^)fuXZ0s{RN^u)88o3&ae0v zB@nfLP=W!CoGVy93fuz#U9p;4ddSun(uv+aU-!A@4k$rLSj5jXpb)ab^nUV0hPRbz zdg0uKr>O?-#G!F92kIbPZF-<{tCa3B2rE}$^VSu}jo=vlGrA%JF{)@9r?@|4D2PU~ z<w0;7Jan?VYb7xups--7O-d(yG0dtvQ_bcI$q`Mbc%rHG&7#Jt3rrnz;F|0@jaQ)g zur;bqsSxWR%h4$jE6?;2&AaBOQwo1xM77BTq)warg6_LFD+7WJn(-Y0h(94z-4Ahb zq4_LglLJkAmGEMTh@W>}aW*>2*LJb`2=P?;RK85kKoK|ftxu^g@#Zlnj)_ZPuO(lN zbIDPqzjSjS*3nV-@6*r(m>hl-<AS8yX6-LY@bGqaGFyFm<!oUNSzHF7UTfr$)*`lO z*Y&t+A-tvPQQ_|vOWc|wz9bnil`-Aq_&JPOwif2G57m@B_&$%RozO4sUUj2SQW~6U zFQo@T+(5yt-75@Sb5h_nIF9q%8&@DxNl^09T77@com(BbHNR@mdf+{lp*pv0q|n9H zzn<9g_E~Y}Cg3Pkm>e2B*;9kh3nEi7VEzLf1ACFkkLq&m4t<g~-1b8U5%r`=hU%z9 ztUjh+vY=9gnV*mG=ojhuAV;=iy|;(s7mT9o?;lm2k8$Cywt_{YMnZhI6)#_4BDgVe zN8vdPY)3~a(~&6MmS}V>2sif8uos58ATD!PICz=ql9{qVYFyiW{(2s<=#`a@fXjeo zqNo1GdYn5pDDuYlm6hHSX28O9SVHIm6f^ZAME^J^S~_2n^QQ(5?E>x91iM>`V^2m} zm=th32F=T5Ui~Q@lBh+1`K6g<JUi1fhpI8|*XMzP^#V<&>G&X*Q+=#UDRY8x>^SW* z+qwP;hAA?R<jpR;YO-ITe=5nl2=3X&U`u?bnA)BAewjoh713H0dhRZB=ck!p^_xIW zE6dU^UW;fjVQ&6|zix&^|6(?{jaLwBc$lq+dMs_#&}za{BDR{7X@<eAQEY8{==YSg zPB#>eo-bndrE%Ji?09j$y5Zez2EN&}aTEze+fBn0H_&S|=XQ*#S_;}<NQ&qD;y#Z# zvm&^)up&VAP@kvG9qwqQ*5X-x-8l$82TB$xl5W4&2NuiBQ<|BY|2dktc~gjkE61U& zgMut5k))?z&5kn~lA+lQM6_G+EK^A<?*ha0*d_fFLzAd?BB4-leqKv4SWb%}60t<| zMfck+w%rh-Vw#I%K1P@-+HO{Kts{U3li&U5xo|v}5J%ht3bSUUR}Qms^Z{s^kh&~^ z{rV}@IRUp(;-Oo?!{8P}P;ktw*=u%!;ex=CGaUiP%x+iR42GH>Y#+9^{2<U_f;-a~ zXdxVOwL%1>%6u7iQA%)|#%YR0=z{?sKttCul_4Cjqg#1g)P|qcxfYqUj%5(wUuDXM zjD#F5Eg3|#sBo{~9*SB7b6B7*Lm(ylxlE{4S6xgJuXrN&Cqu0)lc0i=^%l?OENqqg zrK}`Zqr2Z3U|R<b^hGagJGZksUzL&8UyVY(#40QPkUUuGf+!pHK`;aby69&k;pTG1 zggK2VNIE#$U1!7(zX7?AO-tIkA{O21v?9@1`K`&EH%2s5GhdsL2?ed&d{}K``3Imu z5hh(NZeM2N$-@~?Fj$WBAcn}4t^)5+{>n6~52WE!T_)Yp#iAx0nI}q)NgYDR`9(*$ z4aa<r2bJ(Hj+MH$6_7B2u^P`myg2S%)8CnJJ1rv)Z?4?v-+ncLHCQq63GDsh+olf1 z3W}$o7YQaZEpG3s86P6a(WACP=Dd`B7T*1mOSo90la%ebhcZS?Y~~~%oQ?1<lHw)Q zNd3XZKr0NH5^#fHN!kKDtt93|*Q`woX}E^M!h$>mN<w5tGo~>29nfEF+#dP)$&s>P zHB3}y6OpXFZ?LW8KFNwPrq<>{B<3`^t&LcxRv37Go`;HtjWO2=OvLjP$r3op`kCfs z1`G>~1OoZ4_*9(BmvMyjB-W3KH_spQYh8gzT;1hKi7tPEcZqh*Bav8IN_0>lmB($@ z^LMu;<(#3K(V!B;STs1u-;7^BQjy8)Vyx_`Vxm;&mfE8OaRB7SC=kPuD{c2(ea|y3 zMn)vSLzx6y#EFkHusv%6gLklb#Q<W%gA>d}p$KEQB#`)A!)SaI3{`>SDcBz8AWC>3 zp*SE1U8R*PldGd<^|}P4sEFhVFH9V>0tVNSoU+~Ci47c$h8{9$FyyX=lp+oYezJ0B zUQO_MOi)LtwGTV5H`$bBcFdb0^n7V_yrS{!VovKYsQX9xL+Z4b0<?p31Rp6wA{Bqh zV~FN&fGS(F1(+@LY`eYaFf#5IA4@RQ1=<!7=1mFamuV0S|LNOwMEYBe&Wj+lR_ST( z)-^IsQoZ63)eNxU=%^>EP-_i~x1N4H#*o8Hes?2U9%u2ky3$5i=5!itQkG+8u}q&$ zRVz%Fo0{69wVjq3Oc8kX+K|BYx|kf8QXaZR`T;eEgytZpt!-!e(r;+i!=!Is=WKG^ zc_G=#<-x*CCb+^y-zaDLQtK~AyF_#=zJz#a?n)<qVeD*dw==nu4UaqngS^8epYOzI z_fALz!LL+_7SbSR5enuIol`kkj<R>v(HsV~3eMF$T&_J}#k6yvBf_{d<?D&pk7;Ec zRZeFyx0b=Ch2TK_Ep*Ja1##(0brnrb;{aEo_<=P`x(<{j1Ki>q2C+h)#!Ehfd#t1i z!m^?j1}!LXT6b_}s1Y77z`^8TAq3GMKz>MGdI#vKFBj=c<;URHbFgilZEv7gkDla7 ze#v7}<tw6E0O~E5JR(5*ro^mx*`b<;sEGzsOwgUU+Zqx&OvKd~CAFFd>2_o4{_4z` zq@%uv1vlMTUB1`bOP>n@BajFeHB1mh!CI(ISn9bg=+W7=!k!ppHaYg=s~O=Z-6$%O z)6TZoBSE3nBkuJ8!?{b<JiDAZ?A44;I#@y;#P;f5v)W~v5&|PsQ9Otobl13?ZrEGN z29`m1q&yQ_OXftdbj@OfY-wYr=)ah$wB;cBLBxU#=aEx+=^@z}7H!l(6#{jJWt~S` z@XH9mZ4S=o28H`1s#dspL~wsfMm=kvdkASVGnIDfRLd>y42ao<7Q%jblSPL*R1A5# z`lVPQ(1;HD+(T#!k{=r7cUoxKg9={7m?yGnkxbJtM?akB;@KlcL#e|b8vXkM!G<x; z`2v(?LCoLYoX&7Ox|G~3y-PFeaY2qP-Zh6lMUa(8z}?$Zb{CYH(#&(9A?xEYE|fBF z*7H_;hZ^KDQ75G0-cs>`-ZAcx{#Dw!AQP#6a8rbD8~^Ho#F9;F^^`00<)QrPB4Q*r z2NoLfWEG(&IV{*u$diMNGZWAP!&1shJ(6MS8SG#(`7}Sc$(9m>s3%62YkMf$fFEgS zqBIev->w2aL=_u|VV?rE2f{SxVkX-`fH=@~Y{irXWtp4`Zooug_I}|VMqodr1V#?z z;TGuXkEtkz!-%Yuh3rBq(dYs;7IE^mcNi-Zw%|PYOv^}NG$xFI%AYv-Z#;x^xLzBU zlUAYCUhyifMypr?Y9ZT<*GjvZd8U#)bN{QQ2LbXNPuTgmmM1;}V3i51;x`?7StUXR zT1o3(Q-%yHU^Ek%sdZM5$P1lK%M<_?*!HEZ7OzU&U1nFnM5>3S%MSx6rl0`w$gSMR z1(!-aCXB^vP>+;Rv)mEWP#5vCBN;yMi>+)*(&KjB(<@+n54ViT2jm$mOI10SBT+pn zLuj$@(Q7w(y;))CWu^{8co<c;3!w~7;?|6Fu;Up>MsYgV!M1wXo)llC!>M=@p5=L% z)qC&QRogXvsF)4JTUFng<__gkW(2JQ_uY@g8U&uHj$<)_J?VY1rAM)Bf?zM0h!;;n zqm*b^yWWtmM5b}tOHR(m*>wm$wDJ$k*E;Ye2O)eKn=;pJao!-m+3WaSfvAcuZ_Wn> zr5~B;$Z1l`<)H(R$E(o?_>I!Ap#InoJ%%E}>XO5{EN`n6uLPA(fIGqPa&$`(<j894 z0W}N4Gkx0h!#VvpMVDKI3N~V-RjhVsFRx`?#$JM&jT7tR9Oie+nyLL_(uK_rJ-pH2 zS2{5UIoTZ895;p2-o`0#PXG_RU(!77wchg&&G4626m<;f?}Ck~E^Yln7Pjk`O~1-~ z^2-M!P%78kGY$Cx(fQ5KRk3h#v^Na%yxFw}V+7+469U_k-4-7OSQ$h)L*5*2*ET}1 zZoL+1@r)CiRaMF{`6^?ulW{u5mNFZg=NBE@Y6MbvkNe9N*d>@+r!2>G(h$ONLRoCk zu0CCf^ZWrB<*v9^Muv~Cg>&rLBzKl(ZcbjT|G=v_jJ17=D_WuEj)9XttkzW#O#th> zZ`8k;iE0aoi#1f#%6&54E}j@!EaN9CnB}r7g`Dmr2sk`Lz8hW*i1xhY#X~@J%a5Vs zd9BG1O$4)k$>0dvL`B;=Nur4wqfnnBF;Frw!!%$qC>0}4J9!7qchown?RRW_AcX`s zbGKoUF+%|JGixDwtNLcLB0v~sp-}gfglMM8x9dV%hUU^D-LR3MB!9fTAZyrRz_DWM zLdL?c_jV~Od~3S&anhfB!B&njE=HA)F^!~oxvjHQCE|5jHd=PZA4$}2h;U*evMJQx z`NC2)LP#FZ;WZ+rPbwl>RBB8f=zIl`@Gdu9j-%Sb3BQwk<=qgoVFe?IR-)%mErC=R zs|Ob-nqwTvYO$CZx^khY17k(>BAxkSm{TtJ61L&JoLhGk%ZmA)nRLN$8NEFF;@swq z!z#NTM<KKo+LNAo-VV*SLU~c1d)|cguQ@h$rb8i@M=U_e8K0U6oZl`<L_CG&+6Q-P zOiNdtJ4VGDwW+!Bn76tNT67SN_J9Q<OpHkp8m>_sdy2JN1uC`##%ntVH^9qSD~i<| zbF=0e(eLunF6&6LS<?XcPgXgoxWnIu_VS}YQo3$`yyR}l0sIW}cQuP;&`)B4eKzMv zV$3Ah@C_@lJF978=0Ea*r3mjli0po}!fb=)iYYg{-t2Cy(5HBb2eRgdPOe^{Zh42P z=^IVYMCePZ7W30$wFJoW$9}B~jLgWEj0g-EBTE+}KNlmPA7YE9GDK7Cfc=*)u5UwE zw6}&Bmt1Y%ABBJUzVKR3`Pm=6)E7Q2|32EkIEYB?wU6ElTo3>3+o3S~FVBZd+l$0N zf%_2b$FJ#VZ_#k=ssADvLpLwI{ncgjYUrrtpM8G=_Ww21a(ksV{sDcrTs`A>f#2t( z-f>mt&&mA(-T&mSGyXduTc?8*g=I$JxIg-CbbS6-5QEs>f+=Pi-hJEuJ7TyP@jAax zDg`&6`seKa37C?945=RC)(ii=?`Dej=pTbT7y0?mBZdd2*eX)<H=1_q)qmZ)7fjn4 zQr{Z-XYsO`y0_)s@^=8sY*}h=-HiZQYCnDU_MgSe+oxaO(*9mlT)rN-GW2uw=`T8M z{!?ht`;7KG_XiUGy8qr$Bh?1C^&EZqe~uOoIq?*K+mnB?$-kk6<NVjXFH?J8e+~N| zqGe$S_g<vL;INWB>?GTY#UFI}AJFm_RJEk9|2|q`bJYU_py41Z7Z<h9|G?dx+O3qc zY*^PFmA8M5^Y5btxN~l5X6Kdj))42`AIv(Wy)dNqaZh{G!{Ypq&i{x{h+Nb^Jcvti zG+JFt?(b>wM_G4)6gkAm|FiH{hi*3V<6q?Y{gU}Qr26B{&$rXfS!<8ajhxz?3b@F4 z{C>;URo<-w3R?p$OP^&yYL^cG254{H(|g<B@*A+$uyys()X?%@V=zWiuT$ctP{+-y zg+^iO&q!Nyr=xkpCVm)}D51?{;>%!l+z2!zf-ooU%0x~flDH8_nF$kW96Pr}hUFiC z{C@B7sxwd|XDqgIp+!P~5|w3l!WO-_V~v7y+7V%n=Pl5M*if}g3}osJQS<?(LNd<$ zrb5-vZeP8>8)Qf%z3zpN#(PjJTQwUR8Ldlx+HK9k%mBR8nuMME^uY4TlwSn9TdQIT zl)3pn<jGaGItp0j8J96_@9(Dc_apw-%D*B34>9t^GJ(M?V8#yf$ItJPfP{5~wd-7P zbb85%BEGf_ZRN7@dm!MiB(Vraly7F+Z$OI2GMh%);SWB09xewal)|ba^wzfwc~htd z>lAZ+=r+4&V+DMRokwq%$6kTpMd;d0Apz8)k=y0lA9`nh1KKQY`(glE9{`O+Yo0%D zxzZF~<*oL)O&J4OP#(qObWSMj;MFSceKu0CeNHAI?-iqqRqjS#B6HosPZn5a^ng8% z2tIm+`=+^v^bYXY(551qp1-<%E5&0t@QtB&5|cX;51^tL&ef(F7F2dDn{8N;2O_$~ zM9s#hEj-Qb!zE0}sZ!`vq!6PE^A#vRUPQ86KMv1|dS#hXXT2?06F&RaXL%d=VPtqq zu<0{t_<>Ryc{Nc=dWxlsX)=@4c2}>Fr$P^z--J6?TIyx(paIf7qd#{>eAwVsXb*pX z9;oIVLCBu{bpHNsf2IsJz}m&0CRlWMv^vu=pl>>J;$r#f$$}15={X^jM&ARJbA2Wz z=tYS|#@T=%rn_q<{0biZLLc9M=_HF3OUY*8hw&aN+TI#;8?)?--<Y?f`$4&UOO~D= z_g16b-r-fjpgsj<7?mx4w2!4@e=!?=EZo7`=rDFb#5#BVP(k{)Q$=C=E~3m3WC5(9 z*?*ViY4~Pz-mX-%fOAq*V|F4w2D&0nw={>M<Kz(FRvBEI_F!y^&j>k<ms$K%o7>9W zHLBpf7*Gv35ses36ufq#>1iM6sl5pgeq5DIpNjKg2j{S|m+&_!Luy<H=Elk|&R*6; znNrdhhb7l4t3ng9<mK~Qz=H|>&^21k8-R;^qdNJna~b=sqPM&8C)#k3=DmxX%fy^G zJXQJ~(P4>BaXWz|4s)UsD>pCjUH~%NMwRyrR)!C9p)H4rxR7)`R_k8Fo>#%(Hdm}M zTa{-7v?wmJ!MHW#L&5DLUj|_J9hW7G`7$VOvh{SU!{igMFAZ1iqJ?*`cl14axl!&p z7jods`g+w)v0Pbbm|xX>lS(P6vv&7QGqSBN+l_1YaTAz_oLiG~f@J2EL*&>_^BQ)a zyH`DL4}=_lf`p>M?+qPEl`^bUARElA=WXR(xlQkMiqfg)zXWDoEM@8<#rEoxxy$N< z@4faZVoP7;sfA#{z#{T6&zcDY?T>{(uXS1lzs!?_^#GEqfpwgGx|w9Ik2<xl)$@Sp z`DpBAb_J9d+gu*o1}}%r4Tc%1QmoxqFl#7+i*AKsdad!@!v!Y8{59wU?5CKO(YN!Y zh(`vo7aUXWv8Q?|t-4TNN~^3xpq1z#j})twq9f@e;?eGC=0<o5`U##z`6I8KE7P}q zFt|_FzK2)JBa(5+#mvfJP%iSkuf=tX=|H_aK<`JiA)1i3o{(r9B(YVyF$c}WyzU1Q z1QQVINFoi8vhU@LOWOrZUCJn};Mt2j65%33?Hq@0z@HO5lVu-kW6&*%Wg62+?Du#k z(6GB-;=7}+%)CBdHSZGLzpx!F@4tA#Jm<@1zS5^9Rrjer#2w-BUw@T?&t0<4k4>Kc z^#Lj@>D?+FG|nBS6K0vUGs!ElGN)@W)vklsv;T=<a;{h>mvIF`tO6(;_?=0eHR8?v zlW3hODaIL`8<QaM!=h=R;F&tD#e1UZtq;%qiVj+v)OkX>Cz{4|ojnr1xcK7`b}kuv zYu(Fk_fq!t<{;}<Lp1>7(Zoy-GoS+?P>?3(DCCLUa-%4Z0r^JSav=)5nn2tjj0jRi zdFn(FNaYB@iw1NK-HQi{N1yM_XmW+juo&8T(1z`t*i{Zv2L<GZ^GaH)imO__v{zNg zGj2CotKf{4lo@kX<Lw}8q*@jqvXD<Lo7Jjt`B!T@bzaXHW$pc`kIXWsMtToTtyfjH z<DK;SVRIofV4(^vHUew>`#LUXH~vfeQ!6Kcq4Iq`DEdAkvbyPKz|}8rnQu;8=W!n6 zzxp<+Dk0`b%a>!0%3F1ncXbt2Mz5g43_f0x9ev+^li{M=w>=|tWXKQo>{|0hwiDqx z$h?EMBr9!pjKb-fPP^lR1hC-3p(hX>JF$b>&TBmfg$JG#G2eW916iPOvWnL$@~3j8 z(VcTfC&JtG8DJImNT@qaTaW6FOo1+IS7xF%A1%<~Z6nua)*a4GvJ|O4kzvelgixsb zw*8#p@z4HOs{Y!Gm|0nw{$Ve&c1<6dTSqYB(rerB8)!yO;@|h8U#W-@^CtYz9CFy^ zZ-B^#|Lc3iXcwx_Z@_iQa%%L3-qVX+>Sv+!w{uf(aVxPC;Y7idMTQ$|r9tor9+Wr8 zcgEO4s2!cS->e+*beEt&q9PVfKfYwpGQu*o_4HyYyYiKn>!Blo>$V+y_%j>o5*CRK zU4Ti{_1X2%w|8RgEd};>y;O;GQQLAZmt<Hc07_UbmEv^e-ueyTOM|b=R~@!)7~19r z=SA9FfQ^)E6x?vo2{k_p8W6&BhAsT)WX6DMEEahlT>mO4ua|&>9&17~L!-n+a(Pbl z==5sF0Pl*FFT#63IpW{ml%W`niJ5xqsn<rp_$~II)B#?a=x01?L9q@6)pTnz;K|@; zbIpoKP|ev3xrxQAaxW)_KyQ@?9+>zfty$DL-?|SG&X?oqGGtPHb>K}Ojmp~YggmT^ zSh_f(+^YIH;!wnL^^8T)8*Qn=_M50IfN-iP_G4M~&xFG=DqP*b>@tW6?!ID0<BF4w zsxadcA?ZH~ea>r;V4Sr^m=<OvRj~)lg59=KUGed*q_^Q%Vb4Q_?{OoS2tZE)JXPlU z?3pxFar~UpMX(9z>#1~@{cnH=V46W*wdk=#TO(1fm(7#;Sle<9Y}lT&w{koe|FFaT z!J}Aw5q;;|t92Q?n!-SagbHfQ5)p1Gf8aeJQardYeCyqg3l)J<>eWyy1?wblUD|C- zv9L!sXugTkfPcKWRQ0O|@hL!qC$`3S^^usr-KDh|;gd5$Tvzg3OxAjbH?$|==b~7A zRl)1t4(4{@US;PkNIEK{Ac2Ziw-BP_k!W06WSiro0y_?_4R-E;({)i5iH8D|EJQ>{ zhlYac)+S0W`B!%zoPOky0)!boDE8;+Lb=i^r*iWu*UkT*_TD_2&F<?PPa;T+5fM|h z5uxUp8j6G<<^(lU)T~t$t+9q61T`0>h<P4Lsi8$_jjfsLq%CfWme$Z#+xyLZKi}W; z{jT-C&+}Wq-+JERk9V!Cb>%wOb<Ww>Is2Tm&pw~MH^-Sg?i?Y`4s&!UDpF6aZ{UE| ztuRn+#qAp}t?yfB#dHkyyEDN_#b|gW?8Q<CbGd;_n59YtSZ~gHm~uE{bGAi5^@s~@ z^U6Ji>Eal82EiCE&!3C+V$8f=q->(25^8!`FuSLrJ}lv@E>Yf;L-ZR#w!nxnSu1mq zFXj)xE|_5q>1sRT^SBnv#de+1+AwnpF7xRwhNG~qP3%}RFz}KNMXHzUhSVnoV&Kc1 z5BtTMff^zJiu-1~TWTOwsy^*|KD7Gy`Z!{f)fCqE>@~~?Ch-H3MW3|d=w74L&!76e zeF04!ycm?~Ci*C3`juff*Qv*dC<c|(jb=*Z;FL2F6|(bq6v4$Euy*Ke3(Y7`72_7$ zypPpKX?BqT2_Zi$n#CykQxBf<_?U|_xURl0Bx?XNR|_@I4B3Q8^GVH63>Du|YnF%4 zeq`hXdEKYrxDu&15Ryk_n3HOLPBH<kdkB7dDia@u!<Uta?5b46PC>rLd_UV7#E$}5 z2yuBCM!XR<v47e~S~~j^0DnGoUU&*{syI-4NbJLq7Z3yqOaZ7H+MUf}j$4GB%Y>nl z>DJ`~XE*rWm=m}X+)z<m3WKZiifqF=Rz<O+`^+1$bps+-H*E=6c_sYx4W_Z{5>2lB zwYHLb?&{}%*37S2)Qy%}Wog%-#qpBfGEC&VN+a|e1rAx!pBEs^>}!w6KZ+?L@^!^s z5?b3)Bvx0-;NUqkK$aXTXZ7K9V#NqBF#Wl?Z^who53bbs$g%`IOURuuiH|lO!65{7 z;py|z=3Yt`TO)C0-gcc76bOQ0!!eoU3%@gdoZTxv`2aBeL~@Nr;wzg5f?xftZyw(s zVahGrxAo+vjIiI2_h$a|ai{$B<$6(OM_`e1_%tUM7OhvN@R8>a&ruH5B{ywL+mhSp zIX^(G$h2^LEU$-6fjz90RO@|BLlwF(!hg0qDdS>03oyg;7;~y72dTCwK?QIasK~L* zfC22(1G5G6Wpf`wVrJ1vHb!5eP7G;a@`;eEFoG`QUM8%I9%GE~X0)F*H-U;LcT1T@ z%(?XuVj4Q$*81zk(VGS9J=bUWMO5%&<gT05t75MWY6-&1q6m-rbKQYF*7~GgHDbW9 zXoR>0dvqXNvy&JsKsz7?zdAR!9h*HYHTUwzs)Duyt)84JnGkv&{6U5Vo+?Ru2J$hY zR}yhE3Ow;i#9GE8g4Qr#tXWjHrlJqYxfFTw&SrOppLU>M+^(qq{<Wqb)oL|YG`Z$D z75?UDAob!gtxinS7VnVy`X#OT^Bj5R6){tPg@v=X?`Y8a8pJ9r{FW%T#WBCT{!HN1 z1!%zJH_odOuJP0lA5<J49_T|qM-v-9Iqb=96o;4v-`Q_5na&MZVE-J$!`Nxd6L9o$ z!GZjt+j|%KG-z*>whR5WwScTXRzZ^IPuU+fQz{HzmA*ueAAPu8g}JT;E6{c9?OR|* zC7uahfPRkLpw1wJXO}R<-0R)Z!qFw~T37;J<z|{+vxqq8M^Xb~3ZYMo1CIS@y2Xz_ z+zt^HdX7KW|4n~|drtXjeA(-sQ0qSdR)4#N0n!6nGtfQ5(EY;vy&D8_0fZHBgL@=5 z`tqAq-Zn#Dez8Q?cmH$?Lyt24oEhCREiMLnJGo<^62KTDAqr9^Pi;!<IDBWxg$T2^ zI_0Ovea#KB;gNa4zC?3}XdNzDLa^~uTB!S1v4iEFyaXxxeK!BZt4>l8?;Mv{-gMg> z4s|v2^anO=|KG&_eGQ^l;hD<uOJW#ITz?U+=*H#i;4Ukgt<L~|A^$2=U8N#dR)|64 zl-bAsyqllzC1G&YpH%%=Ax`Edq4E_X;5_9BeH0s0pj)qRKj%A<alwzdr_hkp+ecU8 z8<o9@vMzb!-Vlhm9gGRC%+$RjY!M`kZ9jcV&hWPqiL+LMAxlL<xwnBW6IyM^&LMp% zLyE#gvJ>+&Kv;kuGpUQQ-oG>b8-Bk0VI6J=MX9^#wJiDAAQZH|<y0LQ8=n{la1;62 z%v<p%fGbUCNO}x28x<pZZ`<;Q2FtewXUQN|wd99qY-<ie)m(1<)DGm%{|5Cb{qj5a z=ZFD&71}=6fMI;ZN5YF^L~Ho9c7tuzA>{|7n24y_0{=thZGB=?ipu%5yN@PnKhKi^ z<8wzrkPG_17lo-_jRN4{$#rB&<Ce)2XAUNQ6Kcb$8E(dV=t|aRMHyn16Als2%4phb zX2(*-pSZROQ@`{$k&g8oS^=$LBRai(B{;3$JsNQ{y;L(_pxv1zQhcj?Z$5%y{zuTh z=}Je7je^tLt1s$MMR0DPRX-*<R!Zf7y!>Dm%EM@w$8}mH-&?$6*W1`daWhbU+{xK) zgHj+<$b)hY%JNH;d=IIF*-3f^-%OPFz+;|GKJcN&?D&ZGQx(ARW>SuWu8eixlk7_* z&I2QJGo@81tW)Y=SFNpMwXJz&{5;oo7SUj6qB^;#v-Q0=gPS<{lymBAl%7MFd_9lr zu9KACJ4aiVm2R7bq5I7|oq<gaiC6w_;(u9#1Tf-Fz0Nw=_?Bz?nN-CNeXp7I=jMv` zF+1Z=w2+@TP0}^#vD7nTpNQg3QBe7hyFimY2}drGC~8$uCX8`3X_sLbVL6$M<=h;3 zeuqCHwhByGGSGN&&kpDp<CgDjYyogt$FQ=ygT9(aedFOlapo~jI249!s!-xUZsu-h zzdO-~EW7;3=j7h_#@oVE-3fE+MTSB0xJTF5Y9&Gm7thHZ@%%N)*nk~%z->#lM&xI$ zXqLyP-G%sK8rF@R0U-6MTgHE!knZ!H0#57H)poH0QFdlkjThC*Y^eN>6zPtQHox|P zBZf<QO-#db!ASP}ERh?v7O$TYW0@26sc#CWG?@-jAYXxj5f|4W6r-yTTd`d!$6uo# zm=D^DVcc4`;G5mlexncJFIayN6?wXonW?sSYT~CussR$3;DDRE!jEtlGf64x&RCD- zk(xd3SXr{Y7eAk0<GO?~=n#bUkJ_m^;M3oi>s%MorH4O7%0+l9?+DJvLM#0l&J2;_ zN-&7|I=kHJ(Bgb9wgw>Hr;jl|{RMo7a?Of1`6s|!Fi=)D2#2tJQkyCJV4&aFdY^1b zktV_K@zi=S%6Fve>VfC+ryTl|N^|N53Y5<rcS>5<Symb6{ja#x#-CE>ewTSzH}EH5 z8DzbXA;Me`ZDiJL=P0CfM#iuw!J>^hG4T2xSH^AT%Qun#9aX2(t}JPN6e*A%epv4{ zT3ZVTqutGzBpy6KJP=`k0pnjcFwvxy)GaCri#7U%zl&8@ot)msi?^hcP|nxlB690K zK&oJNG*K^|yrF}ey<jZ3q0016fcqzxh#zKJ*et9eueTB@>8qIVJth&WXK4k}VCLfs zbf!8MPOKs@Jgc%>X1ICxqD2It#^deW8;84F!p|oi{{+C6e%AjG=&vo&mTUPHdFi3Q z#O6e&r<Te};?g?tlI3j9lnn9O8E(<G%ddHFe-8z0WQTw*^SaCz-t1*NW8xuRG=fC} z)>PeO1_SN;R+2?f=Bz%6gQi)^Uv@4s8lj%WzUnkSeg+`N-;)H3iZg^SWACmSGoqsY zqKpa1^pi69hO^Pv!EPF~AI)aa67jK~>!#A}Z%WJn!+eD56}K%B{?9G`*r0-Ow{M(9 zUwFq-edX86ekPBYx&)_m{G2D_SvZmnZ#?&V95J-WFfZepaLYLHDw$zT#=Ij%Km2Zs z!5bG9AQI$o8w$kMqTKkP#g;&pwBQgMuz1dmTF}6$q)E|kS=MuRh-)6u!7H$CiEOdE z&eYX94F9xXex1wr0a&JuCzf2Zm+R+}3)=d_K;GrTU6)u?Zs&Zkx}mtNvmO#x*lAC) zOps;1%&%HdVJ9`kgW+vPZoAyEM|s~7v?Oq4uS<8St^uW2J&^W(iX3S%7qpnHVfivQ zkA}by7z!H)`k#DxEQMx-mC8R}i`)H-z?Up|-n7+AedUpu=KJ*Xztqq8fvVbEUGp@e zfR6urlli?7Y_|+bC^Jp`d51GU&ASTwkaSq&7Md?1QH&2ue-!xdbTfOsNS>;@c`yV# zK)fUfdx#Ao=M-gOb23Cw847CB#iD+yB9~XToQj%UX{@co-DbGYcE^;|$g`1}&AP-I z+G5t2sWg>dhk=Y;`)j&9aYFIN{Gr#+Oq*=bJoxdQ^h50w@Wd@xl7=f#*~??{eh=<= z+$kSrvTp#NvE_YzMwjM+fqvz!o728scImwbr{jmY6M<qm!yj9-06QBSX<nZ}2rf(L zCYBXOZr=g@uryTzAE%!=AHFcz*L<sE`|Z{Vzt^s|<$-1gkjP|H?ah&T!dv&^p5ci^ zYspZ`f$}p&MP973T)@5hY0b3Fz60$%@QdR!rcos9D+s6FkMWF~I|JbQ=~2bI;8c98 zuz(j6A`b)YQd5f{buzGDDPp@PEHGlo0{3Qlnv0AeoqZo~7pH__kuLEwqOhO{uP7c$ zUW<G0B6OC-31`EzBjxgo&%ol46osUj*+-nV?>_$2B3W}QfQQc4*i{X~vUlf8nuH!X zykpBe-Gp>lhW!vdI;^4<%iq>j8EInHEuKu_%#nURVyGlzzpt=Q%Bil7{xFc$E|Xlk z|52Q!6(OVXz#x<PZt8H_3oNc^1@mfKzc5ZAGsnr~3H5z?Eua78Y0pB)qNExzN6qGZ z*}d5m9Rz$BT8JWfZ2uIM>4Z(PHKPmV8yR-$Udc<tc=&t~=~E)H)Ef@8ZhlE=HpEC} zL4^vyq_Q0Clw{i}tvLfO<5kUEPAR%JHl`=YkAf*liPq(8opsr(!SCqT;#z*Z_@6tO zx8Cq`01}NxMNMW$??f=~^891ni0pKOeVn~ccekXIK6?MCYf<thq_xDzYQ_Je1R;`* z?@MZ0#QxaVYlpwx{sRKdl$7lwFHra}h{zTD2HBDpd!9`G1n_G^Z3|}fS4QFkwp#o% z5^9bWHy`INDHWGZ8yGZoFiKS-f_seNqNARXmXG^k#=vX7?3BV^YEO#zKSAHU)ASPy zc_nzbx0m6eOkhmlN~;!Mzy-5s1tBigZnpdU32<dBKwo~*@xEqrS|ko7-shyKx^&#_ za_g|ptBFBKtFNjI0Dv%9yqGAv^VTG6es}{S`ArL@F;a)A8e+iFN+SOR*ji3~Jj=C_ zJEAPbCg8wr<|Eh+$kwb)I_2y1C&16E>CGLy5m3m)7h%Jcg}NL|jUOm>XH=I-W;X(i zEAeJ$Nex*KU;!v;hJ|0Bcq@K+w8_+Rdwx&owfXY0s3|RGK<K*@BYvU7Ft9k{Z6|@I zD6xEP<L6Ch;sgr`5b8G_h!$CUqxntU4wxEwzw+F48!E|76#9uc@TI$3cln5Bo3oCK z8JdpN6?cbVHBvl&p(ubnN5-h<{HyX2vq)A*(g&xgg|4kX;PO8#ag#A8S_a}CuQE=L z<!1;DxQBY{{Iy&9(H8$+nI#;p0ruZIbh*oXmx0>d6IM0Xc%xrumlLI_^qy^$@4~kG zUTBjF|K3AUZE^<(>sjC*bL*dMWMP3fjVvt=H#hmU{K6%?n#&UwGh6NO=L9}%G(ECV z%SxWj=D2kH;-i9|*jnI`>7%L;t^}w`+YeG{pjC(9u2vD2HTTO~2HMw~ML*4~Jlenj z(^SXC);6PWJi`r;*XRLEh>`AwQ`V^hzZ_1VnpG|q87#kanpVADFQq8pg+x9kueWs0 zN3fb6xZ!^J9=kYRCf_~;?6R%1&gZ@b;Wbi-w5G6-siey;CEVP~XUHP<x~~)SJ~`x6 z_?;Ix$TWc$RQGH6R*q8ST}dK~=KWO$h06_y1dGGq|4v5vFO;J$FmS}mu|l?Yb;Sm& zF2u!OAo3(_FebVo<WAdYE}ELThCyfT?<_9`3#A8lZt);{PCN2HFb-yLC#B>^+$8+x za-A)H3i)QiQ_sknt8r8xKAhZINKjSk>uS|pM*vY<n3<x|FKG%PWY)@p{(3y4u72%( zIrEg1BF-VM#`1un@nadIna<Pf5d_f`)0<L%?JX|=>v|UkA7xn~n@F;!A4F^1@LRbT z>+xlKq01rJw`bk2|Ltx)x)<2D<=R!^aETDQ0FgGg+g59sy<wB#=9cuViuU#UiUHRF zu&|Qw=t6aYy#(_h0E|r%6fjb_%&nWf4@=9;TSh%&iTZuaI`g|yjLFJaSR@F|Dbg1y z^b<2N$=>3nMLj5M4OY^#_~fUiN@ZDm!<9(({wiqoKHt?R2{I?JWvRk3;E}JqjFvjn zPZt6!OGvk`Rz^-|HlRgDpLERg%+8-wxn{p7e0%LM;s=l1DZ9!5;B|LBE3_2@#d^e* zifNq?u}Il3hvvysm`|<nw+l-zEj~%QQ3`S_Q)-CfZSz@XLBHzBeR<YY$=C#OEz3q# zk7cwQfyS*agH6KBkz+lI<09AzK9+0+n0s+#YH4i_w`hEX*y+PlBeL?xg>Af7)yq<7 z;F)Y3l&9c}H6NUu;ClHDM+znNA}C1uj{x1FBRN9*xPaLW0+VMUtwzwd+7lfDQ{iW} z(LrY<fFO>%kG}8!*Gogym<-Qy@Iy&QVX=js?1L(CM}3ja$}w}KUb69=NZzdx2=#@@ z3s>!p0_i4G_Og<D`}lz<@n3X8xSZXObjKPF(&ozCIB!3^xJ~#MdFekU6u0(P@w<xr z?(qDH460F_=h&p_V#knm^NEN?iXh9aU@~`DoEc`Mh3IMwXOFvgLqiNL5d|H-SMq?B zb-5osA?~a44#l7EeQ+F$?ffPqAUkT5P!+>!p)<%jfx(YO3j3K^FE0!fC_%xZl|`GT z(Zfb}N{~;ky69tHT~i95L*API73ju_RyC-IY2%mX)l}|B6R#XR9WnIeOBp7g&I^Hc zMPDi#5uhd}ynvHZy8%54x8MG)Xi<KYjkr{KeueeN;>(WMz+e7^=DMz4Gv6<mpK?te zpbhNzi&bz)j)E*&I<)Sy=(NL_Iw8Ug0D}qKsHFgmdx#hWAuZ+o<&ybSA^Kr-<Ef($ zvnHdRZnM`mZ(g**C~wJ#LxnM7@P|O%SCD8QkIHe;2Xkk5gmT@_!eJ2?rgdK*W+Wi| zWRaX6Mt>=&ekMnX<ID;?ijfy@MBRPcChRjx?eSlJl!u3Y3cQ;M`2K0S=z<$Jtnha% zI%n{Dr-p}km&>||sQ~b(C>z!jMb-~9EN5PikrZ}2ZORQ6>a5D@8zOAVIX!Lenz>i? zcsbhNC_ukdYRfDX4T?^+874fvq;%TNRvOIj`s0jK5A(N=bV2ePhIpBcp!n2cZl}2& z|I}zN4YlA}_u!Jz8Q;2Af7(NL$*Dargq`{B+UJ#yj&}hEi@@2*C@bBkqReYQEV&5) zu5(uf%sYOjVk_obn*4~`9Wq*veM*!2h$vySqPBQao4QL}gOw6jfY!sO4MhHSx!;4! zb(i%H8Op4tvY9hz77<4}KBaEW@81U;9DY`|I>(UdvIsq>>UP3BvK(B$SrnhE@<LyC z#8kp%H%vj71v<irwiT_{pu51X{g4ah2~AoE-kt6fu|%NJR}f5w(AbXZ`A}h_)B<By zQ!-NQs&5fOueCT4JOLkHDsNO*&Sl!zbIjth(o~0D@&+^MdU*Dm;-(s2Nqkq6mPjD} z{__800ihD%=g-eKH!-3eD!1HC@G})KR<0oxE6(RTv)^v%^coO!9r^X@lpvcKX%7#K zW_7t&s-~MXY3=?X5eAt{U^^UzLP@jy1##p+qsm?r4I@eQ&9&bsG;SEme<4MwiHXw- z-;;|%0psNC_O0u<KE?w4I^>q)&rO5xI&1YwYNPYP(eSFL=H9&1C#OS-?zp)hggFor zAT`FUEqS%b%bZe|Rvn*F7%G>~fC|exbFSZRI%D?e;Fi(XhJ;+ACjMN+4}s@L|DSXY zwS*oc;2%bzy>-IV{Jurcv{h0kyUbQw;$Ix{$k><l9hg2X(Jh%Umb(JI1PO!J3-Q0q z(7fP{_YQ}a;ft&CTx0EHsaF1=jWW?p>49uUVAhbUj6|mp!P31NUcfEPm~v;uD-pJH zRv4!^+}^qA&tWDCe9(tn!{3CaNE6C8<F$s3FIgs33ZKTX3E%hW2~^#Kg(TMKw^_#G z+a9_`Ti$D&j{(RAV!{WnH*q`gBuFb^6A=kj`j%j82oDPqckb#<x~}M?ii^nFP~|2Z zTNgF?BXW9{jmD{(Jn<%5Sf1R&nw{8FH%?UtP`?$rVKL_ErydAj&$@M;spkpg=iu6D zVKXAeJjE>5Jy^p_;q4g*B6DV-Ja{oY{Kyv764)UA1Y+2$7-=Q9oYe)8o4H93Y9no? z-K6<wBQ;cEXx>y$KCPp@Hqb)-X$4bs$k!)@4x3R*n@d*bvD&vrIE;FPKe<pyYt!k| zaeYrK=kjonV&)KwCIgiR@)5Gb9X#-<`0odYx7(a=1U@QQ|J`O3K+*OU#)<b)@*Hmn z#>oYJO4pp82piG98ohA;_*c!negA}aR#EL+*J3wQgypn6Gu>~Oolf~-L;DW@sng`k zw?_NPnJTol{3G2&f|O9spc7lH*mYaVUhbpGXP!OWF9ZaH5orP*N;bwl*VhR5;d*B! zD&4>*=+=wG+|T6=wp7Fp*aC$gAe_|%Z$LD3=V;4yShU?+dF?v;ML!(?uNwUPYVTr7 z6U$&ef0=G7Ztkyb@iBZ!<GEgmap2^%^5dD1?~ykB^KltpA9Wgax4({Fcx%*n>cTO2 zx@gQJ$6oF0lF14sXb8t^Cwlr%0L|%v2k66@W$x;pFjyXIIrRs8eIj!g|1BoHHZW@O z>xz_G^i3<5L)uDuTm+=HyF+F>3mKC=9MeS+0Pf71<L_w|YSkj&T&iaZTG5z?u-^`M z`XY2KHG{G3+P3eS;lX5T<~~~jJ*3KdIDw@osgN(is17^G#XGNq5FtGL2-`4ij%tMj zLfjVc5qTBYnK<tqEL~WOjp5xWn=KlT5dYS25O(gwzI|s`!H*3n4KUn1e;ssXF+}3| z-3FaSYx>T(t0V7~VQ<1VE<OmN@%?zmviOI9E79JxfKx-M1<qOjbIGvEn66CyGSAoA zz7r<%lQR2J`b_maJt&uLrgUf^(TxOUAV-PqYMrU88}%*w+&T}&c|-%>N>M!ke9!VL zN3}yL#?Edw)V*>$2wixh{hn$u(TR3n2|e|!BP1|uF%uS=a<{8oWTjI3%lF!jvo;aZ zQAF59Bn#(H@N$wc#aD|X`G^OQ5_=yPKT)fXDKp3{>}S-XUKF;B0}J10&7L7@2WLnQ zRrLz@9GK#mANG92L16YZmB^`0K4odz7NftmaJnEL2_%30|Cn<>4<R1zC5G*loUIAW z^_%ZV&%JiHk4|@b`Sq!W7`NQ@c`gnBmf8Lvaavi4UKx!_dzkwqh_8V)AySFC$^5gU z$E-aAH>a7@=g@}_{}5EEIi28=RoOj{d+q-Fnq{9+P|;czvhBv#?EY6TOT$|d;tqHO zQnvSy*1hGdGvIe~ob$y)Vpo>X(=es-W2wK-Vc|3<saiUcYU{t^pmwJHg)1NbVkSZf zxHcjWxW^~Rl_NiPR(UAV9gF3HLtgdFj5VDq58ULRet*?=)Vd4@xe~wDVa-`wk=j}p zFdEQra_@-DMh|Djp3Mf@zz5|(GAgVLD=h&7-b{l3??-@G|BNBTF&x1v{Eoh-u=KGE zOc$3wrHc<NrI}|qPMQyPIV8%W;1P?QT1+vWIZ>=Uk8y7#7z=>N_Y5DarBvB2j((4_ zX`f)|-Cws0;sS2o^#4dnpJ9urx@3BJYd%}+mI|Y3k6NVH#lT(ta)53H)Lm;_`_*ZH zE9VS%=~g{M9XW}w+<+}mEgniG^e$v17Pzj8&ZbsvRJ!5!Oyw_SyZ%SVqhx;20GRm; zUE{IN>}uR|q|uT7giVGfZFKPC7r1Mt(#^?)=c(`;asMl1=DIMKVsZbYg%6eO$8~C@ ze%k#iC$pQ=j0GA}BRwafIj*-*v}YPNgSVPg&7yrieC_E}^H=aJC>EPEKS<;dHj%2e z%W9(P82g`FTIqSd@Y&>2JRGC)AYaM!tI;X8cVD8Vq@!bN#_o04Ku>@EI6ZYnfH_bd zw_J2Xnk3!I(fHvw+qWEq%U3#6X>e(Z%~ObQ$6_l-=&^>!DT!Lur30;-QUDcSt3|Ol z>CVjBVZSo>E`RJ`YS10kk6RbCxMuwQybL|~$Z=z7^&^Aq(vHb~QhcGIz3XnSnc?JS z=)G5S{Lg}IG-s~+1qPRWk&5{dtzim^Fk08xZn3FQ#m_}8oU=D@7vRY#FKq-X1PYiY zUea$9GHMr$G>=H))TJweGU|p7Ziuz18|1t`h)KwO{}F5%%`($}_EO&>F#Olblw9U7 zDa|dN>1qaYc8fc<`OOb4)<b{otW*pAwU~pXe&%|j$WuN*kBRtE-CiY7uI!@w@wT?& z`UGRGozZptNN5p1N8+6j<!Zup=$n1~aF^BR3$kJl3bX)K1ln5zx!|k2<|$ZO0`h9X z?8CrxT6WeATYpJ4-WoV6#dkrmTn9lp+hJj-u7e||8G}ACDR#<BXplQzT+*|cULQzI zSddVE&r>)1bT5*R7`>7U*Ld*b*StOXp<m_vw)z)ZEFVcdr)u_diO)@@M4#irV<~c} zCm=aiw}az$Y~Qncp@NI!oT>Q4v=C;v2>RGxfy-xDh~*^HaQxxpriFS=_7JOVqz<a4 z&}=OuM5swa%xmt(59wd2A8LA=O3oE!^RSVH5Tm=Is^r%t8E+bg-Q@yqw^l|8Z0f;v z9JCn5lpzlwA6@~DJGIzEZ)1A2Lee&iZmnMX@-VL%sjtJj?GPT!_mjA*eCN5wHmB7e zh$7Ma)0LT<3p?Jz8~F>FUj?lPyNYHm)2y`y141PiWZHOrp)Pfo1zMh|9JOTp(HZ3- zQ<u|>P=;1~8!@-sIKN`*sw^K~|Lx6A;0pt;nX*0~Cff_4PAxmMA&U}#F?ZLdHJ_U# zdL!k`3~Mj(<@_0*c!!_JG^l*qU0G{zi{JYb>vyAsZ!~#$o65*hEjz~OyyHOd@Y1=J zU;IaCx0qZA-0=+chd?GUm_fd;1jH<TBe0*R+%m<zS)kgt-|XDg;>p80j!a~`nZwz$ z@1V!D@2{Rr7m7b?G+jBa6v*`S<i(^k=6tn&^5gTNkA)iKIxGC(erWYL(Np~^U$l>O zgpOAl@XHCpjZ^rjrWgb{2gTG2Y|Z+NgK{Rl;0#lpL1x>jSDmaPd;;&oHCUc>a`dMI zYhRL#e<B|-wha33(Ld)Oe}W+Vo0QGthAWEJIm<TxNDKp+6hsRM18<8h=l?(Nu~f1y z&M8zW#DhIb!zxblcock(e9%)#X#rF5r76uiolZCXx_>VSN{?q~8RvSLrJpUQr#wWY z&vv7}7lrw~B2BYHW-Oa30xRNOA<4Ciwii(v_J_*q&}`=A(ju~vTjHjSZb}Y}y@T1q zN3>J!#OhCgk@HF>b_@<KRp!uu=pHF5o^)I-=wZ4T@e_F5GH@n>vlaz1|6bPDt;J3< zN(AJJe*Y_#{;)iHgbX{GXT0rwTm~r8NPhDO5WT&}{HA7q74-W6(c@zOj~D;CoVFh& zvx!9M+trLVNKo}_jQ>&kU*)`S_5vUH=q(aWPddLbe7+c~eMrApvGVpoH>bZ0wkds@ zFR(D~WwmtszHSPn1dK>1jDemUj>atf{hN1tqASI{V>u~_3sYKK5<ap0`)4__>iYVq z0rRZ(mf!6&aw|PoH+pVLIygPdF<;B_ytr+(6;T>-yJFXJ>m<7N=ZCvJz1;=3zF$nM z`5^Ia+?X=DdJj(#2&_Gfez?GVVb}TPN&+xMkQ7YjYxoge?<{w<)BN%oKY~}blFv34 z5E~0BrRNl{!{{3LtPWH;>BlJkolrOkMHIcvdwjoW>92BQ6bm!C5ZBn6qqKj&QNhGS zIfMM{)b_!`+<8M#dQ4Q+#ix`qb}|hX6eeY~&+fZCRC^)e-*FmY@)WS!zo0ngcido* z$NvK7s9V0Q$cCYd1%7JsZMHQ1oUeXnvMD*k@&nV3+l(LiW?FnP(Jf@v<`GvX5c`3# zrmKG3eDQbWgp$vPlLaK#Ct0(lTH7;knsxe}Zbo$fK16ga=No7o```L(4OeEFRL^#e zxUKZUQ^8AKXriIHfKBS@ac$MZ;dX_kUV4VYcO9w%bq^Nlfvs{Se9NR2V0a6g&?|l) zPUaV1y4%}tFVhPqdQ*#`3%RCQYa0Y=IT|=X$^7`b_cDiVwKcbUEBoS2Q1NF|f7vVC z%#bRM6*)gXYlOOeEOsDdVJfVlM)!2Q*%yahTZ8;FvrdwFG&gQ&Fqv)U;~>MRlx@`W zx@ynX@j$MN@k^#Ru5eEnK3Xn|l|Gb-VKtp_%Uwl3VyqBDQ8rsfr1t8=T<MUQX3<XZ zSUm3bjla<_b^qSn6D+S^yLa3CYXg@F#DmArr@nKvY9nJsIR6bvlRd3Fcs?m_=zfh` z>!^HA)!&F3<Bd4MHL1ia1~>{z)?%)W-W}Auee-||S%&mnq)c}RYtF$A9f#A)9EjlJ zDz|-4ugQNW1wzUwc}qv$S;lh^GP%c6HL|(bFWS*56F5QZA}-ZjrvvilJ4DfZcTI`d zZZz(qD!mf(`=hWp`>o|8`g>a32ksFg*KaBPb;B<UfVAnD@6t)Cc?&)G`vYso0s;Cd zKd$>HUcs%N&8KIl(-!8)Rsj^ClT!hEP&)EA9LTDD*^>`4OUDTXNUICeNuob3Ns~;p z)1?1t8p$aALN88}4-b<6tERxF`gyx``nS{D55<-I4|b)}ztyUB*@MsMuX5;M7k&DJ ze=sQCB3xYa=^gw|R;;ci8isZ5`ug1^75yzPJ{9R)wUQr3qlg&-%-#hb7)g7Ixq4#> z<Ai}F)`eC5eFjE^bgxOL;ioBRI2$mDR}Nc-%4YA!@r@}r^VSzvp$#wThF0f($(0qu zYC*sHHgORMg)o@2^uV;%-EGB8AX)`<k%i1VGXHEa-b6}HH?xqDBFSvR(gWJE|79-D zdJ-;7eM3pxNtJJi<#$|ujJt9~vdj}a2g^P0u*y4Y&8Y#WRNRz6a%bdSc}_?ip~fj- zpo=N%t&~2zP=P_tMbTAC*oqItCRu8XLabDCW(AdtV!0OAWmnBDN$0b)&O;h^^<kzN zfICC$+fegN%jX2iued<~9)}UieU7CM&TZMJ+F%=QRwkCS`9tV^SeToDnJBoRN<84+ zp@cYAA<$zF-ERU!xvAz;F}+{0jg~g#&5p30dx1&vjE`_~Dg5aJV+c_@XkLHPl=1XV zW*+HY5Eu3+vT+;>rp!a5v{?%OM{k&k0P~I7W#5?UomOF!?i4jbgIKEy1OnE`o4Isn z9GwLSA%Yh=UuIW#)GgXPj$`kJwUShr1j`W4r`=OVSM)9pTPAOxFdpZq3xHq?36Ohq ztqra4C8!6fYodyl9w*9Wj67w!<;|{KlUp972;8)|Ll^q3V|J!*XAbbW1t0L(4fv%M zL-YC=ysCV{2*$N9x+%@P4FkE<$~q}Fpz^rDG`~kxDs(#k6M4oee?J?NK0!?n?0130 zc_9?%6qi+!tFZSP<yq<nnc|Q9dtJm<-J_%Y(2NDd3DXJJ#nZVaJbYn1<oFqnaR(ZU zCvbcas>GZ{@3R5o2<1|m6Ep}ES{*jfoS2zCMWHI@YDUPm&xU?od}uO=)8Dj1xFC?h zV!6ipv(|Y@fFe)!n>Yl*B{5F_9nKr=YlIV%Fcxh5Wo!&%bK*Y_sf90Bemf`4im}V% z^+<Nm472an;{&}dyFHv5CzEQC5IoSXpF#>Fgf>itf6uvr;+`($jITP)z6r?l`*)6* zmFM@kgWg>mR(Q8(T`|}XfH%4LsG%SfOhS8$qzv51Rg}pbbKdVf;k=Oc@LamjNp6;> z*wow#<sr(ImU!DYY`-=Ub{5GKAP!K{&<D+k<!}R{lHC3|M(9|W)D&vU`tEh#t!>*w z#V;5ZBg&{tk<~b{yAW`2cIvMl(6LbGVj!;b^?%e*=aEEtFkMwE7pMCM&vH}Sa+0$p zHv{gD^4s~4s0-g=L-N#G{zWoP{O!0t`9n=2?)?(rVRl*g?D;<6kR=~u&^Z~qR}}g& z3!dzHFaBS+WwYKlJQc8F<4*QKirxwF<AB$luN7`$g7&B;?nqY+=AE@O0%N6|<SzL7 z{qr^7mn^wjc=jy*tUE8J1c4itDYH24B)RcJD<5~~Sul&xyDz?Nr$Gkwf!rL8c2joO zWIYM!9>L*B5niUUy4)NejDp$?YYC#5@>TquX`SKW;+IVWh$OMx=6*wlv|-P3nUw+G zdH}Le7y4Sj^5u?voK=uBAgUuK%1rCCFza=aNzGYCaRo+H_nURzU|xuySzeMon`_w+ z#7I&8^j$B<rLh~r;d+E!sxOz+Z97o$IBFVl-;il5fYgNov!Hy8_t3wi&#}vsWx&JZ z>9pq(R;V)SXg4=sWt{jJg2hEyrmVvyC_yEj)>@dNXx8E<lA0zh%}siv7?s`b9>Twn z2N*=HcyevD&)s=B74HF*3p)>a8Bt-P+G=+<k-^Lp9{)^OoD~TWH>47LT@4WStfg>; zGofqQx;Q8`B}I~Nz$)GrUNAZJNneCWvd-}*xCicilXTbK9>b91xp}$a)(WvT;AT;U z!aJ{0x%m}(T2;j?!F;z^QaU6pdvuMG8Mq`TOT<M`n#`y|m7=S~1$#>Xz+}5+DeJ&+ z9??gPWAGhGWI&mi3UfJCjh66X9-Qyaih7}{T<1Ys%Pupp;g==Q!6y<vfNLnU!sCF( zERuh=^^Pc!z<S5MsH}EmlB(4B<1ZN>AU}$_YXyb1D@CXaSGr0!F(&a=@w&!2d)Aj+ zRT(<GaT@YP*VGv3>DG%_mD;$?f--_XnS7EbDT6)_Wt6n@qOTJTL(+X6kQdDZt!;NZ ztQNyz0%G_f&G|E`MF4)MevyU!I;4vO`0|pgo!xVXWEsO^6vELIDaKF!qLWYiLw#<c zC3{cLTsKz?ez{R`)D2bk<lv4%o(x~8N9vRTJbh1QTAHq2&#p?eGJ&$?G&yfK5paS* z(#_iu&@0xo0v^nS#~tFm0m@k$!0p!4V7m*-t(jvQ3vYVn$y{CV@lRc4d>BDf+WAF? zYmwotrm>=*p2qR0SYtEX@Vlw4UtU4e)3EOXdQi8JnX?0F;_bZJ80!TRNIjAJzU1SH zKrvMXhQyxDG*M+cb6vEw>C{`!_{xy{<`)EExGuiW5}WIh$|xs*oOX~yUlKcK!!$gO zP2jr7NZ68bZqL-kkW+5_E9dEw9#1`6Rjf*a?$;?@@dm+1Tf7{KW(0=%8K#k*!8US) zq&c8J>Up8iPd~adb8;5&G&R*Bem=OHyAB-tTEohkhwnj_S7@mPeKpAB6Ro^~@^ls9 zQUSiP-MTzP(I30!=NDhWt0?{K-rrLRQ^aa}yl0-L(Idli%wQmSEH~b{Hrzu+vi?x^ zklw*2J{k4>e1&MHs}bpA*(e3mN$hjK)AsDf_5CJ~67{~m_x&6WaqNi~h9$MydI%>v znW;>ZsQ^%03U$Oployi+QfwUyHaxfh;71R%p0&`(DN8H#@?<Th`~CaG1sLp`&u`21 z+P58yp23HqY0kNp_PFc8ZRgUjF4FV^f{$^RoQQ}N;0VU}K3R4n-}n3o3Yq0bLLaCM zSblWmn{<Ly48qNIt+s6`X&`;q-ZZ1)Jg>eZqpTYB0r}~Q5Fr{El){fJdtmSnq`5`1 z$*=(s-Rk@V^UV03OC)A=u6UKtht$I{0|MgHsFvj=;^xzQ{`BJ`Mn!8o8rb-lOW-}# z%>mXGn{t_&JwGM6i2!<%t8FEYb$!QevWGJ%@CV-|bqgh>Ng&ZkN_vofYZJtA0DoV9 z%+D(?gayz(WF?h*Qm(u%W#mr4L!D-jYnSt?0I})De+Wz$X5c5>IZ`C@#;>%Eq7s=L zS7V*4N^S`^<8huP)glAbU{&MUSgb+SwR9iTr)bYMW_<4Wx{3!AfaS6DGK!ZD4Vrq2 z6n%fl>S8){gX;=I<!t39>yvvc=?Kk??AH8mD7t&_BmgF<Y%CL}fIo?Yu!&yo0>dzG z2U3VnohO3g_hY+kavWs{Rb{#qRC=A^%<oh-iumY@*s{8%WZ3Xwe{%|Z6pyH$&~=$7 ztWQ9%9n3CwqVwZeQ1Pl&X<f(yMVTQZwJ8?1<~ZGiAo(HfyF3WgezvNW*0k0&?1s*M zl>i)#(Xh@MCkIMhKUY^G=^ET7#mfUu5=}EPf{C`0qT*JFs<8$0Z0usdxFog|2DCY< z@p7P8AvUS1P}~Dtz=D)8+^>pthAyT9RI5MQCm2hVi`cM()V+eK=8GZa47Dogs#un8 z^kKHH&~u|c|Co*m*=v>4lCp!+TnccntcKY`(Vkj6uQhVj2iar>wyKeZ4F8s9w$awu zSF{w;-gtnP<kg<DMw!;m@pfo;%#?_2)kl+1V(Zix^q+<c)7a4I0jkr-3LfI6k3zM` z31G4f*m@8)IaLoWTU-@QdPd@){nNkzEz0Zs+(MX1?-on!eLFUdR&+Ha$?FQyjHwGK ztr|=TMc@Z7kJf><)2LQvwLWeG{QNsAE!mYe=6E!~qpv}PZSME$8R8mWaT>ByH!lcm z36bVee4t!H=zv2#$ioRNf2`H@qEc=QI9=v2M;wP}e2iy<S&y&HGhS6xvey9fE9hFl zPQiInvtfi=pmQEva(t}mabrVwKP5X8aq%pLPDLfbs<FPNyihs|R3+Sk>2j$%p$Z<w zaVb8?B4WYDX;3Qy-~q6}#XOE7UrONz#(-BYFkJa(OwvSxMAWVpCkX9%4P6!s$>W1p z|5H6=eXxeLXa3B~+@!r=3+)t+^)gYDxyWcb!|$}|V1glI^F~v{QVNGGvp{ZDDea^3 zlJ;@3IRa)<#Va6|WKad9t15~|3GaEW+*dlA3uKFySP}Dv8sni!O;fiCf#BC_v(9Y9 z_(Ks`oXkk7gNY>`dKqyM6_(3hCZ@u`pl4whGTJ<==v|Iw`I?5wSde~DnF{GPK%j=C zzgv}lM#6fyn*;z?%;xVg<yz?)w6zTsd4dG;J<5ND1QSRiORhF~)%EM#5=`em8|$P? zgEq}Oe1M(jEGGp>W>A4APeH!95I_6uv~Yf3h{LA=7mvEtL1QUUQ(J!Z2`!|MQGZ!9 zUJPwIZ!A-w#~N!rDcTf&o3)idXzi_0TTHb{4NOua``Em!w~kUQ{*M{Y#%HK8&HD~g zfbpO6i8&-bm_@sT)id^S14z=9;^nmfp7sxfKlT<+COJn3dg+sy))A3CLZLV&$X}){ zv`uBNRUn9L)p0j8oIZ_XLm`9xNZ<yL3@HGauG`O2LTN5|)Dw;BuS%rr{7{cZKGC*v zzesJdjN{Do8hzl{gWP(jLIg$0S<Opqzz#CVwo!ur5Y2CSIUN9V_#_tSg+vI!v*cYx zt`<hsG9g4@00q7w-hR&1jdI7#anCpki>=ywiFnN4rZTC+rQC5V2{cPFHt?0Na(RFu zvO9oDgirUleBWtaDwyB2RRKtJw}b(6Xdumb8_c(2js=k<Od$ANkC(S`(&_3E``~hF z^$;UlS<VgV!c%aG9%z|U32ANyt6|`&?=a%~fxkDD@Gj*Pko{9(;cR(wU7L+lt@~DM zoSr!54Xc<TI5i;Nhxe>?$N`ZftB_>V3s|0P$T;Nsv<3Pg2)W}`DxAwA@Aw{yCsqMo zo=b*6Co>b=Z6p|Et}IK>KE|58|4%ZYF2xR|pa>ld^bDK1l?c-{AkyGe-ZIk@VW+V2 z3nQbj1Th)VS%+SLy?E?{eAIGYD%DFl$(b^m&3h#xei~NX`OvJ%KgnT-;S#J_lUSIR zz{(`ugV<En7VR0l587=p@c-Zu3}7-Fkg+rMdxt7&Y)~nhd7|Jo&aIH?<~nj)w}k2G zaF?CxfOF@jghojXtbqYM$b~58M{o&a4lmpZsl9Kdt&wrSY6Twmi1g&qs>kXYr^SQp zjWBq9M0t!Ia9PQB>JMY;SG!a@X(R(y2_K_tC;p*h#vocQQyJNT1b}(|X&7UZ_deF1 z%S}pVq)Yb!7zcp2yj0q>G`RQ+<|L-XO}dV0Gk%l(&Hn1Y7|>`3c;vd4!7y%~OjLlJ z<WA<Xulh>p3I$7!C%~^npj=yv60lUL@?AjxH~}dz%(#(L;u9+6`(|_Gy=YaGQ%G(i z)OA<8<037Glm&sWWuwhn@N7tKq7RpwSk3_N10&F5yV$;kZ>LTqi=3dD?(>gmQX#PL z`N(0nCqrvPZ}!>q?|KK#v8HoDGI#&Qh^J*UPY#=jf5xh>?{1MYuuJ;Pl`P1b!x}lP z>JVP?)Kpd(kJjt_7ZWh*_UkySYvuTeMJWrush4$ex+|vaP+YeCsO2M^B8*X9(fa-T z#Mp~QJcOI&8dTZV6c)&;oL6pQ=H9WN_PVFsW6ViW5f4ve;P>@*h2duC9$=CVWC46A zhJUjr6H&E}n5cdMr}w*a>}9VDPa_g@L<2|1V8-%no>e8WIA+5_E-%6PbBl~dZ1x5$ z-0cQHD1m|lhAq%p&eQ37Wo8`zAQ)Wbc!w9zV8MirRfSV<Bg<tpilwLAeZ&&JLVYFE zvscH%BI4gT&XRylTa5=<Hce4uFVrM(VFjUh)cYM`0pfylQ2w~+i8TO(`}ihYqfM#F zt0O4QzC9yNpkSnyu?d>T<Lev>jkVlEFE=;N$rO^wsC*HogNuS~`LNlD`cmU5pAUTZ zJcamF6sSa22X0Bp*`ANwfT~sfHfQ@ff!2U-g#^8gLeW>(0Q~7K?kj<$Gnx4;YP-s$ zQj;}y#wNyCAfwzc8+_G*IMBvyiOS#H%2nMk0Q(yW9X(|UkOzRAJZZ7vw(jY}!-uo9 zPe$%}{i1vAZ<?e=0PW}@8%JtD0%Zy5boLq{s+OZXlQ9o9Tt9;G{1Y(4ICM!tg*Vs) z(X=I(n1AT&BF>nFgtxzP40*V;Q+xqCY7;GG#}uT1A;qMc8Q@VS*@P6;eja5Bl;jl> zB*C7ab~{VN2sc#CpfPj&E4WblqNe=QMz|)D_jD8QX63wxF8Be4lH)(az(}4K0NWW= zm8*c^;+2p<>eNTRh&w!<<4Ll2APDzaz5>4FVe9`Pry4!$(8%lf9OAwYpM5rfN~oBm T+++VJ1&=akzWPh&&lmp<xM9Wl diff --git a/site/content/en/blog/complex-prog/index.md b/site/content/en/blog/complex-prog/index.md deleted file mode 100644 index 290ef53c..00000000 --- a/site/content/en/blog/complex-prog/index.md +++ /dev/null @@ -1,179 +0,0 @@ ---- -slug: complex-prog -title: Простое сложное программирование -date: 2021-04-15 ---- - -![КДПВ](complex-prog.jpeg) - - -В очередной раз увидел на Хабре статью про сложное дело под названием «программирование». -И то, что программирование действительно является делом не простым воспринимается как факт и обычно не требует какого либо подтверждения. - -Но понятие «сложность» сродни термину «куча». -Для кого-то и пять кокосов это не куча, а кого-то съел один и «больше не хочется» - значит для него и единственного кокоса будет много. - -Так и со сложностью ПО. Вроде бы увеличение сложности является для всех очевидным и наблюдается во всех сферах применения IT технологий, -да и сами языки программирования по мере своего развития становятся все сложнее, -а вот оценивать «сложность» с помощью численных метрик — дело заведомо неблагодарное, но и «нельзя управлять тем, что невозможно измерить ...». - -Обычно разговоры о «сложности» включают в себя только оценочные суждения без какой либо численной оценки. -А так как лично меня интересует вопрос сложности языков программирования, -то я решил посчитать сложность реализации компилятора gcc в каких нибудь условных попугаях. -Вдруг можно будет увидеть какие нибудь закономерности? - -## Выбор «попугаев» для измерения -Я не стал придумывать свои или вычислять эмпирические метрики [программного кода](https://habr.com/company/intel/blog/106082/), -и в качестве «попугая» решил взять самую простую метрику SLOC (англ. Source Lines of Code) — количество строк исходного текста компилятора, -которая очень легко вычисляется. - -Правда, с её помощью можно будет оценивать сложность языка только при следующем допущении — сложность языка должна находиться в прямой зависимости от сложности его реализации, -если для простых синтаксических конструкций будет требовать меньше кода, чем для более сложных. - -Конечно, использование метрики «количество строк исходного кода» имеет и свои недостатки, -т.к. она сильно зависит от используемого языка программирования, стиля оформления исходного кода и в общем случае не позволяет сравнивать несколько разных проектов между собой. - -Но для численной оценки сложности кода в рамках **одного проекта**, метрика SLOC подходит хорошо. - -## Методика подсчета SLOC -Изначально попробовал использовать простой bash скрипт с поиском по маске и подсчетом числа строк в файлах исходника через `wc -l`. -Но через некоторое время стало понятно, что приходится изобретать очередной велосипед. - -![Ну вы поняли](bag.jpeg) - - -Поэтому решил взять уже готовый. После быстрого поиска остановился на утилите [SLOCCount](https://dwheeler.com/sloccount/), -которая умеет анализировать почти три десятка типов исходников. - -### Список типов файлов для автоматического анализа -``` - 1. Ada (.ada, .ads, .adb) - 2. Assembly (.s, .S, .asm) - 3. awk (.awk) - 4. Bourne shell and variants (.sh) - 5. C (.c) - 6. C++ (.C, .cpp, .cxx, .cc) - 7. C shell (.csh) - 8. COBOL (.cob, .cbl) as of version 2.10 - 9. C# (.cs) as of version 2.11 - 10. Expect (.exp) - 11. Fortran (.f) - 12. Haskell (.hs) as of version 2.11 - 13. Java (.java) - 14. lex/flex (.l) - 15. LISP/Scheme (.el, .scm, .lsp, .jl) - 16. Makefile (makefile) — not normally shown. - 17. Modula-3 (.m3, .i3) as of version 2.07 - 18. Objective-C (.m) - 19. Pascal (.p, .pas) - 20. Perl (.pl, .pm, .perl) - 21. PHP (.php, .php[3456], .inc) as of version 2.05 - 22. Python (.py) - 23. Ruby (.rb) as of version 2.09 - 24. sed (.sed) - 25. SQL (.sql) — not normally shown. - 26. TCL (.tcl, .tk, .itk) - 27. Yacc/Bison (.y) </code> -``` - -Причем, считает не просто количество строк исходного текста, но и умеет игнорировать комментарии, -исключает из подсчета дубли файлов (сравнивает их хеш суммы), а также выводит расчетную трудоемкость, -примерную оценку стоимости разработки анализируемого проекта и другие характеристики. - -Меня изначально интересовал объем исходников на С/С++ и может быть еще на Ассемблере, если таких файлов окажется достаточно много. -Но после начала работы очень обрадовался, что не стал изобретать велосипед, а взял готовую тулзу, -т.к. она отдельно считала статистику исходных файлов синтаксического анализатора Yacc/Bison (.y), -который и определяет фактическую сложность парсера (читай сложность синтаксиса языка программирования). - -Старые исходники gcc брал с https://gcc.gnu.org/mirrors.html, но перед запуском анализатора удалил каталоги других компиляторов (ada, fortran, java и т.д.), -чтобы они не попадали в итоговую статистику. - -## Результаты в попугаях - -![](graph1.jpeg) - -__Итоговая статистика__ - -![](graph2.png) - -__Объем кода синтаксического анализатора Yacc/Bison__ - -![](graph3.jpeg) - -__Объем общей которой базы GCC (только для языков C и C++)__ - -## Выводы -К сожалению, синтаксический анализатор Yacc/Bison использовался только до 3 версии, а после его использование свелось на нет. -Поэтому оценить сложность синтаксиса С/С++ с помощью объема кода парсера можно лишь примерно до 1996-98 года, -после чего его стали постепенно выпиливать, т.е. чуть менее, чем за десять лет. -Но даже за этот период объем кодовой базы синтаксического анализатора вырос двукратно, что примерно соответствует по времени реализации стандарта C99. - -Но даже если не учитывать код синтаксического анализатора, то объем общей кодовой базы так же коррелирует с внедрением новых стандартов C++: C99, С11 и C14. - -На графике не видно выраженного пика для С+17 и следующих версий, но предполагаю, -что при текущем объеме кодой базы (более 4 миллионов строк только С и С++ кода), несколько тысяч строк, -необходимых для поддержки синтаксических конструкций новых стандартов просто незаметно. - -### Вывод первый - очевидный. Рост сложности инструментов разработки -Фактически на примере проекта GCC можно видеть постоянный и неотвратимый рост сложности рабочих инструментов программистов. - -И как бы не говорили о деградации разработки в статье ["Хорошие времена рождают слабаков"](https://habr.com/company/itelma/blog/550620/), -о системном кризисе программного обеспечения, который носит поколенческом характер, но мне кажется тут дело немного в другом. - -Обновление персонала и как следствие — необходимость обучения новых сотрудников старым наработкам, -тут дело не сколько в передаче знаний, сколько в возможности эти знания усваивать. - -Причем возможность усвоения знаний для разных поколений будет разная, но не из-за того, что предыдущее поколение было умнее, а у нового поколения не хватает толку в этом разобрать. -Просто изменяется окружение и усложняются рабочие инструменты, по сравнению с теми, которые были в ходу у предыдущего поколения. - -### Вывод второй — порог входа -Представьте, что нужно «сделать свой сайт». Естественно нужно определить, какую CMS для него использовать и какой брать хостинг. -И если с хостингом вопрос решается очень просто, конечно же в TimeWeb, да еще и [с бонусом по ссылке](https://timeweb.com/services/hosting?utm_source=rsashka&utm_medium=timeweb&utm_campaign=timeweb-bring-a-friend), то при выборе CMS приходится подумать. - -И если для простых сайтов существуют и простые решения, то для тех, кто не ищет легких путей существует CMS Drupal, -который примечателен тем, что имеет фантастически высокий порог входа для начала использования. - -![Сложность внедрения Drupal](drupal.jpeg) - -Это я к чему? При использовании любого инструмента, как и языка программирования, существует некий минимальный уровень комфортного использования. -Причем этот уровень прямо пропорционально связан с размером той целевой аудитории, для которой он предназначен. -Точнее, размер возможной аудитории определяется в том числе и требованиями к уровню начальных знаний и квалификации потенциального пользователя. - -### Итоговый вывод — не утешительный -Если рассматривать увеличение сложности только самого ПО, то это одно дело. Вот к примеру: - -__Статистика ядра Linux с вики__ -~~~ -17 сентября 1991: Linux версии 0.01 (10 239 строк кода). -14 марта 1994: Linux версии 1.0.0 (176 250 строк кода). -Март 1995: Linux версии 1.2.0 (310 950 строк кода). -9 июня 1996: Linux версии 2.0.0 (777 956 строк кода). -25 января 1999: Linux версии 2.2.0, изначально довольно недоработанный (1 800 847 строк кода). -4 января 2001: Linux версии 2.4.0 (3 377 902 строки кода). -18 декабря 2003: Linux версии 2.6.0 (5 929 913 строк кода). -23 марта 2009: Linux версии 2.6.29, временный символ Linux — тасманский дьявол Tuz (11 010 647 строк кода). -22 июля 2011: релиз Linux 3.0 (14,6 млн строк кода). -24 октября 2011: релиз Linux 3.1. -15 января 2012: релиз Linux 3.3 преодолел отметку в 15 млн строк кода. -23 февраля 2015: первый релиз-кандидат Linux 4.0 (более 19 млн строк кода). -7 января 2019: первый релиз-кандидат Linux 5.0 (более 26 млн строк кода). -~~~ - -А что делать, если сложность программного обеспечения накладывается на тенденцию постоянного усложнения самих рабочих инструментов? -Ведь постоянное развитие языков программирования неизбежно повышает порог входа для всех начинающих и только усугубляет проблему сложности разработки ПО. - -Другими словами, не зависимо от того, как хорошо документирован код и как полно он покрыт тестами, -через некоторое время устаревают используемые инструменты, завершаются жизненные циклы внешних зависимостей, -и самое главное, приходят новые люди взамен тех, кто разработал или сумел разобраться в системе. - -И у новых людей возникает необходимость разбираться в системе с самого начала, но в других начальных условиях. -И из-за этого, сложность изучения системы для всех новых людей будет выше просто по факту того, -что изменились внешние условия и усложнились рабочие инструменты, которыми приходится использовать новым сотрудникам. - -Понятно, что чем дальше, тем проще уже не будет. Ведь область IT , это среда с самой высокой конкуренцией. -И как уж тут не вспомнить Льюиса Кэррола, что его крылатое выражение -> Нужно бежать со всех ног, чтобы только оставаться на месте, а чтобы куда-то попасть, надо бежать как минимум вдвое быстрее! - -Ведь это относится не только к Алисе в стране чудес, но и ко всем информационным технологиям в целом! - -[Первоначальная публикация](https://habr.com/companies/timeweb/articles/551754/) diff --git a/site/content/en/blog/dsl-with-macros.en.md b/site/content/en/blog/dsl-with-macros.en.md index 9eb70830..1b19c9e4 100644 --- a/site/content/en/blog/dsl-with-macros.en.md +++ b/site/content/en/blog/dsl-with-macros.en.md @@ -7,13 +7,22 @@ description: > --- +{{% pageinfo %}} -https://habr.com/articles/720416/ +Attention!!! + +This article contains a description of the NewLnag syntax of the previous version. + +Publication source https://habr.com/articles/720416/ + +{{% /pageinfo %}} ![image](https://habrastorage.org/webt/r9/4d/tu/r94dtuimvtiiuntx5xpunndaetq.jpeg) + [This is a translation of my own article](https://habr.com/company/timeweb/blog/719332/) + The release of **[NewLang](https://newlang.net/)** language with a brand new "feature" is coming, a remodeled version of the preprocessor that allows you to extend the language syntax to create different DSL dialects using macros. ### What is it about? diff --git a/site/content/en/blog/dsl-with-macros.md b/site/content/en/blog/dsl-with-macros.md deleted file mode 100644 index 742c089c..00000000 --- a/site/content/en/blog/dsl-with-macros.md +++ /dev/null @@ -1,213 +0,0 @@ ---- -slug: dsl-with-macros -title: Вариант реализации DSL (domain-specific language) с помощью макросов -date: 2023-03-01 ---- - - -![КДПВ](/blog/dsl.jpeg) - -{{% pageinfo %}} - -Внимание!!! - -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. - -Актуальную версию синтаксиса языка можно посмотреть [тут](/docs/). - -{{% /pageinfo %}} - - -Близится релиз языка **[NewLang](https://newlang.net/)** с принципиальной новой «фишкой», переделанным вариантом препроцессора, который позволяет расширять синтаксиса языка для создания различных диалектов DSL за счет макросов. - -И, как всегда, используя ранее найденный лайфхак [Хабр — ума палата](https://habr.com/post/539674/), хотелось бы получить от читателей обратную связь насчет предлагаемого ниже подхода, который планируется к реализации в новом препроцессоре **NewLang**. - -### О чем идет речь? -> [DSL](https://ru.wikipedia.org/wiki/Предметно-ориентированный_язык) (Предметно-ориентированный язык) - язык программирования, специализированный для конкретной области применения. Считается, что использование DSL существенно повышает уровень абстрактности кода, а это позволяет вести разработку более быстро и эффективно и существенно упрощает решение многих задач. - -#### Условно, можно выделить два подхода к реализации DSL: -- Разработка независимых трансляторов синтаксиса с помощью генераторов лексеров и парсеров для определения грамматики целевого языка посредством БНФ и регулярных выражений (Lex, Yacc, ANTLR и т. д.) и последующей компиляцией полученной грамматики в машинный код. -- Разработка или встраивание диалекта DSL на языке (метаязыке) общего назначения, в том числе за счет применения различных библиотек или специальных парсеров / препроцессоров. - -Далее речь пойдет о втором варианте, а именно, о реализации DSL на базе языков (метаязыков) общего назначения и новом варианте реализации макросов в **NewLang** как основы для разработки DSL. - - -## Две крайности -Наверно имеет смысл начать с описания о двух крайностях при реализации DSL на базе языка (метаязыка) общего назначения: - -### Ограниченная грамматика -Если язык программирования ограничен собственной фиксированной грамматикой и не допускает её расширения, -то при реализации DSL разработчик будет вынужден использовать уже существующую грамматику, правила записи операций и вообще весь синтаксис будет оставаться такими же, как в языке реализации. Например, при использовании в качестве базового языка С/С++ или применении различных библиотек и фреймворков в других языках программирования общего назначения. - -*В этом случае под термином "DSL" будет скрываться просто набор специфических терминов предметной области, переопределенных макросов и/или операторов, но использование которых будет ограничено грамматикой языка реализации.* - -### Неограниченная грамматика -Если же язык (метаязык) позволяет модифицировать собственную грамматику (например на уровне [AST](https://ru.wikipedia.org/wiki/Абстрактное_синтаксическое_дерево)), то DSL уже не будет жестко огранен синтаксисом базового языка программирования, и в результате его грамматика может быть какой угодно. Вплоть до того, что «для каждого нового проекта придется изучать новый язык… ». -Это можно сделать с помощью использования специализированных метаязыков (Lisp, ML, Haskell, Nemerle, Forth, Tcl, Rebol и пр.) - -Очень рекомендую прочитать о метапрограммровании великолепную статью @NeoCode [Метапрограммирование: какое оно есть и каким должно быть](https://habr.com/post/258667/). - - -## Для обсуждения предлагается следующая реализация макросов -«Нет в мире совершенства», и после выпуска релиза **NewLang 0.2** я получил много отзывов (по большей части негативных), -по поводу первого варианта [реализации макросов](https://github.com/rsashka/newlang/blob/v0.3.0/docs/syntax.md#макросы) и [DSL на их основе](https://github.com/rsashka/newlang/blob/v0.3.0/docs/syntax_dsl.md). И если положить руку на сердце, эта критика часто была обоснованной. -Поэтому я решил попробовать немного переделать макросы, в надежде получить «золотую середину» между двумя описанными выше крайностями при описании DSL. - -### Используемая терминология -Макросы в *NewLang*, это один или несколько терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем). -Макросы являются одновременно и расширением базового синтаксиса языка, при реализации собственных диалектов DSL, и синтаксическим сахаром. - -Главная особенность макросов в том, что они позволяют изменять выражения еще до их вычисления во время выполнения. -Раскрытие макросов происходит во время работы **лексера**, что позволяет подменять ими любые другие термины и даже модифицировать сам синтаксис языка. - -Поэтому, если перед именем объекта **NewLang** модификатор не указывать (**\\**макрос, **$**локальная_переменная или **@**модуль), -то сперва будет производиться поиск объекта среди макросов, потом среди локальных переменных и в последнюю очередь среди модулей (объектов модуля). -За счет этого можно использовать термины без обязательных модификаторов для указания конкретных типов объектов. - -#### Определение макросов -Для определения макросов используется точно такой [синтаксис](https://newlang.net/ops.html), как и для других объектов языка -(применяются операторы «**::=**», «**=**» или «**:=**», соответственно для создания нового объекта, присвоение нового значения уже существующему или для создания объекта / присвоения нового значения объекту не зависимо от его наличия или отсутствия). - -В общем виде, определение макроса состоит из трех частей **<**имя макроса**>** **<**оператор создания/присвоения**>** **<**тело макроса**>** и завершающая точка с запятой "**;**". - -#### Тело макроса -Телом макроса могут быть корректное выражение языка, последовательность лексем (которые заключается в двойные обратные слеши, т.е. **\\\\**лексема1 лексема1**\\\\**) или обычная текстовая строка (обрамленная в тройные обратные слеши, т.е. **\\\\\\** текстовая строка **\\\\\\**). - -Для соединения двух лексем в одну (аналог операции ## в препроцессоре С/С++), используется по аналогии синтаксис **\##**. Похожий оператор применяется и для обрамления лексемы в кавычки **\#**, например, `\macro($arg) := \\ func_ \## \#arg(\#arg) \\;`? тогда вызов macro(arg) будет преобразован в `func_arg ("arg")`; - -#### Имя макроса -Именем макроса может быть одиночный идентификатор с префиксом макроса "**\\**" или последовательность из нескольких лексем. Если в качестве имени макроса используется последовательность лексем, то среди них должен быть как минимум один идентификатор и может присутствовать один или несколько шаблонов. - -Шаблон — это специальный идентификатор который при сопоставлении может заменяться любым одиночным термином. С помощью шаблонов производится поиск по образцу и замена заданных последовательностей лексем на тело макроса. - -Для указания шаблона в начале идентификатора нужно поставить знак доллара (что соответствует записи имени локальной переменой), т. е. **\\\\**одна_лексема**\\\\**, **\\\\**целых три лексемы**\\\\** **\\\\**лексема *$шаблон1* *$шаблон2* **\\\\**. - -Макросы считаются одинаковыми, если их идентификаторы равны, количество элементов в их именах совпадает, а идентификаторы и шаблоны располагаются на тех же самых местах. - -#### Аргументы макросов -Термины или шаблоны в имени макроса могут иметь аргументы, которые указываются в круглых скобках. Переданные аргументы в теле макроса записываются в месте для раскрытия как имя локальной переменой, но перед именем нужно добавить обратный слеш, т.е. `\$name`. - -Произвольное количество параметров у макроса отмечается троеточием "...", а место для вставки этих аргументов отмечается лексемой **\$...**. Если у макроса есть несколько идентификаторов с аргументами, то для вставки аргументов из конкретного идентификатора используется лексема с указанием нужного идентификатора, например, **\$name...**. - -Чтобы вставить количество реально переданных аргументов используется лексема **\$#**, или с указанием нужного идентификатора, например, **\$#name**. - -*Макросы работают с лексемами, которые содержат различную информацию, в том числе и о типе данных, если она указана. Но на текущий момент типы данных в аргументах макросов никак не обрабатываются и это одна из обязательных фич, которая будет реализована в будущем.* - -### Примеры: -``` - \макрос1 := 123; - \макрос2(arg) := {func( \$arg ); func2(123);}; - \\макрос из(...) лексем\\ := \\ call1(); call2( \$... ); call3() \\; - \текстовый_макрос := \\\ строка для для лексера \\\; - - # Обычные макросы (тело макроса корректное выражение) - \macro := replace(); - \macro2($arg) := { call( \$arg ); call()}; - # В функцию передается кол-во аргументов и сами аргументы - \\func name1(...)\\ := name2( \$#, \$name1... ); - - # Тело макросов из последовательности лексем - \if(...) := \\ [ \$... ] --> \\; # Выражение может быть не полным - \else := \\ ,[ _ ] --> \\; # Выражение может быть не полным - - # Тело макроса из текстовой строки (как в препроцессоре С/С++) - \macro_str := \\\ строка - тело макроса \\\; # Строка для лексера - \macro($arg) := \\\ func_ \## \#arg(\#arg)\\\; # macro(arg) -> func_arg ("arg") -``` - -## Какие возможности это дает? -Таким образом можно определить макросы в следующих комбинациях: -``` -№ п/п Имя макроса Тело макроса ----------------------------------------------------------------- - 1. \идентификатор выражение - 2. \идентификатор \\лексема1 лексема2\\ - 3. \идентификатор \\\строка для лексера\\\ - 4. \\лексема1 лексема2\\ выражение - 5. \\лексема1 лексема2\\ \\лексема1 лексема2\\ - 6. \\лексема1 лексема2\\ \\\строка для лексера\\\ -``` -Каждая из перечисленных выше комбинации имеет свои свойства и ограничения: -1. Классическая замена одного термина на другой термин или целое выражение. Однократно обрабатывается лексером и парсером при определении. Выражение в теле макроса должно быть корректным с точки зрения синтаксиса и при наличии в нем ошибок, сообщение об этом формируется сразу, еще при определении макроса. - -2. Классическая замена одного термина на последовательности лексем, в том числе и не полные синтаксические конструкции. Однократно обрабатывается лексером при определении макроса. Тело макроса анализируется парсером при его использовании, поэтому возможные синтаксические ошибки будут замечены только при раскрытии макроса. - -3. Классическая замена одного термина на текстовую строку, которая подается на вход лексера. Однократно обрабатывается лексером только имя макроса при его определении, что позволяет модифицировать тело макроса и изменять/комбинировать/модифицировать лексемы до их подачи в анализатор. Синтаксические ошибки будут замечены только при раскрытии макроса. - -4, 5 и 6. Замена последовательности из нескольких лексем (шаблонов) на выражение, последовательность лексем или текстовую строку соответственно. - -## Назначение и примеры использования -Макросы используются и для преобразования базового синтаксиса *NewLang* в более привычный синтаксис на основе ключевых слов, так как такой текст гораздо легче воспринимается при последующем чтении исходного кода. - -Если перед именем объекта NewLang модификатор не указан (**\\**макрос, **$**локальная_переменная или **@**модуль), то сперва ищется имя макроса, потом имя локальной переменной и в последнюю очередь имя модуля (объекта модуля). За счет этого получается определять синтаксис DSL в привычной записи без обязательных префиксов у разных типов объектов. - -Например, запись условного оператора на основном синтаксисе **NewLang**: -``` - [condition] --> { - ... - } [ condition2 ] --> { - ... - } [ _ ] { - ... - }; - -# С помощью макросов - \if(...) := \\ [ \$... ]--> \\; - \elif(...) := \\ ,[ \$... ]--> \\; - \else := \\ ,[ _ ]--> \\; - -# Превращается в классическую запись - if( condition ){ - ... - } elif( condition2 ) { - ... - } else { - ... - }; -``` - -Или цикл до 5: -``` -count:=1; -[ 1 ] <-> { - [count>5] --> { - ++ 42 ++; - }; - count+=1; -}; -``` - -будет выглядеть более привычно с использованием соответствующих макросов: -``` -\while(...) := \\ [ \$... ] <-> \\; -\return(...) := ++ \$... ++; -\true := 1; - -count := 1; -while( true ) { - if( count > 5 ) { - return 42; - }; - count += 1; -}; -``` - -### Удаление макросов -Для удаления макроса нужно присвоить ему пустую последовательность лексем `\macro_str := \\\\;`. Так же для удаления можно использовать специальный синтаксис: `\\\\ name \\\\;` или `\\\\ \\два термина\\ \\\\;`, т.е. указать имя макроса между четырьмя обратными слешами. - -Необходимость использования отдельной синтаксической конструкции для удаления макросов вызвана тем, что имена макросов обрабатываются лексером еще до этапа анализа в парсере. - -## В чем профит? -1. Базовый синтаксис языка можно разбавлять дополнительными ключевыми словами и превратить его в привычный «keyword-based». -2. Определение макросов соответствует лексике языка, а сами макросы обрабатываются как обычные объекты. -3. Простота анализа исходного кода и его отладки. -4. Использование терминов DSL и приемов метапрограммирование можно сделать явным, например, всегда перед именем макроса указывать префикс. В этом случае компилятор будет однозначно знать, что требуется выполнить раскрытие макроса. -5. Несмотря на то, что синтаксис языка на свой страх и риск можно значительно модифицировать, но это можно сделать только в рамках определенные ограничений (AST нельзя модифицировать напрямую), что не позволяется очень сильно разгуляться и, например, обрушить или подвесить компилятор. -6. Несмотря на очень большие возможности по модификации синтаксиса, получается очень простая, быстрая и однозначная реализация. А это положительно сказывается на скорости анализа исходников, детектирования и обработки возможных ошибок и одновременно является разумным компромиссом между сложностью реализации данного функционала и возможностями определения собственных диалектов DSL. -7. При желании есть куда развивать возможности метапрограммирования. В будущем можно добавить сопоставление шаблона с образцом (например, на основе регулярных выражений), сделать параметризацию строки для генерации синтаксиса в теле макроса, в том числе и в рантайме, и много других разных способов изящно выстрелить себе в ногу или ногу своего товарища. - -## Заключение -Буду благодарен за любую обратную связь по данной реализации макросов. И дважды благодарен, если кроме критики будут высказаны еще и предложения по её улучшению и доработкам, если какой-то момент был упущен. - -[Ссылка на первую публикаци](https://habr.com/companies/timeweb/articles/719332/) - diff --git a/site/content/en/blog/inter-prog.md b/site/content/en/blog/inter-prog.md deleted file mode 100644 index 388c2e8e..00000000 --- a/site/content/en/blog/inter-prog.md +++ /dev/null @@ -1,212 +0,0 @@ ---- -slug: inter-prog -title: Интернациональное программирование на естественных языках -date: 2020-12-05 ---- - - -![КДПВ](/blog/langs.jpeg) - - -{{% pageinfo %}} - -Внимание!!! - -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. - -Актуальную версию синтаксиса языка можно посмотреть [тут](/docs/). - -{{% /pageinfo %}} - - - -В последнее время часто попадаются на глаза статьи о новых языках программирования, -а так же различные рейтинги и прогнозы, связанные с популярностью компьютерных языков. - -Заявляют о себе и новые [инструментальные средства](https://habr.com/company/testo_lang/blog/521682/), -которые в своей работе используют собственные форматы описания конфигурационных файлов или последовательности выполняемых команд, -которые так же очень сильно приближает их к понятию «язык программирования». - -Цель написания данной статьи — формулировка ожиданий и возможной реализации абстрактного языка программирования, -который может стать универсальным инструментом для общения между компьютером и человеком. - -## О программистах -Если начинать с самого начала, то когда-то давно я слышал перефразированное высказывание, -«каждый программист должен написать свою базу данных, текстовый редактор и язык программирования». -И если первые две вещи я уже давным давно написал, то с языком программирования пока не сложилось. - -Ведь как обычно создаются языки программирования? - -У каждого программиста всегда есть какой-то своей предыдущий опыт: - -- знания одного или нескольких языков программирования (как же без этого) -- негативный опыт от их использования (в противном случае, если все устраивает, то зачем придумывать что-то новое?) -- желания получить новые возможности (когда в существующих языках чего-то не хватает) - -А перед тем, как описывать синтаксис, выбирать ключевые слова и начинать основную работу: -лексер, парсер, базовые библиотеки, нужно дать ответ на основные вопросы: - -- Компилятор/интерпретатор/транспилятор(transpiler)? -- Статическая или динамическая типизация? -- Ручное управление памятью или автоматическое со сборщиком мусора? -- Модель программирования: ООП, функциональное, структурное или что-то новое? -- Разрешены ли вставки из других языков программирования и т. д.? - -У меня, наверно, как и у большинства читателей, присутствует опыт использования нескольких языков программирования. -Поэтому давно сложилось практика, что для решения задачи лучше взять известный язык или даже выучить новый, вместо того, -чтобы начинать писать собственный. - -Тем более, что не хочется придумывать еще один язык просто ради галочки или ради самого языка. -Я считаю, что цель его создания должна быть за пределами потребностей самого разработчика. - -И мне кажется, что удалось определить область, для которой разработка языка программирования может быть востребованной, -а потраченные на него усилия могут принести реальную пользу. - -## О не программистах -Эта область — программирование для «не программистов» на «естественном» языке. -Я специально взял слова «не программистов» и «естественном» в кавычки, т.к. эти термины являются очень условными. - -Ведь если не программист начинает программировать, то сам того не осознавая, он автоматически становится программистом ;-). -А «естественным» язык программирования быть не может по определению. -Точнее для компьютеров скорее всего «естественным» будет язык Assembler или набор машинных команд. - -> Поэтому, цель максимум — приблизить язык программирования к естественному человеческому языку. - -Это не только сделает чтение текста программы более понятным для не профессионалов, -но и позволит начинать составлять программы просто освоив письменную речь, используя самый минимум основных правил. - -Но в подобной формулировке кроется очень большая проблема! - -> Любой язык программирования является интернациональным, т.к. его синтаксис не зависит от естественного языка, на котором общается программист. - -А если текст программы будет на "естественном" языке, то она станет понятной только для знающих этот язык, -одновременно становясь непонятной для всех остальных. - -В качестве иллюстрации: [раз](http://espressocode.top/natural-language-programming/) или [два](https://habr.com/post/268401/). -Если пофантазировать насчет хотелок к такому языку, то видятся следующие требования и ограничения: - - -- Так как каждый пользователь является носителем своего родного естественного языка (или даже нескольких), то жестко задавать ключевые слова невозможно, из чего следует, что основой такого языка должны стать только правила пунктуации, но никак не лексика или грамматика. -- Компилятор/транслятор должен уметь преобразовывать исходный текст программы не только в машинный код для компьютера, но в другой вариант "естественного" языка, чтобы пользователь мог работать с исходным текстом на известном ему "естественном" языке. -- Очень хочется видеть в новом языке ~~толерантность~~ терпимость к очепяткам. Подобная «фича» присутствует в письме на естественном языке, и несмотря на наличие опечаток, практически всегда сохраняется смысл. Естественно, в данном случае не стоит доходить до фанатизма. Компилятор не читает мысли и не может в действительности «понять», что имел ввиду пользователь, и все же довольно часто можно игнорировать опечатки в тексте программы исходя из контекста (пусть и с выводом предупреждающих сообщений). - - -Тем не менее, такой язык должен оставаться именно языком программирования со всеми возможностями создания программ любого уровня сложности, -включая функциональное и объектно-ориентированное программирование и однозначное понимание написанного. - -## О гипотетическом языке -Если взять за основу правила письменной речи, то основные соглашения и пунктуация для нового языка могут выглядеть примерно так: - -- Любой текст состоит из предложений и комментариев. Предложения обрабатываются, а комментарии игнорируются. -- Предложение состоит из последовательности терминов, литералов и символов, разделенных пробелами и знаками препинания и завершается символом конца предложения. -- Термин — слитно написанная последовательность букв, цифр и символов ":" и "_". -- Литерал — константы, включаемые непосредственно в текст программы, тип которой определяется однозначно. Это символьные строки в кавычках, целые и вещественные числа, и некоторые специальные форматы (время, дата). -- Символы — все остальное символы, которые не относятся к знакам препинания, пробельным символам, цифрам и буквам. -- Знаки препинания — символы пунктуации, имеющие специальное значение при разборе текста программы: - - «.»,«;»,«!»,«?»,«…» — конец предложения. - - «=» — присвоение значения. - - "" (кавычки) — определение символьной строки. - - «()» - передача параметров/аргументов или группировка операторов для определения приоритета выполнения операций. - - «[]» - массив или обращение к элементу массива. - - «{}» - включение в текст исходного кода программы на обычном языке программирования. - - «$» — системная переменная. - - «@» — системная функция. - - «,» (запятая) — перечисление. - - «:» (двоеточие) — список или логическая связь. - -Если с символом присвоения, кавычками, круглыми и квадратными скобками все должно быть более-менее понятно, -т.к. их назначение соответствует аналогичному в подавляющем большинстве языков программирования, -то про назначение остальных символов (фигурных скобок, двоеточия, запятой и системных функций/переменной), следует немного пояснить. - -Раз цель гипотетического языка программирования все же написание программ, -то необходимо предусмотреть возможность делать вставки обычного программного кода без учета всех возможностей и неоднозначностей, -которые присущи любому естественному языку. - -Так же эта возможность требуется для реализации низкоуровневых функций и для взаимодействия с внешними библиотеками. - -При создании подобных вставок и могут использоваться фигурные скобки, весь текст между которыми будет вставляться в итоговый файл практически без обработки. - -Для похожих целей служат и символы «$» — системная переменная и «@» — системная функция. Если такой символ поставить в начале слова, -тогда он станет обозначать объект с соответствующим назначением. Например «@exit» — будет означать функцию, -а «$var» — переменную с соответствующими именами, а сами объекты станут доступны как в обычном коде, -так и в программных вставках внутри фигурных скобок. - -Аналогичным образом организуется и доступ к отдельным полям/методам объектов: -«объект@метод» или «объект$поле». - -Символ запятая «,» применяется для указание последовательности равноправных логических блоков в одном предложении или для создания списков. - -Символ двоеточия «:» используется для создания списков и для обозначения логической связи между двумя частями слова/текста, в том числе для указания полного пути модуля. - -Например, создание списка: - -`В_строку: элемент 1, элемент 2, последний элемент.` -``` -Форматированный_список: -- элемент 1; -- элемент 2; -- последний элемент. -``` - -Логическое следствие/указание связи: - -``` -module:calc //термин «calc», который находится в модуле «module» -super:module:example$var //переменная «$var» которая находится в указанной иерархии. -``` -Как можно заметить, использование знаков препинания взято из их прямого назначения, принятого в письменной речи, -что должно обеспечить определенный компромисс между синтаксисом в стандартных языках программирования и письмом на естественном языке. - -## О компьютерах -Так как речь идет все же о языке программирования, то не обойтись без стандартных алгоритмических конструкций: следования, ветвления и циклов. - -Следование легко описывается обычными правилам письма на естественном языке. -В случае последовательного выполнения в одном предложении, операции и вызовы функций записываются последовательно через запятую. -Если они располагаются в разных предложениях, то они записываются так же друг за другом. -Причем форматирование по абзацам служит только для лучшего восприятия текста и логического разделения отдельных фрагментов. - -При создании условных и циклических управляющих конструкций уже потребуются ключевые слова. -Но так как согласно исходным пожеланиям к языку, резервировать обычные термины для записи алгоритмических конструкций нельзя, -то перед ключевыми словами достаточно указывать символ системной функции, что позволит отличить обычный термин от ключевого (управляющего) слова. - -Естественно, при программировании, данными терминами хоть и можно будет пользоваться, но делать это совсем не обязательно. -Так как при настройке под конкретный естественный язык, системным функциям и ключевым словам нужно обязательно присвоить конкретные термины и пользоваться уже ими, например: - -``` -перейти = @goto, -метка = @label, -продолжить = @continue, -прервать=@break и т.д. -``` - -И последняя по очереди, но наверно самая важная по сути конструкция: передача параметров при вызовах функций. -Если стремиться к полностью естественному синтаксису, тогда мы получим тот самый естественный язык, который очень сложно анализировать. - -Тем не менее, мне кажется, что можно скомбинировать оба два подхода, если отказаться от обязательного использования круглых скобок, -там, где это допустимо по синтаксису. - -``` -Компьютерный: функция(параметр1, функция2(), параметр3=значение). -Естественный: функция параметр1 функция2 параметр3=значение. -``` - -Но: - -``` -Компьютерный: функция( функция2(параметр) ). -Естественный: функция функция2(параметр). -Или так: функция (функция2 параметр). -``` - -Другими словами, для естественного порядка указания аргументов, скобки для функций и запятые между параметрами могут быть опущены. -Хотя их использование должно определяться в первую очередь целевым естественным языком, а не синтаксисом. - -## О возражениях -Предвижу обоснованные возражения против использования подобного языка со стороны программистов. -Программа на нем по любому получится значительно многословнее, чем с использованием строгого формального синтаксиса обычных компьютерных языков. - -Поэтому напомню про его обязательное свойство - умение преобразовывать текст программы с одного языка на другой. -Это позволяет писать программы как с использованием строго формального синтаксиса без использования переопеределенных терминов на естественном языке, -так и преобразовывать исходный текст в "естественный" язык для "не программиста". - -[Ссылка на первую публикаци](https://habr.com/articles/531400/) \ No newline at end of file diff --git a/site/content/en/blog/lang-final/index.md b/site/content/en/blog/lang-final/index.md deleted file mode 100644 index 283ae944..00000000 --- a/site/content/en/blog/lang-final/index.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -slug: lang-final -title: Какая «идеальная» цель развития у языков программирования? -date: 2021-04-07 ---- - -![КДПВ](lang-final.jpeg) - -С постоянной периодичностью появляется информация о выходе новой версии того или иного языка программирования. -И с каждой новой версией расширяются его возможности, добавляются новые синтаксические конструкции или иные улучшения. - -И это очень сильно напоминает развитие технологий, как и в любой другой области техники. -Когда с очередным этапом совершенствуются создаваемые творения. -Быстрее, выше, сильнее … и одновременно значительно сложнее. - -Об этой проблеме меня заставила задуматься первоапрельская статья [«Доказательное программирование»](https://habr.com/post/550270/). - -Понятно, что дата публикации статьи говорит сама за себя. -Тем не менее, новые стандарты С++, постоянно выходящие спецификации Java или новый синтаксис у PHP 8, -невольно заставляют задуматься, а в нужную ли сторону идет развитие языков программирования? -Ведь большинство нововведений добавляют сложность в основной рабочий инструмент и решая одни проблемы, неявно добавляя множество других. - -А что должно быть в конце прогресса у развития такой дисциплины как программирование? -Или хотя бы у одного конкретного языка? Ради достижения какой конечной «идеальной» цели разрабатываются новые стандарты языков программирования? - - -Если фантазировать об идеальной конечной цели развития, например транспорта, -то это будет мгновенное перемещение на любое расстояние с произвольной полезной нагрузкой и нулевым потреблением энергии. - -Или, например, какая может быть идеальная цель у медицины? ~~Бедные не болели, а богатые не выздоравливали,~~ вероятно, лечение любых болезней и биологическое бессмертие. - -Конечно, «идеальная» цель это очень упрощенное понятие. Фактически, «идеальная» это синоним «недостижимая», -т.к. она всегда будет упираться необходимость соблюдать компромисс между различными взаимно-исключающими граничными условиями. - -Но сравнивать разработку средств программирования с процессом развития в других технических дисциплинах напрямую нельзя. -Ведь при создание конечного продукта в любой технической области, все сложные производственные операции, -которые требуют непосредственного участия человека, практически всегда можно разделить на отдельные, более простые части или этапы. - -Это делается, в том числе и для того, чтобы сложность одной выполняемой операции не была запредельной для исполнителя. -Но как это можно сделать при разработке программного обеспечения? - -В данном случае, я имею ввиду конечную ограниченность возможностей одного конкретного человека в противовес возможностям разделения технологических процессов на отдельные этапы, -каждый из которых может выполняться совершенно разными людьми (как пример, это обычный конвеер с его разделением труда на элементарные операции -или узкая специализация врачей-специалистов в одной конкретной области). - -Ведь даже сложно себе представить фантастическую организацию труда программистов в виде конвеера: -- Первый разработчик пишет только интерфейсы функций и их вызовы, после чего передает код второму сотруднику. -- Второй пишет в тексте программы только условия проверки и безусловные переходы и передает текст третьему. -- Третий отвечает за написание циклов и общее форматирование кода и т.д. -и результате ожидаемо получится полный бред. - -Из-за этого индустрия разработки ПО вынуждена идти по экстенсивному пути развития (т.е. за счет увеличения используемых в производстве ресурсов). -Современные промышленные языки программирования имеют очень богатые возможности по разделению кода приложения на отдельные функции/модули/компоненты, -что позволяет вести разработку сложного программного продукта сразу множеству сотрудников одновременно. - -Но и такое развитие имеет естественное ограничение. И этим ограничением является сам человек, -так как каждый разработчик должен знать и уметь пользоваться своим рабочим инструментом, т.е. языком программирования. - -Если взять приведенную выше аналогию с конвеером, то в ней каждый рабочий должен был бы досконально знать б**о**льшую часть используемых станков -и инструментов на всем заводе, независимо от того, какую **одну** конкретную операцию он выполняет на своем рабочем месте. - -Ведь парадокс развития языков программирования заключается в том, что добавляя новые возможности и синтаксические конструкции, -мы усложняем рабочий инструмент, предназначенный как для совместного, так и для индивидуального использования! - -И получается, что одновременно с процессом постоянного наращивания возможностей средств разработки идет -и обратный процесс — увеличение сложности разработки кода отдельно взятым разработчиком. -Фактически, это и есть то самое взаимоисключающее непреодолимое противоречие. - -Может быть именно поэтому невозможно найти «серебряную пулю», которая бы повышала производительность труда одного программиста? -Ведь внимание и возможности человека не безграничны. -И любые новшества и улучшения рабочего инструмента программиста вынужденно толкают всю IT индустрию на экстенсивный путь развития. - -Возможно следует разрабатывать принципиально новые подходы, а не гнаться за синтаксическим сахаром в языках программирования из прошлого века? -Или и вовсе не париться, продолжать пользоваться тем, что есть, а теория дедушки Дарвина все сама расставит по своим местам? - -[Первоначальная публикация](https://habr.com/companies/timeweb/articles/551224/) - diff --git a/site/content/en/blog/lang-final/lang-final.jpeg b/site/content/en/blog/lang-final/lang-final.jpeg deleted file mode 100644 index 2c5b9f2c0b9d035e92713bfef63173f6e76d2977..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51058 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%0D&o2R(0->97)yqBKT|o4<I0ae3bR$Ku>n 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 J4UE5Y{{u*e_&@*v diff --git a/site/content/en/blog/langs.jpeg b/site/content/en/blog/langs.jpeg deleted file mode 100644 index ec905246947cd1769180b1c938d1f26b7d83b16a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 227272 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 E*%iS9{Qv*} diff --git a/site/content/en/blog/logic-prog.md b/site/content/en/blog/logic-prog.md deleted file mode 100644 index f16c87c8..00000000 --- a/site/content/en/blog/logic-prog.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -slug: logic-prog -title: Проблема логических языков программирования -date: 2021-01-09 ---- - -![КДПВ](/blog/langs.jpeg) - -Некоторое время назад я писал про [«Интернациональное программирование на естественных языках»](/blog/inter-prog/), -в которой попытался представить достойную цель для абстрактного языка программирования, -попробовав примерить на него роль связующего звена между миром программистов с компьютерами и не программистов. - -Но в результате оказалось, что это не нужно в принципе, т.к. «не программистам» просто не требуется учиться писать программы. -А если иногда такое желание и возникает, то вполне хватает обычных формализованных языков программирования, -которых уже сейчас насчитывается наверно более десяти тысяч. - -А пользователи, как программисты, так и не программисты, просто хотят решать возникающие перед ними задачи. -И хотя задачи бывают совершенно разные, но если способ (алгоритм) её решения известен, то выбрать язык для её решения не составит никакого труда. - -За исключением одного класса задач. Задач, решение которых нельзя описать в виде алгоритма. -Но можно указать некие критерии, которым должно удовлетворять искомое решение. -Я имею ввиду логические языки программирования и [Пролог](https://ru.wikipedia.org/wiki/Пролог_(язык_программирования)), как самый яркий представитель этого класса. - -Еще помню воспоминание из юности, когда удалось достать дискету с этим языком. -Ух, с каким задором горели мои глаза, когда мне казалось, ну вот, еще чуть-чуть и будет создана система с базой знаний, -у которой и можно будет получить заветный ответ 42 на любой вопрос. - -Так почему этого так и не случилось? В чем проблема Пролога, да и любой системы / языка программирования, -назначение которых анализировать факты и искать ответы на вопросы? - -Эта проблема называется [«Комбинаторный взрыв»](https://ru.wikipedia.org/wiki/Комбинаторный_взрыв) - экспоненциальная (или более) зависимость времени работы алгоритма от количества входных данных. -И есть как минимум два решения этой проблемы. - -## Подходы к написанию программ -Прежде чем переходить к частностям, следует сказать пару слов про парадигмы программирования. -Обычно противопоставляют между собой два разных стиля в написании программ: [императивный](https://ru.wikipedia.org/wiki/Императивное_программирование) и [декларативный](https://ru.wikipedia.org/wiki/Декларативное_программирование). - -Императивный — это классический вариант написания программы, при котором программист сам задает шаги алгоритма для получения конечного результата. -А сам текст программы состоит из последовательности команд, которые читают, сохраняют и обрабатывают данные или вызывают другие команды. - -Декларативный — в этом стиле программист описывает условия задачи и правила для получения требуемого результата, -но не требуется детально описывать все шаги работы алгоритма, оставляя их на усмотрения компьютера. - -Именно к декларативному стилю относится язык Пролог, да и все остальные логические языки программирования. -К декларативному стилю написания программ следует относить и язык структурированных запросов (SQL). - -И проблема под называнием [«комбинаторный взрыв»](https://ru.wikipedia.org/wiki/Комбинаторный_взрыв) сильнее всего оказывает негативное влияние как раз на подобные языки. -Ведь в императивном подходе программист сам отвечает за последовательность выполняемых команд, и если он запрограммировал алгоритм полного перебора всех возможных вариантов решений, то он сам себе злобный Буратино. - -Другое дело, программирование в декларативном стиле. Разработчик хоть и может указать ограничения, которые следует применять при поиске решения, -но это возможно только в том случае, когда известен алгоритм решения задачи. -Но если алгоритм решения известен, то проще использовать императивный стиль, как раз и реализуя этот алгоритм! - -Поэтому основное применения языков программирования в декларативном стиле — отказаться от необходимости описания четкого алгоритма поиска решения, -отдав это компьютеру на откуп. Для которого самое простое решение «в лоб» - полный перебор возможных вариантов. - -Именно в этом случае и начинается экспоненциальный рост времени выполнения алгоритма. -И начиная с определенного порога, время ожидания ответа становится неприемлемым для реального использования. -Это и означает «Комбинаторный взрыв», резкий («взрывной») рост времени выполнения алгоритма при увеличении размера входных данных. - -## Проблема поиска решений -В языке Пролог эта проблема решалась за счет использования механизма отката и отсечений. -Иногда еще уточняли про «красное» и «зеленое» отсечение решений. -Но в любом случае, это были **алгоритмические** механизмы для ограничения количества размера дерева возможных решений, -а необходимость их применения все равно остается на программисте. - -Но чтобы их правильно реализовывать, нужно знать алгоритм решения, что опять возвращает нас к утверждению о том, -что если известен алгоритм, то и программировать его удобнее в императивном стиле. - -А если полный алгоритм решения задачи не известен (или не подходит, например из-за большого времени для его работы), -то в результате остается либо увеличивать производительность системы, чтобы сократить время выполнения алгоритма, -либо искать другое решение, в том числе, сокращая вычислительную сложность поиска решений, например, исключая заведомо не подходящие данные, -чтобы уменьшить возможные комбинации их перебора. - -### Масштабирование производительности -Увеличение производительности тоже бывает разным и работает не во всех случаях. -Вертикальное масштабирование производительности одного узла вычислительной среды имеет свой естественный предел. -И даже многократное увеличение скорости работы компьютера может лишь отдалить порог терпения пользователя при ожидании получения результата, -но не в состоянии принципиально решить саму проблему. - -Другое дело горизонтальное масштабирование, при котором выполнение алгоритма запускается на отдельных узлах, которые параллельно решают одну и ту же задачу. -Такой способ масштабирования позволяет уже значительно сократить время получения итогового результата для сложных вычислительных задач. -И хотя это способ является решением «в лоб», но успехи в области data science доказывают успешность такого подхода. - -Конечно, у горизонтального масштабирования тоже есть подводные камни. -В первую очередь, сам алгоритм должен допускать возможность параллельного выполнения независимо от других узлов. -Также требуется автоматизация управления заданиями, самими вычислительными узлами, да и всей системой в целом. - -Тут частично может помочь парадигма функционального программирования, которая ограничивает результат вычисления функций только входными параметрами -и результатом выполнения других функций, но сам результат не зависит от состояния системы или иных внешних данных. - -### Поиск обобщенного решения -Вторым способом решения решения проблемы комбинаторного взрыва является уменьшение вычислительной сложности решения. -Тут имеется ввиду не выбор другого алгоритма или решение задачи в символьном виде. -Если такое возможно, то все опять сразу сведется к императивному стилю программированию. - -Я имею ввиду возможность поиска самого алгоритма решения. -Точнее не совсем алгоритма, а возможность применения к входным данным различные методы отбора, чтобы исключить необходимость их полного перебора. -По сути, это сводится к применению различных методов и механизмов обработки входных данных с учетом различных закономерностей. - -Это возможно как алгоритмическими методами (откат и отсечение в Прологе), так и с применением машинного обучения, -которое очень хорошо справляется с поиском различных закономерностей. - -Естественно, такой способ подходит не для всех классов задач. Он не подходит для выявления **ВСЕХ возможных решений**. -Но там где это не требуется, подобные способы уменьшения вычислительной сложности имеют право на существование. - -Например, не требуется искать все возможные лекарства от конкретной болезни, достаточно **одного**, с учетом определенных ограничений, которое гарантированно подействует. - -К тому же, даже при нахождении частных решений, всегда существует шанс, что с их помощью получится увидеть не очевидные на первый взгляд закономерности, -которые помогут показать новые пути алгоритмического уменьшения вычислительной сложности основной задачи. - -## Область не решаемых задач -> Как вы считает, а реально ли создать язык логического программирования, который бы сам умел автоматизировать поиск решений для задач подобных классов? Или хотя бы имел в своем арсенале встроенные механизмы для автоматизации подобной деятельности? - - -### Результаты опроса из [оригинальной публикации](https://habr.com/articles/536268/) -``` -- 57.47% Ха-ха! То, что хочет автор и называется искусственным интеллектом (50 голосов) -- 27.59% Поиск решений нельзя автоматизировать (24 голоса) -- 19.54% Это уже есть и все давно придумано (17 голосов) -- 9.2% Такой язык не нужен, т.к. нейросети могут всё (8 голосов) -- 3.45% Свой вариант написал в комменатрии (3 голоса) -``` -Проголосовали 87 пользователей. Воздержались 62 пользователя. diff --git a/site/content/en/blog/matrix.jpeg b/site/content/en/blog/matrix.jpeg deleted file mode 100644 index 6961ac64a64bc43b5fe4e500d9745be96d1c2715..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 377403 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%0AoG=wMi6{77$s-r?n?*1hhw0Wqh{U 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%0A&GpRJmn}OvkjwLL$6hNa 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 diff --git a/site/content/en/blog/newlang.md b/site/content/en/blog/newlang.md deleted file mode 100644 index 030dc607..00000000 --- a/site/content/en/blog/newlang.md +++ /dev/null @@ -1,711 +0,0 @@ ---- -slug: newlang -title: Новый язык программирования -date: 2022-02-18 ---- - - -![КДПВ](/blog/langs.jpeg) - - -{{% pageinfo %}} - -Внимание!!! - -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. - -Актуальную версию синтаксиса языка можно посмотреть [тут](/docs/). - -{{% /pageinfo %}} - - - -Более года назад я начал публикацию статей с описанием особенностей нового языка программирования. -С тех пор утекло много воды, было протестировано множество идей, в итоге несколько раз все поменялось кардинальным образом -и сейчас представляю на суд читателей описание предфинальной версии языка и его особенностей. - -Данная статья предназначена в первую очередь для проверки основных концепций нового языка программирования, а также для получения обратной связи от читателей Хабра. -Ведь согласно наблюдению [Хабр-ума палата](https://habr.com/post/539674/), не замыленный взгляд со стороны очень сильно помогает в проработке новых идей. - -Этот проект очень долго был без собственного названия и в публикациях назывался просто и абстрактно "новый язык". -Но после нескольких статей, временное название "новый язык" постепенно превратилось в имя собственное _NewLang_, -которое я и решил в конечном итоге оставить (что еще раз подтверждает поговорку, что нет ничего более постоянного, чем что-то временное). - -**NewLang** - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические конструкции -с декларативным программированием и тензорными вычислениями для задач машинного обучения. - -Основной особенностью языка является легкий, логичный и непротиворечивый синтаксис, который основан не на использовании зарезервированных ключевых слов, -а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка). -Основные свойства и особенности языка: - -- Возможность работы как в режиме интерпретатора, так и компилятора. -- Динамическая и статическая типизация с возможностью указания типов в явном виде. -- Статическая типизация является условно строгой (автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных, например, целое число может быть автоматически преобразовано в вещественное, но не наоборот) -- Автоматическое управление памятью. -- ООП в виде явного наследования классов и [утиная](https://ru.wikipedia.org/wiki/Утиная_типизация) типизация. -- На уровне синтаксиса поддержка нескольких типов функций (обычные и [чистые функции без побочных эффектов](https://ru.wikipedia.org/wiki/Чистота_функции)). -- Необязательные и именованные параметры функций. -- Возможны вставки кода на языке реализации (С/С++). -- Простая интеграция с уже существующими программными библиотеками (в том числе импорт нативных переменных и функций из С/С++). -- Имеется REPL [read-eval-print loop — «цикл: чтение — вычисление — вывод»](https://ru.wikipedia.org/wiki/REPL). - -## Зачем нужен NewLang? -У всех современных языков программирования происходит постоянное развитие (читай усложнение) синтаксиса по мере выхода новых версий. -Это является своего рода, платой за появление новых возможностей и воспринимается пользователями как естественное явление. - -Но одновременно является и серьезной проблемой, т.к. с выходом новых версий добавляются новые ключевые слова и синтаксические конструкции, -что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки -и трудоемкости поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов. - -У NewLang сложность языковых конструкций естественно ограничена за счет разделения синтаксиса языка на две части, -что упрощает его изучение и использование. _Основной синтаксис_ — для написания программ в объектно-ориентированном (императивном) -и декларативном стилях, который основан не на зарезервированных ключевых словах, а на строгих грамматических правилах -и _Расширенный синтаксис_ — когда основного синтаксиса становится недостаточно, или требуется использовать языковую конструкцию языка реализации. - -Еще одно неудобство современных мейнстримовых языков, большинство из них были созданы до начала эпохи машинного обучения, -поэтому тензорные вычисления у них выполнены в виде отдельных библиотек, а не встроены в основной синтаксис языка и систему базовых типов. -У _NewLang_ тензорные вычисления доступны «из коробки» (используется библиотека [libtorch](https://pytorch.org/)), -а арифметические типы данных являются скалярами (тензорами нулевой размерности). - -### Основной синтаксис -Основной синтаксис _NewLang_ - простой и логичный за счет того, что он построен исключительно на грамматических правилах -и не использует каких либо зарезервированных ключевых слов, а все буквенно-символьные последовательности рассматриваются как идентификаторы -в которых можно использовать любые не-ASCII символы. - -> Идеализированная цель отказа от ключевых слов, приблизить чтение исходного текста программы к чтению обычного текста за счет использования знаков препинания при описании логики работы алгоритма. - -> Конечно _запятая_ человек может вычленять ключевые управляющие слова языка и _слеш_ или учитывать форматирование программы _запятая_ -> чтобы на их основе понимать синтаксические конструкции _запятая_ хотя при обычном чтении мы привыкли опираться именно на семантику -> знаков препинания _точка_ мы конечно можем писать знаки препинания и обычным текстом _точка_ но согласитесь _запятая_ что тогда -> _открытая скобка_ например _запятая_ вот такой вот текст _закрытая скобка_ будет очень не удобно читать _точка_ - -Названия встроенных типов или имена служебных функций системной библиотеки определяются конкретной реализацией языка, -поэтому не являются зарезервированными ключевыми словами и при необходимости могут быть переопределены, например, -для создания собственного, предметно-ориентированного диалекта ([DSL - domain-specific language](ru.wikipedia.org/wiki/Предметно-ориентированный_язык)), если в этом возникнет необходимость. -Но сама структура программы и логика выполняемого алгоритма все равно останутся понятны всем, кто знаком с правилами основного синтаксиса NewLang. - -**Пример скрипта Hello world! на NewLang** -~~~bash - #!./nlc --eval - # Определение функции hello - hello(str) := { - printf := @import('printf(format:Format, ...):Int'); # Импорт стандартной C функции - printf('%s\n', $str); # Вызов C функции с проверкой типов аргументов по строке формата - }; - hello('Привет, мир!'); # Вызвать функцию -~~~ -Вывод: Привет, мир! - -### Расширенный синтаксис -Расширенный синтаксис — это возможность вставить в текст программы NewLang исходный код на языке реализации. -Сейчас это С/С++, что позволяет использовать любые возможности этого мощного языка программирования. - -Обработка расширенного синтаксиса происходит на этапе компиляции приложения, а взаимодействие между основным и расширенным синтаксисами происходит за счет совместного использования идентификаторов, -которое полностью прозрачно для пользователя и подчиняется единым грамматическим правилам основного синтаксиса. - -### Еще немного примеров: -Любая последовательность вычислений возвращает результат выполнения последнего оператора. -Поэтому выполнение одной команды или последовательности команд всегда возвращает какой-либо результат, -а оператор возврата из функции необязателен, так как результатом будет значение последнего вычисленного выражения. - -**Создание переменных** -~~~bash - scalar := 42 - 42 -~~~ -~~~bash - tensor := [1,2,3,4,5,] # Тип тензора выводится автоматически - [1, 2, 3, 4, 5,]:Char -~~~ -~~~bash - str := '$1 string' - $1 string -~~~ - -**Арифметические операции** -~~~bash - tensor * 2 - [2, 4, 6, 8, 10,]:Short -~~~ -~~~bash - tensor * 20 - [20, 40, 60, 80, 100,]:Short -~~~ -~~~bash - tensor * 0.5 - [0.5, 1, 1.5, 2, 2.5,]:Double -~~~ -~~~bash - tensor / 2 # Результат деления — число с плавающей точкой - [0.5, 1, 1.5, 2, 2.5,]:Double -~~~ -~~~bash - tensor // 2 # Целочисленное деление без остатка - [0, 1, 1, 2, 2,]:Char</source> -~~~ -~~~bash - tensor % 2 # Целочисленный остаток от деления - [1, 0, 1, 0, 1,]:Char</source> -~~~ - -**Строковые операции** -~~~bash - str = 'сцепеление строк ' ++ str; - сцепеление строк $1 string -~~~ -~~~bash - str('строка как шаблон'); - сцепеление строк строка как шаблон string -~~~ - -### Преобразование тензоров -В эпоху машинного обучения тензоры являются основными элементами вычислений, -поэтому для конвертирования _данных_ в тензоры используется отдельная синтаксическая конструкция, -состоящая из двойных квадратных скобок **[[** _данные_ **]]**. Подробнее про особенности преобразования типов можно прочитать далее. - -~~~bash - tstr := [["Тест"]] # Создать тензор из строки широких символов - [1058, 1077, 1089, 1090,]:Int -~~~ - -~~~bash - t2 := [[ "Тест" ]]:Int[2,2] # Тоже самое, но тензор двухмерный - [ - [1058, 1077,], [1089, 1090,], - ]:Int</source> -~~~ - -~~~bash - StrWide(tstr) # Конвертировать тензор обратно в строку - Тест -~~~ - -~~~bash - Double(t2) # Изменить тип данных тезора - [ - [1058, 1077,], [1089, 1090,], - ]:Double -~~~ - -~~~bash - t3 := [[ t2 ]]:Char[4] # Преобразовать тип данных тензора и его размерность - [34, 53, 65, 66,]:Char -~~~ - -## Синтаксис NewLang: -При разработке синтаксиса я старался придерживаться уже сложившихся правил, чтобы не создавать множественных смыслов, -зависящих от контекста. ~~И одновременно «объять необъятное»~~ - -### Основы - -- Операторы разделяются точкой с запятой «;». -- Отступы и переводы строк игнорируются (очень хотелось иметь возможность автоматического форматирование кода). -- Многострочные комментарии в исходном коде соответствуют стилю С/С++ и должны располагаться между символами /* и */. Вложенность многострочных комментариев не поддерживается. -- Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash. -- Последовательность выполняемых команд, которая должна выполняться как единое целое, заключается в фигурные скобки «{}». -- Программные вставки расширенного синтаксиса на языке реализации заключается в фигурные скобки со знаком процента **%{** _/* тут может быть любой код на C/C++*/_ **%}**. - -### Создания объектов и присвоения новых значений -Для создания объектов и присвоения им новых значений в NewLang используется сразу три разных оператора. -Оператор «**::=**» используется только для создания новых объектов, а если объект с таким именем уже существует, то генерируется ошибка. -Оператор «**:=**» используется для тех же целей, но если объект с таким именем уже существует, то ошибки не происходит, -а новое значение присваивается уже существующему объекту. -И последний оператор «**=**» применяется только для присвоения значения уже существующим объектам, и если объект с указанным именем отсутствует, то тоже происходит ошибка. - -Использование трех разных операторов для создания/изменения объектов позволяет более гибко контролировать подобные операции и выявлять логические ошибки в коде на более раннем этапе. - -~~~cpp - var ::= 1.0; # Создать новую переменную var без указания типа - var = 100; # Присвоить новое значение уже существующей переменной - printf := @import('printf(format:Format, ...):Int'); /* Создать новый или переопределить - объект printf, который будет результатом выполнения глобальной функции @import */ -~~~ - -### Идентификаторы объектов и модификаторы -В качестве идентификаторов можно использовать буквы, цифры и знаки подчеркивания в любых комбинациях, при условии, -что первый символ идентификатора не является цифрой. - -В NewLang существует возможность указания области видимости и времени жизни объекта с помощью модификатора — специального символа перед -именем переменной. Это может показаться немного похожим на венгерскую нотацию, но в отличие от нее, -модификатор не имеет отношения к типу объекта и не является частью имени идентификатора. -К тому же в качестве модификаторов используется строго определённые символы, назначение которых определено заранее. - -Так, символ «**$**» в начале имени обозначает локальную переменную, время жизни которой ограничено текущей областью видимости и при её завершении локальная переменная уничтожается. -Символ «**@**» обозначает глобальную переменную, а сам объект сохраняет свое состояние даже после выхода из текущей области видимости. -Так же обозначаются и имена типов данных, например, при создания новых типов, а в качестве модификатора используется символа двоеточия «**:**» - -Семантика обращения к аргументам функций очень похоже на работу с аргументами в bash скриптах, где **$1** или **$arg** — порядковый номер -или имя аргумента (происходит обращение к локальным переменным в текущей области видимости). - -Использование модификаторов является обязательным только в двух случаях: - - При создании нового типа данных, так как типы всегда создаются в глобальной области видимости, а их символьные имена должны быть уникальными - - При обращении к объектам NewLang внутри программных вставок кода на языке реализации, так как они используется как маркеры при поиске идентификаторов NewLang в коде С/С++. - -В остальных случаях, для обращения к переменным указывать их модификаторы не обязательно. -И если при обращении к объекту модификатор не указан, то сперва ищется локальная переменная, а потом глобальная с таким же именем. -Причем, локальная переменная будет перекрывать глобальную. - -Так же следует иметь в виду, что компилятор может генерировать код для прямого обращения к локальным объектам уже на этапе компиляции, -тогда как для обращения к глобальным объектам, или если модификатор области видимости отсутствует, компилятор вынужден каждый раз встраивать runtime вызов функции поиска объекта в таблице символов. - -## Система типов -Так как система типов языка динамическая, то явное указание типа не влияет на размер переменной и является только своего рода логическим ограничением на возможность присвоения переменной значения другого типа. - -Информация о типах используется при проверке их совместимости, когда существующему объекту присваивается значение другого типа. -Такая операция возможна только когда типы совместимы между собой и допускают автоматическое приведение. -Это справедливо как во время парсинга/компиляции исходного теста, так и во время выполнения в режимах интерпретатора и/или скомпилированного файла. - -### Арифметические типы: -Арифметические типы данных являются тензорами - массивами чисел одного типа с произвольным количеством измерений и одинаковым размером столбцов в каждом. -Единичное число тоже тензор нулевого размера. - -Поддерживаются только знаковые целые числа, т.к. в беззнаковых числах особая нужда отсутствует, а проблем с ними можно найти очень много на ровном месте. - -**Проблемы беззнаковых чисел (из интернета)** -> Во-первых, вычитание двух беззнаковых чисел, например 3 и 5. 3 минус 5 равно 4294967294, -> т.к. -2 не может быть представлено как беззнаковое число. Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных -> значений со знаком и без знака. С++ может свободно преобразовывать числа со знаком и без знака, -> но не проверяет диапазон, чтобы убедиться, что вы не переполняете свой тип данных. -> -> В C++ всё же есть несколько случаев, когда можно (или необходимо) использовать беззнаковые числа. -> Во-первых, числа без знака предпочтительнее при работе с битами. Во-вторых, использование беззнаковых чисел связаных с индексацией массивов. - -Но это мой случай, так как индекс может быть отрицательным и даже не числом, а диапазоном или многоточием. -З.Ы. И даже зная об этом, все равно умудрился недавно словить баг с отрицательными индексами у словарей! - -Имена встроенных арифметических типов говорят сами за себя: Char, Short, Int, Long, Float, Double, ComplexFloat, ComplexDouble. -Отдельным типом идет логический тип Bool, который может принимать значения только 0 или 1 (false/true соответственно), -и в зависимости от выполняемой операции может быть отнесен к целочисленным типам, так и не входить в их состав. - -_(данный подход интерпретации логического типа данных был взят из библиотеки Torch)_ -~~~cpp -// Treat bool as a distinct "category," to be consistent with type promotion -// rules (e.g. `bool_tensor + 5 -> int64_tensor`). If `5` was in the same -// category as `bool_tensor`, we would not promote. Differing categories -// implies `bool_tensor += 5` is disallowed. -// -// NB: numpy distinguishes "unsigned" as a category to get the desired -// `bool_tensor + 5 -> int64_tensor` behavior. We don't, because: -// * We don't want the performance hit of checking the runtime sign of Scalars. -// * `uint8_tensor + 5 -> int64_tensor` would be undesirable. -~~~ - -В будущем планируется добавить классы чисел для длинной арифметики и дробей, для чего зарезервированы названия типов BigNum, Currency и Fraction. - -Доступ к элементам тензора происходит по целочисленному индексу, который начинается с 0. -Для многомерного тензора, индексы элемента перечисляются в квадратных скобках через запятую. -Поддерживается доступ к элементам через отрицательный индекс, который обрабатывается точно так же, -как в Python (-1 последний элемент, -2 предпоследний и т.д.). - -Литерал тензор в тексте программы записывается в квадратных скобках с обязательной завершающей запятой, т.е. [1, 2,] - это литерал одномерный тензор из двух чисел. -После закрывающей скобки тип тензора может быть указан в явном виде. Если тип не указан, то он выводится автоматически на основании указанных данных и выбирается минимально возможный байтовый размер, -который позволяет сохранить все значения без потери точности. - -Примеры: -~~~bash - $var_char := 123; # Тип Char выводится автоматически - $var_short := 1000; # Тип Short выводится автоматически - $var_bool := [0, 1, 0, 1,]; # Тензор из 4 элементов. Тип Bool выводится автоматически - $tensor[10,10]:Int := 1; # Тензор Int размером 2x2 инициализированный 1 - $scalar := $tensor[5,5]; # Присвоить скаляру значение указанного элемента тензора -~~~ - -### Строковые типы данных: -Поддерживаются два типа строк, StrWide - символьные (широкие) и StrChar — байтовые. Различия между ними заключается в типе единичного элемента. -У символьных строк единичным элементом является широкий символ wchar_t, а у байтовой строки единичным элементом является один байт (точнее char, т. е. байт со знаком). -Символьные строки литералы в исходном тексте записывается в «двойных кавычках», а байтовые строки в 'одинарных кавычках'. - -Количество элементов символьной строки возвращается в широких символах, а размер байтовой строки в байтах, поэтому и обращение к элементу строки по индексу происходит соответственно либо к символу, либо к байту. - -Важный момент. К любой переменной можно обратиться так же, как к функции (записав после её имени круглые скобки). -Результатом этой операции будет создание копии/клона объекта. Причем некоторые типы (словари, классы и символьные строки) можно использовать в качестве шаблона -при создании копии объекта с модифицированными свойствами, если новые и/или изменяемые значения указать в скобках, как аргументы при вызовах функций. -Так, если при создании копии в скобках указать набор новых данных, то результирующая копия будет содержать уже измененные данные. - -Например: -~~~bash -$template := "${name} $1"; # Обычная строка -$result := $template("шаблон", name = "Строка"); # result = "Строка шаблон" -~~~ - -### Составные типы данных: -#### Словарь -Словарь — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии -(он похож и на tuple и на структуру одновременно). Словари от тензоров отличаются тем, что являются только одномерными массивами, -но каждый элемент может содержать произвольное количество элементов любого типа, в том числе и другие словари. - -Доступ к элементам словарей происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. -Индекс также начинается с 0 и как у тензоров, тоже может быть отрицательным. - -Литерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, -т.е. (,) - пустой словарь, (1, 2= «2», name=3,). - -### Перечисление -Перечисление - это не отдельный тип данных, а обычный словарь, у которого все элементы имеют уникальные имена и целочисленные значение, -которое явно указывается при определении или вычисляется автоматически (на единицу больше предыдущего элемента). -У перечислений тип значения указывается сразу после закрывающей скобки через двоеточие (ONE=1, TWO=, THREE=): Int. - -#### Классы -Класс (реализовано частично) - тип данных, с помощью которого реализуется один из принципов ООП - наследование. -При создании экземпляра класса создается новая переменная, у которой сохраняется информацию о своем родителе -и которая наследует от него свойства и методы. Тип данных «класс» аналогичен словарю, -но все свойства обязаны иметь имена (хотя доступ к свойствам класса по индексу так же возможен). -Литерал с типом «Класс» в тексте программы записывается в круглых скобках без завершающей запятой, т. е. () - пустой класс, (1, 2= «2», name=3). - -Пока остальные детали классов до конца не реализованы, поэтому описывать их не буду, т. к. в итоговом варианте синтаксис классов и определения их методов могут поменяться. - -### Функции -Синтаксис NewLang поддерживать несколько типов функций (а в будущем и методов классов): обычные функции, чистые функции и простые чистые функции. - -Для всех типов функций поддерживаются аргументы по умолчанию. При создании функции, её аргументы указываются как в Питоне, -т.е. вначале идут обязательные аргументы, потом аргументы со значениями по умолчанию, -где имя аргумента отделяется от его значения по умолчанию знаком равно «=». -Если функция допускает обработку произвольного количества аргументов, то последним в списке параметров указывается многоточие. - -#### Обычная функция -Обычная функция — такие функции являются именно обычными функциями в понимании С/С++. -Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д. - -Внутри обычной функции можно обращаться к локальным и глобальным объектам, и они могут содержаться вставки на языке реализации, например, для вызова функций из внешних библиотек. - -Вставки на языке реализации оформляются в виде **%{** **%}** и могут содержать любой текст на С/С++, -а прямо из него можно обращаться к локальным и глобальным объектам NewLang так же, как и в обычном синтаксисе, -указывая первым символом имени соответствующий модификатор (**$** для локальных объектов и **@** для глобальных). - -Технически, такая программная вставка просто переносится трансплайтером непосредственно в исходный текст генерируемого файла, -а все идентификаторы NewLang специальным образом декорируются (добавляются специальные маркеры для их идентификации), -после этого исходный текст подается на вход обычному компилятору С++. -Для локальных объектов трансплайтер может генерировать код для прямого доступа к объекту на этапе компиляции, -а для работы с глобальными объектами вынужден использовать runtime вызовы функции поиска в таблице символов. - -Например: -~~~cpp -print(str) := { - %{ - printf("%s", static_cast<const char *>($str)); /* Прямой вызов С функции */ - %} -}; -~~~ - -#### Чистые функции -Чистая функция - это тоже обычная функция, только в том смысле, какой в него вкладывает функциональное программирование. -Создания чистой функции происходит с помощью оператора «:-». У чистой функции отсутствует доступ к контексту и глобальным объектам, -поэтому она может обрабатывать только те данные, которые были ей переданы в качестве аргументов. - -Программные вставки на языке реализации внутри чистых функций не запрещены и могут использоваться, например, для отладки. -Но делается это на страх и риск разработчика. Именно он отвечает за их «чистоту», например при вызове функций из внешних библиотек. - -~~~bash - Sum(arg1, arg2) :- {$arg1+$arg2;}; # Вернуть сумму аргументов -~~~ - -Так как в языке отсутствует оператор возврата данных из текущего блока выполнения (аналог оператора return <данные>), -то возвращаемым значением функции / блока кода всегда является результат выполнения последней операции. - -#### Простые чистые функции -Простые чистые функции — отдельный класс чистых функций, которые предназначены только для вычисления логического результата -(т.е. они являются предикатами) и их отличает упрощенная формой записи. -Тело простой чистой функции состоит из последовательности операторов, которые разделяются запятыми и заканчиваются, -как и любое выражение, точкой с запятой. Все операторы простой чистой функции всегда приводятся к булевому значению, -а итоговый результат функции вычисляется по одной из возможных логических операций: _И_, _ИЛИ_ и _исключающее ИЛИ_. - -Например: -~~~bash - func_and(arg1, arg2) &&= arg1==3, arg2 > 0; # Простая чистая функция Логическое И - func_or(arg1, arg2) ||= arg1==3, arg2 > 0; # Простая чистая функция Логическое ИЛИ - func_xor(arg1, arg2) ^^= arg1==3, arg2 > 0; # Простая чистая функция Исключающее ИЛИ -~~~ - -### Специальные типы данных: -#### None -None (пустой тип) — не содержит значения (точнее имеет одно значение None) и совместим с любым другим типом данных. -Указывается в тексте программы как один подчерк «_». Значение None имеют не инициализированные переменные -и при попытке чтения из такой переменной возникает ошибка. - -Тип переменной может быть явно указан или выведен автоматически из присваиваемого значения. -Присвоить новое значение уже инициализированной переменной можно только для совместимого типа, так как неявное преобразование типов не допускаются. - -~~~bash - $var := _; # Создать переменную со значением None - $var2 := var; # Ошибка!!! Нельзя прочитать неинициализированную переменную var - $var = 1000; # У переменной будет тип Short (минимальный размер для хранения значения) - $var = 0,5; # Ошибка!!! Short ← Float не совместимы - $var = _; # Очистить значение переменной - $var = 0,5; # Теперь можно, т. к. None совместим с любым типом -~~~ - -#### Диапазон (Range) -Диапазон (реализовано частично) — специальный тип данных, являющейся приблизительным аналогом типа «генератор» в Python. -К диапазону можно обращаться как к итератору и он будет поочередно выдавать элементы в указанном интервале с заданным шагом. -Диапазон в тексте программы указывается как два или три элемента через две точки, например 1..5 — диапазон от единицы до пяти с шагом по умолчанию 1. -В качестве параметров диапазона можно указывать не только литералы, но и имена переменных. -Например, 0,1.._$stop_..0,1 — диапазон от значения 0,1 до значения, указанного в переменной _$stop_ с шагом 0,1. - -Диапазон для целых чисел можно использовать в качестве индекса у тензоров (точнее, у любых объектов, которые допускают доступ к своим элементам по индексу, -т.е. тензоры, словари и текстовые строки). Фактический, это поведение аналогично slice в языке Python и array[1:5] -в Python означает тоже самое, что и array[1..5] в NewLang. - -В качестве индекса у тензоров еще можно указать произвольное количество измерений с помощью многоточия, т.е. -~~~bash - $tensor[…, 0] = 0; # Обнулить все первые элементы в каждом измерении. -~~~ - -#### Итераторы -Итераторы (в разработке) - самый сложный и неоднозначный тип данных для работы с элементами коллекций. -Для работы с итераторами зарезервированы символы "!" и "?", но сами итераторы пока не реализованы. - -### Преобразование типов -#### Явное приведение типов -Несмотря на динамическую типизацию языка, если тип переменной указан явно, то автоматическое приведение типов не выполняется, -и чтобы присвоить переменой значение не совместимого типа, требуется явное преобразование. - -Так как символьные названия типов относятся к деталям реализации, то явное преобразование в конкретный тип данных производится с помощью вызова функции с системным именем, -т. е. Bool(), StrWide(), Long и т. д. Причем у тензоров при таком преобразовании изменяется только тип данных, но размерность тензора не меняется. - -Для преобразования любого типа данных в строку ещё можно использовать оператор конкатенации строк, которой преобразует любой тип данных в строковое представление. -Но так как строковых типов два (байтовые и широкие строки), то тип строки определяется первым аргументом в операторе конкатенации, т. е. -~~~bash - "" ++ 123 # "123" - Строка широких символов - '' ++ 123 # '123' - Байтовая строка -~~~ - Или преобразовать любое значение в строковое с помощью строки-шаблона: -~~~bash - val := 12345; - "$1"(val) # Будет строка "12345" -~~~ - -#### Tensor comprehensions -В эпоху машинного обучения тензоры являются основным элементом вычислений, поэтому для конвертирования _данных_ в тензоры используется отдельная синтаксическая конструкция, -состоящая из двойных квадратных скобок **[[** _данные_ **]]**. Фактически это оператор и функция времени выполнения в зависимости от указанных между двойные квадратными скобками выражения. - -Чтобы преобразовать любую переменную в тензор (с учетом допустимости такого преобразования), её достаточно указать между двойными квадратными скобками. -Выражение **[[** _varibale_ **]]** - преобразует переменную _varibale_ в одномерный тензор с автоматическим выводом типа данных. -Для преобразования в одномерный тензор конкретного типа используется выражение **[[** _varibale_ **]]**:_Type_, где _Type- - любой из арифметических типов. - -Если требуется преобразовать переменную не в одномерный тензор, а в тензор конкретного типа и заданной размерности, -то это делается выражением [[ varibale ]]:Type[2,2], которая вернет тензор с размерностью 2х2 и типом Type у элементов. - -Внутри двойных квадратных скобок может быть не только любое выражение, но и литерал или диапазон. -В этом случае, они также раскрываются в тензор по таким же правилам. -В будущем планирую добавить возможность указания сразу нескольких значений через запятую для их объединения в один тензор. - -Примеры: -```python ->[[(1,2,3)]] # Тензор из словаря -[1, 2, 3,]:Char - ->[['first second']] # Байтовая строка в тензор -[102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char - -> [[(first='first', space=32, second='second')]] # Получаем тензор из словаря с такими же данными -[102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char - ->[[ 0 ... ]]:Double[10,2] # Тензор заданного формата с нулями -[ - [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], -]:Double - ->[[ rand() ... ]]: Int[3,2] # Тензор со случайными данными -[ - [1804289383, 846930886,], [1681692777, 1714636915,], [1957747793, 424238335,], -]:Int - ->[[ 0..10 ]]: Int[5,2] # Тензор из диапзона -[ - [0, 1,], [2, 3,], [4, 5,], [6, 7,], [8, 9,], -]:Int - ->[[ 0..0.99..0.1 ]] # Или даже так -[0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,]:Double</source> -``` - -## Операторы и управляющие конструкции -#### Операторы: - -Все операторы имеют парный оператор с присвоением значения. -- **+** и += сложение арифметических типов данных -- - и -= вычитание арифметических типов данных -- / и /= деление (результат число с плавающей точкой) -- // и //= целочисленное деление с округлением к меньшему числу (как в Python) -- * и *= умножение -- \*\* и \*\*= возведение в степень (он же используется и для повторения текстовых строк) -- ++ и ++= конкатенация строк с автоматическим приведением аргументов к стоковому типу (символ инкремента специально используется вместо одиночного плюса для того, чтобы в явном виде разделить конкатенацию строк и операторы арифметического сложения) - -#### Операторы сравнения: - -- <, >, <=, >= классические для сравнения скаляров -- ==, != операторы сравнения с автоматическим приведением совместимых типов для любых объектов -- ===, !== оператор точного сравнения для любых объектов (автоматического приведения типов не выполняется)s - - -### Проверки типов (в разработке): -Проверка имени класса «~» - немного похож на оператор instanceof в Java. -Левым оператором должен быть проверяемый объект, а правым оператором - название типа, строка литерал или объект строкового типа с именем класса. -Результатом операции будет истина, если правый операнд содержит название класса проверяемого объекта или он присутствует в иерархии наследования у проверяемого класса. -~~~bash - name := "class"; # Строка с именем класса - var ~ :class; - var ~ "class"; - var ~ name; - - (field1=«value», field2=2, field3=«33»,) ~~ (); # Истина (т. е. левый операнд словарь) - (field1=«value», field2=2, field3=«33»,) ~~ (field1=_); # Тоже истина (т. к. поле field1 присутствует у левого операнда) -~~~ - - -Утиная типизация «~~» - приблизительный аналог функции isinstance() в Python, который для простых типов сравнивает совместимость типа левого операнда по отношению к правому, а для словарей и классов в левом операнде проверяется наличие всех имен полей, присутствующих у правого операнда. т. е. -~~~bash - (field1=«value», field2=2, field3=«33»,) ~~ (); # Истина (т. е. левый операнд словарь) - (field1=«value», field2=2, field3=«33»,) ~~ (field1=_); # Тоже истина (т. к. поле field1 присутствует у левого операнда) -~~~ - -Строгая утиная типизация «~~~» - для простых типов сравнивается идентичности типов без учета совместимости, -а для составных типов происходит строгое сравнение всех свойств. Для данной операции, пустой тип совместим только с другим пустим типом! - -## Управляющие конструкции (в разработке) -### Условный оператор -В качестве оператора проверки условия используется синтаксическая конструкция, соответствующая по смыслу термину «следует», -т.е. тире и угловая скобка «->». Такая запись условного оператора очень похожа на математическую и легко объединяется в последовательности для проверки множественных условий вида «else if». - -В общем случае условный оператор имеет вид: -~~~bash - условие -> действие; - или - (условие) -> {действие}; - или - (условие1 || условие2) -> {действие} -> {действие иначе}; -~~~ - -Или расширенный вариант «else if», для наглядности записанный с отступами: -~~~bash - (условие1) -> {действие1} - (условие2) -> {действие2} - (условие3) -> {действие3} - -> {действие_иначе}; -~~~ - -### Операторы циклов (в планах) -_Операторы циклов пока в разработке , т. к. плотно связаны с итераторами._ - -Пока планирую для циклов использовать конструкции: (условие) **<-->** {тело цикла}; - -Или так: (условие) **->>** {тело цикла}; - -И хотя синтаксис мне не очень нравится, но я решил пока не ломать над этим голову и планирую попробовать несколько вариантов оформления циклов. - -#### Операторы прерывания потока выполнения команд (реализовано частично) -Оператором прерывания потока выполнения команд и возврата из текущей функции, т.е. самым близким аналогом оператора return -является оператор два символа минус «--». Но в отличие от классического return, оператор возврата не возвращает значения, -т.к. значение из любой функции или блока кода возвращается всегда и им является результат выполнения самой последней операции -(или None, если такая операция отсутствует). - -Пока не придумал, как оформлять оператор прерывания потока выполнения в случае ошибки (при его выполнении будет происходить генерация исключения), -поэтому, если будут предложения, пишите в комментариях к статье (и про оформление циклов тоже). - -### Обработка ошибок (в планах) -В самом начале работ я ориентировался на классический вариант обработки исключений, -который в обычных языках программирования обычно оформляется ключевыми словами _try_ .. _catch_ .. _finally_ с различными вариациями. -Но в условиях жестких ограничений на синтаксис языка, и невозможности использовать ключевые слова, -комбинировать символы для указания разных типов блоков при обработке исключений, было бы крайне сомнительной затеей. -Ведь основная цель разработки NewLang — простота и понятность кода, а тут с самого начала могут появиться комбинации скобочек, стрелочек, -палочек и других подобных символов. - -И тут в голову пришла очень простая мысль. А ненужно повторять логику обработки ошибок из классических языков программирования! -Ведь основная цель подобных синтаксических конструкций - выделить участок кода где возможно возникновение ошибки, -перехватить и обработать правильный тип исключения. -Ведь классические языки программирования изначально были жестко привязаны к машинному представлению данных в оперативной памяти компьютера -и тип данных для них играл принципиально важное значение. -Но это не является ограничением для языков с динамической типизацией! - -Поэтому, подход к обработке исключений планируется следующий: Программный код, который может привести к ошибке, заключается в двойные фигурные скобки -**\{\{** <i>любой код или вызов одиночной функции</i> **\}\}**, -а результат выполнения такого блока кода присваивается переменной. После этого анализируется возвращенное значение и тип исключения может обрабатываться обычным условным оператором. - -Наверно, это проще показать на примере: -~~~bash - $error := {{ # начало блока try - call_or_exception1(); - call_or_exception2(); - }}; # конец блока try - # Обычные условные операторы вместо типизированных блоков catch - ($error ~ :type1)->{ код обработки ошибки 1} - ($error ~ :type2)->{ код обработки ошибки 2}; -~~~ - -Самое удивительное, что при таком подходе значительно упрощается и семантика блоков _try_ **…** _finally_, которые вообще становятся не нужны. - -Исходный код на Java: -```java - try { - try { - throw new Exception("a"); - } finally { - throw new IOException("b"); - } - } catch (IOException ex) { - System.err.println(ex.getMessage()); - } catch (Exception ex) { - System.err.println(ex.getMessage()); - } -``` - -Эквивалентный ему на NewLang: -```bash -$catch := {{ - $finally := {{ - Error1("1"); - }}; - Error2("2"); # Строка выполнится даже при возникновении исключении Error1 - $finally; # Error1 вернется, если не будет Error2 -}} -($catch ~ :Error1) -> printf(«%s», $catch) -($catch ~ :Error2) -> printf(«%s», $catch); -``` - -## Как все это попробовать? -Сейчас сборка проекта реализована только под Linux и если кроме текстового описания захочется в живую поэкспериментировать на своей машине, то придется собрать интерпретатор из исходников самостоятельно. - -Так как текущий вариант предназначен первую очередь для отработки концепции, то часть из описанных возможностей пока не реализована (алгоритмические конструкции, наследование классов, итераторы, некоторые операции и т. д). - -Но можно поиграться с созданием переменных, вызовом функций и выполнением арифметических операций над данными, чтобы оценить синтаксис, основанный на правилах, и может быть, предложить свои собственные мысли и доработки для его улучшения. - -### Сборка REPL из исходников (пока только под Linux) -#### Подготовка репозитория -- Скачать [исходники](https://github.com/rsashka/newlang) -- Скачать и развернуть архив libtorch в каталоге contrib (PyTorch Build: Stable (1.10.*) -> Your OS: Linux -> Package: LibTorch -> Language: C++ / Java -> Compute Platform: CPU -> Download here (cxx11 ABI): libtorch-cxx11-abi-shared-with-deps-1.10.2+cpu.zip) -- Активировать и скачать исходники субмодулей (git submodule init && git submodule update) -- В каталоге _contrib_ запустить файл _build.sh_ для сборки библиотеки libffi -- В каталоге _core_ запустить файл _compile_syntax.sh_ для генерации файлов парсера и лексического анализатора. Может потребоваться установка утилит flex и bison. Если что, у меня установлены flex 2.6.4 и bison (GNU Bison) 3.7.4 - -#### Собрать -- Юнит-тесты (newlang_test): в каталоге core выполнить команду _make CONF=UnitTest_ -- Интерпретатор (nlc): в каталоге core выполнить команду _make CONF=Debug_ - -## Утилита nlc (NewLangCompiler) -В текущее время nlc поддерживать работу только в режиме интерпретатора (несмотря на название). -Для тестирования и простой проверки компилятор не нужен, хотя на первых порах я делал именно его. -Но трудоемкость работ по постоянной переделке под новый синтаксис оказалась очень высокой, поэтому на время первичной отладки языковых конструкций было принято волевое решение ограничиться интерпретатором, -как более простым и быстрым способом проверки различных гипотез, а разработку настоящего компилятора (в виде трансплайтера на язык С++), -отложить до окончательной проработки синтаксиса. - -## Планы на будущее -Естественное, одна статья и несколько маленьких примеров не дают исчерпывающей информации о возможностях языка. -Да и сами возможности пока не раскрыты в полной мере. -Ведь текущая версия, это скорее тестовая платформа для проверки декларируемых концепций и основного синтаксиса. - -Пока остаются не реализованными некоторые из заявленных возможностей и очень важных хотелок. -Но протестировать основной подход можно уже сейчас, и я буду благодарен за любую обратную связь и предложения. - -Если говорить о планах (естественно, в будущих версиях что-то может добавиться или измениться порядок их реализации), но в настоящий момент роадмап развития NewLang мне видится следующим образом: -- Доделать стандартные управляющие конструкции, обработку ошибок и итераторы. -- Доработать систему типов с учетом множественного наследования классов. -- Реализовать длинную арифметику и дроби. -- Сделать какую нибудь логическую игру (крестики нолики, судоку или что-то похожее) с алгоритмическим выбором следующего хода и его вычислением с помощью машинного обучения. -- Написать много разных примеров для оценки синтаксиса. -- Доработать синтаксис с учетом полученного опыта и обратной связи. -- Восстановить работоспособность компилятора для генерации исполняемых файлов. -- Сделать очередную большую чистку кода. -- Переработать и задокументировать получившуюся семантику языка с учетом всех возможностей и выпустить первую полнофункциональную версию NewLang. - - -[Ссылка на первую публикаци](https://habr.com/companies/timeweb/articles/651999/) \ No newline at end of file diff --git a/site/content/en/blog/parser-nuances.md b/site/content/en/blog/parser-nuances.md deleted file mode 100644 index 88870c58..00000000 --- a/site/content/en/blog/parser-nuances.md +++ /dev/null @@ -1,145 +0,0 @@ ---- -slug: parser-nuances -title: Нюансы разработки парсера для своего языка программирования -date: 2023-03-29 ---- - - -![КДПВ](/blog/langs.jpeg) - - - -Недавно прочитал на Хабре статью [Свой язык, или как я устал от ассемблера и С](https://habr.com/post/723400/), и невольно взглядом зацепился за один абзац: - -> Я решил не сильно париться, поэтому использовал библиотеку parglare. Она очень легкая и удобная, всем рекомендую. Для описания синтаксиса парсер принимает строку в соответствующем формате, использует регулярные выражения (не надо осуждать регулярки, они всесильны!). - -В результате решил опубликовать статью на основе своих старых записей еще с тех времен, когда идея [NewLang](https://newlang.net/) до конца еще не выкристаллизовалась, но уже хотелось писать реальный код и тестировать разные концепции. - -Ведь в жизни практически любого программиста может наступить момент, когда ему в голову приходит светлая идея - разработать свой собственный язык программирования. Может быть и не ради захвата мира, наравне с C/C++, Python или хотя бы PHP, а в качестве личного пет-проекта, с которым он, длинными зимними вечерами будет оттачивать собственное мастерство. - -А так как у любого языка (не только программирования), все начинается с анализа его грамматики, то самой первой задачей создателя будет выбор инструментов для синтаксического анализа исходного текста. - -Это история — заметки на память о муках выбора связки лексер-парсер для разбора грамматики NewLang. А так же попытка описать и систематизировать выводы об особенностях разных анализаторов с которыми пришлось поработать при выборе парсера для разбора грамматики у своего языка программирования. - -### Используемые термины. -Чтобы было понятно, о чем в дальнейшем пойдет речь. - -> Лексер — компьютерная программа или библиотека, в задачи которой входит разделить входной поток данных на отдельные, не связанные между собой отдельные фрагменты, которые принято называть токенами или лексемами. -> -> Парсер — на основе последовательности токенов выполняется синтаксический анализ, например строит абстрактное синтаксическое дерево (AST). - -## Заход № 1 - Flex + Bison - -[GitHub - westes/flex: The Fast Lexical Analyzer - scanner generator for lexing in C and C++](https://github.com/westes/flex) -[Bison - GNU Project - Free Software Foundation](https://www.gnu.org/software/bison/) - -После прочтения умных книжек я начал с классики Flex + Bison. Это старые и давно отработанные приложения с широчайшими возможностями по настройке с помощью которых можно описать синтаксис и получить исходные файлы лексера и парсера для языка практически с любой грамматикой. - -К сожалению, у этих старичков очень большой порог входа и тяжелая наследственность. Чего только стоит определение собственного класса лексера через `#define`, а так же отсутствие нормальной поддержки С++. Вынужденные танцы с бубном для пасинга отдельной строки, когда не требуется анализировать файл целиком и прочие не всегда очевидные проблемы и разные не понятные условности. - -Другими словами, через несколько недель безуспешных мучений я решил посмотреть альтернативы, а так как начальный файл лексики после экспериментов с Flex + Bison кое-как уже был сделан, то следующая связка была Flex + lemon. - -## Заход № 2 - Flex + Lemon - -[The Lemon LALR(1) Parser Generator](https://www.sqlite.org/lemon.html) - -Тут все оказалось до примитивности просто и понятно. Реально очень быстрый старт с боевыми примерами, очень наглядный и понятный способ записи правил (по сравнению с Bison). Все хорошо кроме одного, хорошее быстро заканчивается, если приходится анализировать более одной строки. - -По сути, Lemon с Bison, это как Инь и Янь. Lemon простой и удобный для работы с одной строкой (для этого он и создавался), а Bison супер-пупер-мега комбайн для парсинга файлов любых размеров. - -Поэтому, поиски связки лексер + парсер продолжились и после прочтения очередной статьи, что парсеры языков можно делать на регулярках, решил посмотреть, что есть в этом направлении: - -## Заход № 3 парсер на регулярках re2c - -Из описания [re2c](https://re2c.org/): -> По сути, на этой штуке можно писать лексические анализаторы прямо на коленке за несколько минут. - -```c++ - /*!re2c - re2c:define:YYPEEK = "*cursor"; - re2c:define:YYSKIP = "++cursor;"; - re2c:define:YYBACKUP = "marker = cursor;"; - re2c:define:YYRESTORE = "cursor = marker;"; - re2c:define:YYBACKUPCTX = "ctxmarker = cursor;"; - re2c:define:YYRESTORECTX = "cursor = ctxmarker;"; - re2c:define:YYRESTORETAG = "cursor = ${tag};"; - re2c:define:YYLESSTHAN = "limit - cursor < @@{len}"; - re2c:define:YYSTAGP = "@@{tag} = cursor;"; - re2c:define:YYSTAGN = "@@{tag} = NULL;"; - re2c:define:YYSHIFT = "cursor += @@{shift};"; - re2c:define:YYSHIFTSTAG = "@@{tag} += @@{shift};"; - */ -``` - -Показалось, что это самый удобный способ указания шаблонов для парсера! Достаточно описать в комментариях нужные шаблоны, напустить на исходный файл компилятор регулярок и все готово! Но нет, действительно, это только показалось. - -Ведь для простеньких парсеров или регулярных выражений **re2c** может быть и действительно хорош, но отлаживать синтаксис большого языка на регулярках слишком хлопотное занятие. - -После этого решил с ним не заморачиваться и посмотреть альтернативы классическим лексерам и парсерам. - -## Заход № 4 - flex (flexcpp) + bisoncpp - -Тогда как у традиционных flex + bison поддержка С++ реализована ~~через одно место~~ на уровне - работает и не трогай, то решил посмотреть их альтернативную реализация [flexcpp](https://gitlab.com/fbb-git/flexcpp) + [bisoncpp](https://gitlab.com/fbb-git/bisoncpp) с нативной поддержкой С++. - -Первое впечатление было, то что доктор прописал! - -Синтаксис записи лексики хоть немного и отличается от классической, но это не принципиально. Зато есть нативная и логичная поддержка С++ без оберток и выкрутасов, и как дополнительный плюс - более удобный синтаксис указания правил в парсере. Но и тут не обошлось без шероховатостей. - -В шаблонах правил bisoncpp не поддерживает юникод (хотя сам лексер-парсер с ним справляется на ура), и совсем не понятная ситуация с поддержкой. Как я понял, разработчиком является вроде бы один человек, но пообщаться с ним насчет ошибок при обработке русских символов так и не получилось.\* - -Потом еще одно непонятное поведение вылезло в другом месте. В результате решил отказаться от недружелюбной поддержки и посмотреть, какие есть еще варианты парсеров. - ---- -\*) Через два года мой тикет был закрыт с комментарием, что поддерживаются только ascii символы. - -## Заход № 5 - неродной парсер ANTLR - -От использования [ANTLR](https://www.antlr.org/) (от англ. ANother Tool for Language Recognition — «ещё одно средство распознавания языков») — генератора нисходящих анализаторов для формальных языков, я решил сразу отказать из-за того, что он написан на Java,. - -В этом нет никаких религиозных предпочтений, так как я искал генератор парсеров, который можно было бы сделать встроенным прямо в среду выполнения, а в случае с ANTLR и JRE это было бы затруднительно. - -Таким образом я опять вернулся к старичкам Flex и Bison, с которых все и начиналось. - -## Заход № 6, последний - возвращение к Flex + Bison - -Все описанные выше эксперименты заняли в общем итоге несколько месяцев, в результате которых были написаны килобайты исходного кода и тестовых примеров, прочитано десятки статей и как результат - возврат к изначальной связке Flex + Bison, но уже с солидным багажом опыта в применении различных вариантов лексеров-парсеров. - -Но самое главное, с пониманием того, что же в результате хочется получить, и очень большой базой тестовых примеров синтаксиса. - -## Выводы на память - -В итоге для себя решил следующее: если нужен простенький шаблонизатор, то идеальный вариант **re2c** (если почему-то не подходит **regexp**). Если требуется анализировать синтаксис сложнее обычных регулярок, но в одну строку, то идеальной будет связка flex+lemon, а если нужна серьезная артиллерия, то тут однозначно flex + bison. - -От связки flexcpp + bisoncpp отказался совсем. Что с поддержкой — не понятно, синтаксис от классики отличается не очень сильно (хотя тоже нужно ломать голову), а обход выявленных косяков не стоят того синтаксического сахара. - -И по итогам множества экспериментов с разными вариантами синтаксиса удалось сформулировать пару важных архитектурных моментов, которые могут очень сильно упростить жизнь создателям языком программирования: - -## Стратегия обработки ошибок синтаксиса - -Обычно принято обрабатывать синтаксические ошибки непосредственно в парсере и для этого есть определенный резон — в этом случае нет необходимости в каких либо дальнейших действиях, нужна только полностью описанная корректная грамматика. - -Но если грамматика языка очень сложная (привет C++), и её описание становится сложной задачей, то можно отказался и от анализа ошибок синтаксиса непосредственно в парсере! То есть, лучше сделать максимально широкую лексику (даже с теми вариантами, которые являются для языка ошибочными), но ловить эти ошибки уже при анализе AST! - -В этом случае, поддерживать описание грамматики языка становится значительно проще (меньше синтаксических правил, проще их формальное описание и т.д.), а самое главное, при описании грамматики не нужно думать про lval или rval, где можно указывать ссылку, а где нет — т. е. можно указывать все и везде, а вот анализ допустимости использования конкретных терминов будет выполняться позднее при анализе AST. - -*Отказа от полного анализа грамматики языка на уровне лексера — парсера и перенос проверки корректности синтаксических конструкций на этап разбора синтаксического дерева позволяет в разы, если не на порядки сократить и значительно упростить описание грамматических правил!* - -Подобное допущение очень полезно на начальном этапе создания языка (можно сосредоточиться на общей концепции, вместо постоянных правок в грамматике), а так же значительно упростить в будущем поддержку и/или расширение синтаксиса. - -## Макросы и модификация грамматики в Runtime - -Какими бы мощными не были flex+bison, но у этой связки есть одна архитектурная проблема. Логика flex и bison построена на конечных автоматах и изменить грамматику языка во время выполнения приложения невозможно, тем более Bison сам вызывает лексер для получения очередной порции данных и ему очень непросто подсунуть измененные данные прямо во время работы. А так хотелось сделать возможность раскрытия макросов и модификации синтаксиса за один проход анализатора! - -Для этого пришлось переделать логику работы flex+bison, чтобы парсер получал данные из лексера не напрямую из yylex, а через функцию — прокси. Эта промежуточная функция, складывает считанные лексемы во внутренний буфер. Данные в буфере анализируется на предмет наличия макросов и только после их раскрытия, лексемы отдаются в парсер из вершины буфера по одной за раз. Подробнее о макросах NewLang можно почитать [тут](/blog/2023/03/01/вариант-реализации-dsl-domain-specific-language-с-помощью-макросов/). - -## Самое главное при разработке грамматики! - -Но самый важный совет мне подсказал друг, который некогда участвовал в проекте по разработке парсера для языка программирования. И в правильности его совета - **пиши тесты для грамматики** - я убеждался уже множество раз. Даже так, **ПИШИ ТЕСТЫ ДЛЯ ГРАММАТИКИ**. - -Тесты для грамматики языка гораздо более важная вещь, чем любой из используемых инструментов. Только тесты позволяют убедиться в том, что новая фича в языке не сломала старые наработки. А если все же сломала, то в первую очередь нужно добавить новый тест, который бы фиксировал сломавшийся сценарий и только после этого можно будет со спокойной душой продолжать эксперименты с новыми грамматическими конструкциями. - -И удачи всем языкописателям! - - -[Ссылка на первую публикаци](https://habr.com/companies/timeweb/articles/724146/) - diff --git a/site/content/en/blog/prog-styles-same-time.md b/site/content/en/blog/prog-styles-same-time.md deleted file mode 100644 index e01aeda5..00000000 --- a/site/content/en/blog/prog-styles-same-time.md +++ /dev/null @@ -1,265 +0,0 @@ ---- -slug: prog-styles-same-time -title: Можно ли использовать декларативный и императивный стили написания программ одновременно? -date: 2021-07-26 ---- - -![КДПВ](/blog/matrix.jpeg) - -{{% pageinfo %}} - -Внимание!!! - -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. - -Актуальную версию синтаксиса языка можно посмотреть [тут](/docs/). - -{{% /pageinfo %}} - - -При разработке своего собственного языка программирования автор должен определиться, какими свойствами его язык должен обладать, -ведь в конечном итоге именно это и будет определять назначение языка и особенности его использования. -Причем некоторые свойства настолько сильно влияют на итоговую концепцию языка и его синтаксис, -что впоследствии их изменение невозможно в принципе, либо новый синтаксис получается очень запутанным и непонятным. -Наверно из-за этого многие свойства языков программирования рассматриваются и изучаются как взаимоисключающие. - -До недавнего времени я считал, что императивная и декларативная парадигмы написания программ являются антагонистами и взаимоисключающими понятиями. -Ведь выбор стиля написания кода, изначально определяется автором языка еще на стадии его проектирования и оказывает влияние на все последующие аспекты. - -Но сейчас я думаю, что это не верно. Императивный и декларативный стили программирования не являются взаимоисключающими, -а писать программы только в одной из указанных парадигм подталкивают правила синтаксиса, реализованные в языке! - -Другими словами, использовать только императивную или только декларативную парадигмы разработчик вынужден не потому, что он не умеет или не хочет писать код по другому, а из-за того, -что все более-менее мейнстримные языки программирования ориентированы на использование только одной парадигмы. -И выбор только одной парадигмы написания кода, это ограничение, которое навязано программистам создателями языка. -Ведь если они изначально ориентировались только на одну концепцию разработки кода, то и разрабатывали синтаксис языка в соответствии с этой парадигмой. - -Данная статья — размышление о совместимости декларативной и императивной парадигм программирования и возможности их одновременного использования в рамках одного языка программирования одновременно. - -## Что такое "Декларативное программирование"? -Вначале мне захотелось разобраться, а существуют ли чисто декларативные языки программирования? -Такие, которые могут полностью обходятся без императивных конструкций? - -Но чуть не споткнулся уже в самом начале, т.к. даже само определение «декларативное программировании», в вики описывается [следующим образом](https://ru.wikipedia.org/wiki/Декларативное_программирование): ->Декларати́вное программи́рование — парадигма программирования, в которой задаётся спецификация решения задачи, то есть описывается, что представляет собой проблема и ожидаемый результат. Противоположностью декларативного является императивное программирование, описывающее на том или ином уровне детализации, как решить задачу и представить результат. - - -Уже в изначальном определении закладывается противопоставление парадигм, а дальше идут рассуждения о «направлении» программирования. -И хоть вики сама и не является авторитетным источником информации, но даже такая заготовка статьи смогла показать направление поиска ответов на первый поставленный вопрос. - -И заставил задуматься один абзац в конце статьи следующего содержания: -> «Чисто декларативные» компьютерные языки зачастую неполны по Тьюрингу — так как теоретически не всегда возможно порождение исполняемого кода по декларативному описанию. -> Это иногда приводит к спорам о корректности термина «декларативное программирование» (менее спорным является «декларативное описание решения» или, что то же самое, «декларативное описание задачи»). - -Судя по наличию такой оговорки, ставится под сомнение наличие «чисто декларативных» языков. -И как только пришлось задуматься над это мыслью, то сразу стало очевидным, что какой бы декларативный язык программирования не существовал, -то в нем должна быть как минимум одна императивная конструкция, которая будет запускать поиск решения! -Ведь любой синоним слова «выполнить» или «запустить» по определению будет императивом! - -Например в языке Prolog, который обычно и приводят в качестве примера декларативного языка программирования, "замаскированным" императивным оператором является знак вопроса. -Он кажется естественным и логичным, как же без него? Но по своей сути, это императивная конструкция! - -Тоже самое касается и языка SQL. Он тоже как бы декларативный, но неожиданно все его команды являются императивными по сути. _SELECT_, _CREATE_, _ALTER_, _DROP_, _INSERT_, _UPDATE_, _DELETE_ и т. д., а декларативными являются только описания условий их выполнения! - -В результате, у меня так и не получилось найти чисто-декларативный язык программирования без императивных операторов (может быть, Вики права и такого языка программирования и вовсе не существует?). - -## А что отличает декларативные языки программирования от императивных? -Согласно определению, декларативными языками программирования их называют из-за возможности записать некие условия в декларативном стиле. -Но кроме этого, в декларативных языках как правило присутствует и некий внутренний механизм поиска решений. -Подобный "вычислитель" есть и в SQL и Prolog и во многих других декларативных языках. - -Интересно, а является ли внутренняя система поиска решений обязательным признаком декларативного стиля программирования или это только особенность конкретного языка программирования, которая не зависит от декларативного стиля написания кода? - -Чтобы проверить данные предположения, можно было попробовать написать классическую декларативную программу на императивном языке, у которого отсутствует внутренний механизм поиска решений. - -А заодно, таким образом можно будет и изучить вопрос, получится ли написать программу в декларативном стиле используя обычный императивный язык программирования? - -Для примера, решил попробовать повторить уже классическую программу в декларативном стиле на Прологе. - -```cpp - parent("Tom","Jake"). - parent("Janna","Jake"). - parent("Tom","Tim"). - male("Tom"). - male("Tim"). - male("Jake"). - female("Janna"). - - brother(X,Y):-parent(Z,X),parent(Z,Y),male(X),male(Y),X\=Y. - ? brother -``` - -Получилась вот такая функционально - эквивалентная программа на С++, которая максимально приближена по стилю к декларативному прототипу: -```cpp - enum sex_ { - male, - female - }; - - struct human; - typedef std::vector<human *> parent_; - - struct human { - const char *name; - sex_ sex; - parent_ parent; - }; - - human Tom{"Tom", male,{}}; - human Janna{"Janna", female,{}}; - human Jake{"Jake", male,{&Tom, &Janna}}; - human Tim{"Tim", male,{&Tom}}; - - std::vector<human *> humans{&Tom, &Janna, &Jake, &Tim}; - - - auto brothers = [](human * a, human * b) { - - auto intersec = [](parent_ &a, parent_ & b) { - for (auto elem_a : a) { - for (auto elem_b : b) { - if(elem_a && elem_b && elem_a == elem_b) { - return true; - } - } - } - return false; - }; - - return a && b && a != b && a->sex == male && b->sex == male && (intersec(a->parent, b->parent)); - }; - - for (auto a : humans) { - for (auto b : humans) { - if(brothers(a, b)) { - std::cout << a->name << " and " << b->name << "\n"; - } - } - } -``` - -Конечно, текст на С++ получается значительно многословней, чем вариант на Прологе, но по сути, это почти дословное повторение декларативного стиля написания кода. -Тем более, не стоит забывать про рассуждения в начале статьи об изначальном выборе концепции при создании языка -и "принуждении" программистов пользоваться только одной, изначально выбранной парадигмой разработки. - -**Таким образом, можно с высокой долей уверенности утверждать, что теоретически можно писать код одновременно в разных стилях.** - -Но что тогда мешает в рамках одного языка программирования писать с использованием императивного и декларативного стиля? -Неужели только убежденность создателей языков в том, что императивный и декларативный стили программирования являются взаимоисключающими? -И только из-за этого получаются языки программирования, синтаксис которых подходит для использования одной единственной парадигмы? - -_Но если это так, то что мешает попробовать разработать синтаксис языка программирования, в котором можно было бы использовать сразу императивный и декларативный стили программирования одновременно?_ - -## Что мешает совместить императивный и декларативный стили написания в рамках одной программы? -В любой компьютерной программе всегда существует разделение кода на описание данных и на языковые конструкции для их обработки, т.е. фактически это разделение **на данные** и **на функции**. -Мне кажется, что основная сложность, которая не дает использовать разные стили программирования в рамках одного языка, это необходимость разделять описываемые сущности на «данные» и «управляющие конструкции». -Ведь это свойство (необходимость разделения сущностей на "данные" и "функции"), является неотъемлемой частью любого языка программирования. - -Это не удивительно, ведь на заре становления ИТ индустрии, создатели первых языков программирования ориентировались исключительно на императивный стиль, потому что назначением любого компилятора было - преобразовать исходный текст программы в машинные инструкции. И на примерах модульного, структурного и объекто-ориентированного подходах показана и доказана необходимость оформления исполняемого кода в выделенные процедуры с последующей их группировкой в модули и классы. - -А декларативный стиль написания программ стал появляться только после создания высокоуровневых языков программирования. -И основная цель создания данных языков сместилась на поиск решения конечного пользователя, а не на упрощение генерации бинарных файлов с машинными инструкциями. -Если внимательно посмотреть на приведенные выше примеры кода, то можно заметить, что в них определения данных и операторы для их обработки идут вперемешку, (для примера на С++ это определение лямбд функции), что кардинально отличается от императивного подхода. - -Так может быть, основная особенность декларативного стиля как раз и заключается в том, что в нем не разделяются «данные» и «действия над данными»? -Или как вариант, можно не указывать выполняемые действия над данными вовсе (как в некоторых SQL конструкциях)? - -Может быть как раз именно эта особенность (возможность последовательной записи программного кода в соответствии с собственными логическими рассуждениями, -в которых могут перемежаться «данные» и «функции», как это происходит при человеческом мыслительном процессе), -не дает в полной мере реализовать возможность совмещения императивных и декларативных стилей программирования? - -_И если это так, тогда можно попробовать разработать такой синтаксис, который будет поддерживать определение как данных, так и декларацию функций в рамках единого потока языковых конструкций!_ - -## Проверка гипотезы в новом языке программирования -Для поверки данного предположения, я решил добавить в свой [новый язык программирования](/blog/2021/05/24/необычная-концепция-синтаксиса-языка-программирования/) -(синтаксис которого допускает определение функций в одном потоке с описанием обрабатываемых данных), недостающие алгоритмические конструкции, которые позволяли бы реализовать императивный стиль программирования, -несмотря на изначальную ориентацию только на декларативную парадигму. - -Правда с учетом изначальных ограничений синтаксиса нового языка (запрет на применение операторов в виде зарезервированных ключевых слов), -в качестве оператора проверки условия была выбрана синтаксическая конструкция, соответствующая по смыслу термину «следует», -т.е. тире и угловая скобка «**->**». - -В результате, условный оператор получился практически математический, который легко объединяется в последовательности для реализации проверки множественных условий вида «else if». -А для объединения сразу нескольких логического операторов между собой и для отделения их от последующего действия, операторы проверки условия можно заключать в круглые скобки. - -В общем случае условный оператор в новом языке программирования имеет вид: -~~~cpp - условие -> действие; - или - (условие) -> {действие}; - или - (условие1 || условие2) -> {действие} -> {действие иначе}; -~~~ - -Или расширенный вариант, для наглядности записанный с отступами: -~~~cpp - (условие1) -> {действие1} - (условие2) -> {действие2} - (условие3) -> {действие3} - -> {действие_иначе}; -~~~ - -Тогда и операторы циклов можно будет записать практически аналогично, только выбрав в качестве оператора, не оператор следования, -а следование с возвратом (раз уж нужно указывать циклическое действие). - -Цикл пока: -~~~cpp - (условие) <-> {тело цикла}; -~~~ -счетный цикл для работы с итератором: -~~~cpp - (счетчик_или_данные!)? <-> {тело цикла}; -~~~ - -В этом случае, решение тестового примера декларативной программы на Прологе можно будет легко оформить, как в императивном, так и в декларативном стилях одновременно! - -~~~bash - м := "муж."; - ж := "жен."; - human @= term(пол=, parent=[,]); - Tom @= human(пол=м); - Janna @= human(пол=ж); - Jake @= human(м, [&Tom, &Janna,]); - Tim @= human(пол=м, parent=[&Tom,]); - - - brother(h1, h2) &&= $h1!=$h2, $h1.пол==м, $h2.пол==м, $h1.parent & $h2.parent; - // Оператор «&» побитовое «И» для чисел или операция пересечения для множеств - - - // Запись алгоритма поиска решения в императивном стиле - (h1=human!, h2=human!)? <-> { - (brother(h1, h2)) -> { - @print($h1, $h2, «\n»); - } - }; - - // Краткая запись алгоритма поиска решения в императивном стиле - (h1=human!, h2=human!)? <-> - brother($h1, $h2) -> @print($h1, $h2, «\n»); - - // Запись поиска решения в декларативном стиле - brother(human!, human!)?; - -~~~ - -Примерно это и требовалось показать! - -### З.Ы. -Я почти закончил эксперименты с синтаксисом языка. -И теперь, после добавления в него недостающих алгоритмический конструкций (ветвления и циклов), планирую, -что следующая статья о новом языке программирования будет посвящена описанию его полного синтаксиса и публикации исходников прототипа компилятора для возможности поиграться на реальных примерах. - -### З.З.Ы -В [комментариях @gbg](https://habr.com/company/timeweb/blog/569422/comments/#comment_23301086) привел очень простой ответ на один из поднятых вопросов. -Причем в более элегантном виде и без написания кода! - -> Ну и пять копеечек про ООП. Как ни странно: -> -> 1) В нем таки есть декларативная часть, все эти pubic, private, virtual, etc -> 2) Эта декларативная часть, внезапно, элегантно позволяет реализовывать декомпозицию и управление сложностью. -> 3) При наличии перегрузок, можно поиграть в алгебраическое мышление, рассматривая взаимодействие двух объектов как бинарную операцию. -> -> Ух ты, ООП - это обкатанная практикой технология, которая совмещает декларатив с императивом и вроде позволяет освоившим ее вкусно кушать и мягко спать! - -[Ссылка на первую публикаци](https://habr.com/companies/timeweb/articles/569422/) diff --git a/site/content/en/blog/release-0.1.md b/site/content/en/blog/release-0.1.md deleted file mode 100644 index 6a5ce281..00000000 --- a/site/content/en/blog/release-0.1.md +++ /dev/null @@ -1,501 +0,0 @@ ---- -slug: release-v0.1 -title: Релиз языка программрования NewLang -date: 2022-06-24 ---- - -![КДПВ](/blog/langs.jpeg) - - -{{% pageinfo %}} - -Внимание!!! - -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. - -Актуальную версию синтаксиса языка можно посмотреть [тут](/docs/). - -{{% /pageinfo %}} - - -**NewLang** - это язык программирования высокого уровня, в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения. - -Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка). - -Новое по сравнению с [прошлым выпуском](https://habr.com/company/timeweb/blog/651999/): -- Реализованы все основные алгоритмические конструкции: проверка условий, различные варианты циклов, сравнение по образцу, прерывание последовательности команд и возврат данных, обработка ошибок и т.д. -- Переработан основной синтаксис для отдельных языковых конструкций. -- Реализованы большинство операций с переменными, включая операторы раскрытие списков и тензоров. -- Серьезно переработана система встроенных типов, реализованы функции для их преобразования и для определения данных (последнее можно назвать data comprehensions). -- Добавлены новые тесты и пр. - -<cut /> - -# Зачем нужен *NewLang*? -У всех современных языков программирования происходит постоянное развитие (читай усложнение) синтаксиса по мере выхода новых версий. Это является своего рода, платой за появление новых возможностей и воспринимается пользователями как естественное явление. - -Но одновременно является и серьезной проблемой, т.к. с выходом новых версий добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки и трудоемкости поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов. - -У *NewLang* сложность языковых конструкций естественно ограничена за счет разделения синтаксиса языка на две части, что упрощает его изучение и использование. - -*Основной синтаксис* — для написания программ в объектно-ориентированном (императивном) и декларативном стилях, который основан не на зарезервированных ключевых словах, а на строгих грамматических правилах и *Расширенный синтаксис* — когда основного синтаксиса становится недостаточно, или требуется использовать языковую конструкцию языка реализации. - -Еще одно неудобство современных мейнстримовых языков, большинство из них были созданы до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек, а не встроены в основной синтаксис языка и систему базовых типов. - -У *NewLang* тензорные вычисления доступны «из коробки» (используется библиотека [libtorch](https://pytorch.org/)), а обычные числа являются скалярами (тензорами нулевой размерности). - - -# Синтаксис NewLang -При разработке синтаксиса я старался придерживаться уже сложившихся в IT индустрии правил, чтобы не генерировать множественных смыслов, которые будут зависеть от контекста. - -**Основы** -- Операторы разделяются точкой с запятой «;». -- Отступы и переводы строк игнорируются (очень хотелось иметь возможность автоматического форматирование кода). -- Многострочные комментарии в исходном коде соответствуют стилю С/С++ и должны располагаться между символами /\* и \*/. Вложенность многострочных комментариев не поддерживается. -- Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash. -- Последовательность команд, которая должна выполняться как единое целое, заключается в фигурные скобки «{}». -- Программные вставки расширенного синтаксиса на языке реализации заключается в фигурные скобки со знаком процента %{ /\* тут может быть любой код на C/C++\*/ %}, как в лексерах lex и flex. - - -# Создания объектов и присвоения новых значений -Для создания объектов и присвоения им новых значений в NewLang используется сразу три разных оператора: -- **::=** используется только для создания новых объектов, а если объект с таким именем уже существует, то генерируется ошибка. -- **:=** используется для тех же целей, но если объект с таким именем уже существует, то ошибки не происходит, а новое значение присваивается уже существующему объекту. -- **=** применяется только для присвоения значения уже существующим объектам, и если объект с указанным именем отсутствует, то тоже происходит ошибка выполнения. - -Использование трех разных операторов для создания/изменения объектов позволяет более гибко контролировать подобные операции и выявлять логические ошибки в коде на более раннем этапе. - -``` -var ::= 1.0; # Создать новую переменную var без указания типа -var = 100; # Присвоить новое значение уже существующей переменной -printf := @import('printf(format:Format, ...):Int'); /* Создать новый или переопределить объект printf, который будет результатом выполнения глобальной функции @import */ -``` - -# Идентификаторы объектов и модификаторы -В качестве идентификаторов можно использовать буквы, цифры и знаки подчеркивания в любых комбинациях, при условии, что первый символ идентификатора не является цифрой. - -В NewLang существует возможность указания области видимости и времени жизни объекта с помощью модификатора — специального символа перед именем переменной. Это может показаться немного похожим на венгерскую нотацию, но в отличие от нее, модификатор не имеет отношения к типу объекта и не является частью имени идентификатора. К тому же в качестве модификаторов используется строго определённые символы, назначение которых определено заранее. - -- **$** - в начале имени обозначает локальную переменную, время жизни которой ограничено текущей областью видимости и при её завершении локальная переменная уничтожается. -- **@** - обозначает глобальную переменную, а сам объект сохраняет свое состояние даже после выхода из текущей области видимости. -- **:** - двоеточие вначале имени используется в качестве модификатора для указания типа. - -Семантика обращения к аргументам функций очень похоже на работу с аргументами в bash скриптах, где $1 или $arg — порядковый номер или имя аргумента (происходит обращение к локальным переменным в текущей области видимости). - -### Использование модификаторов является обязательным только в двух случаях: -- При создании нового типа данных, так как типы всегда создаются в глобальной области видимости, а их символьные имена должны быть уникальными. -- При обращении к объектам NewLang внутри программных вставок кода на языке реализации, так как они используется как маркеры при поиске идентификаторов NewLang в коде С/С++. - -В остальных случаях, для обращения к переменным указывать их модификаторы необязательно. И если при обращении к объекту модификатор не указан, то сперва ищется локальная переменная, а потом глобальная с таким же именем. Причем, локальная переменная будет перекрывать глобальную. - -Так же следует иметь в виду, что компилятор может генерировать код для прямого обращения к локальным объектам уже на этапе компиляции, тогда как для обращения к глобальным объектам, или если модификатор области видимости отсутствует, компилятор вынужден каждый раз встраивать runtime вызов функции поиска объекта в глобальной таблице символов. - -# Система типов -Так как система типов языка динамическая, то явное указание типа не влияет на размер переменной и является только своего рода логическим ограничением на возможность присвоения переменной значения другого типа. - -Информация о типах используется при проверке их совместимости, когда существующему объекту присваивается значение другого типа. Такая операция возможна только когда типы совместимы между собой и допускают автоматическое приведение. Это справедливо как во время парсинга/компиляции исходного теста, так и во время выполнения в режимах интерпретатора и/или скомпилированного файла. - -## Простые типы -### Арифметические значения -Арифметические типы данных являются тензорами — массивами чисел одного типа с произвольным количеством измерений и одинаковым размером столбцов в каждом. Единичное число тоже тензор нулевого размера. - -Поддерживаются только знаковые целые числа, т.к. в беззнаковых числах особая нужда отсутствует, а проблем с ними можно найти очень много на ровном месте. - -Проблемы беззнаковых чисел (из интернета): -> Во-первых, вычитание двух беззнаковых чисел, например 3 и 5. 3 минус 5 равно 4294967294, т.к. -2 не может быть представлено как беззнаковое число. Во-вторых, непредвиденное поведение может возникнуть при смешивании целочисленных значений со знаком и без знака. С++ может свободно преобразовывать числа со знаком и без знака, но не проверяет диапазон, чтобы убедиться, что вы не переполняете свой тип данных. -> В C++ всё же есть несколько случаев, когда можно (или необходимо) использовать беззнаковые числа. Во-первых, числа без знака предпочтительнее при работе с битами. Во-вторых, использование беззнаковых чисел связанных с индексацией массивов. - -Но это не мой случай, так как индекс может быть отрицательным и даже не числом, а диапазоном или многоточием. - -З.Ы. И даже зная об этом, все равно умудрился недавно словить баг с отрицательными индексами у словарей! - - -Имена встроенных арифметических типов говорят сами за себя: Char, Short, Int, Long, Float, Double, ComplexFloat, ComplexDouble. Отдельным типом идет логический тип Bool, который может принимать значения только 0 или 1 (false/true соответственно), и в зависимости от выполняемой операции может быть отнесен к целочисленным типам, так и не входить в их состав (данный подход интерпретации логического типа данных был взят из библиотеки Torch). -``` -// Treat bool as a distinct "category," to be consistent with type promotion -// rules (e.g. `bool_tensor + 5 -> int64_tensor`). If `5` was in the same -// category as `bool_tensor`, we would not promote. Differing categories -// implies `bool_tensor += 5` is disallowed. -// -// NB: numpy distinguishes "unsigned" as a category to get the desired -// `bool_tensor + 5 -> int64_tensor` behavior. We don't, because: -// * We don't want the performance hit of checking the runtime sign of Scalars. -// * `uint8_tensor + 5 -> int64_tensor` would be undesirable. -``` - -В будущем планируется добавить классы чисел для длинной арифметики и дробей, для чего зарезервированы названия типов BigNum, Currency и Fraction. - -Доступ к элементам тензора происходит по целочисленному индексу, который начинается с 0. Для многомерного тензора, индексы элемента перечисляются в квадратных скобках через запятую. Поддерживается доступ к элементам через отрицательный индекс, который обрабатывается точно так же, как в Python (-1 последний элемент, -2 предпоследний и т.д.). - -Литерал тензор в тексте программы записывается в квадратных скобках с обязательной завершающей запятой, т.е. [1, 2,] — это литерал одномерный тензор из двух чисел. После закрывающей скобки тип тензора может быть указан в явном виде. Если тип не указан, то он выводится автоматически на основании указанных данных и выбирается минимально возможный байтовый размер, который позволяет сохранить все значения без потери точности. - -*Примеры:* -``` -$var_char := 123; # Тип Char выводится автоматически -$var_short := 1000; # Тип Short выводится автоматически -$var_bool := [0, 1, 0, 1,]; # Тензор из 4 элементов. Тип Bool выводится автоматически -$tensor[10,10]:Int := 1; # Тензор Int размером 2x2 инициализированный 1 -$scalar := $tensor[5,5]; # Присвоить скаляру значение указанного элемента тензора -``` - - -## Строки -Поддерживаются два типа строк, StrWide — символьные (широкие) и StrChar — байтовые. Различия между ними заключается в типе единичного элемента. У символьных строк единичным элементом является широкий символ *wchar_t*, а у байтовой строки единичным элементом является один байт (точнее *char*, т.е. байт со знаком). Символьные строки литералы в исходном тексте записывается в «двойных кавычках», а байтовые строки в 'одинарных кавычках'. - -Количество элементов символьной строки возвращается в широких символах, а размер байтовой строки в байтах, поэтому и обращение к элементу строки по индексу происходит соответственно либо к символу, либо к байту. - -Важный момент. К любой переменной можно обратиться так же, как к функции (записав после её имени круглые скобки). Результатом этой операции будет создание копии/клона объекта. Причем некоторые типы (словари, классы и символьные строки) можно использовать в качестве шаблона при создании копии объекта с модифицированными свойствами, если новые и/или изменяемые значения указать в скобках, как аргументы при вызовах функций. Так, если при создании копии в скобках указать набор новых данных, то результирующая копия будет содержать уже измененные данные. - -*Например:* -``` -$template := "${name} $1"; # Обычная строка -$result := $template("шаблон", name = "Строка"); # result = "Строка шаблон" -``` - -## Системные -### :Pointer - указатель на системную область памяти -Так как любой программе приходится взаимодействовать с внешним миром, то по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип *Pointer*. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. Но можно вывести его значение, например для отладки. - -### :Plain - указатель на представление данных в бинарном виде -Для взаимодействия с внешними библиотеками требуется еще и обмен данными. И для этих целей служит тип данных *Plain* - который также является указателем, но на двоичное представление данных в единой области памяти. Конечно, если их можно представить в виде единого фрагмента. - -## Составные типы данных: -### Словарь -Словарь (:Dictionary) — набор данных произвольного типа с доступом к отдельным элементам по целочисленному индексу или по имени элемента при его наличии (он похож и на tuple и на структуру одновременно). Словари от тензоров отличаются тем, что являются только одномерными массивами, но каждый элемент может содержать произвольное количество элементов любого типа, в том числе и другие словари. - -Доступ к элементам словарей происходит по имени элемента, которое записывается через точку от имени переменной, либо по целочисленному индексу. Индекс также начинается с 0 и как у тензоров и тоже может быть отрицательным. - -Литерал с типом «словарь» в тексте программы записывается в круглых скобках с обязательной завершающей запятой, т. е. (,) — пустой словарь, (1, 2= «2», name=3,). - -### Перечисление, структура и объединение -*:Enum*, *:Struct* и *:Union* — это такие же словари, только на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера. - -### Классы -Класс (реализован частично) — тип данных, с помощью которого реализуется один из принципов ООП — наследование. При создании экземпляра класса создается новая переменная, у которой сохраняется информацию о своем родителе и которая наследует от него свойства и методы. Тип данных *:Class* аналогичен словарю, но все свойства обязаны иметь имена (хотя доступ к свойствам класса по индексу так же возможен). - -## Функции -Синтаксис NewLang поддерживать несколько типов функций (а в будущем и методов классов): обычные функции, чистые функции и простые чистые функции. - -Для всех типов функций поддерживаются аргументы по умолчанию. При создании функции, её аргументы указываются как в Python, т.е. вначале идут обязательные аргументы, потом аргументы со значениями по умолчанию, где имя аргумента отделяется от его значения по умолчанию знаком равно **=**. Если функция допускает обработку произвольного количества аргументов, то последним в списке параметров указывается многоточие **...** (три точки подряд) . - -### Обычная функция - -Обычная функция — такие функции являются именно обычными функциями в понимании С/С++. Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д. - -Внутри обычной функции можно обращаться к локальным и глобальным объектам, и они могут содержаться вставки на языке реализации*, например, для вызова функций из внешних библиотек. - -Вставки на языке реализации оформляются в виде %{ %} и могут содержать любой текст на С/С++, а прямо из него можно обращаться к локальным и глобальным объектам NewLang так же, как и в обычном синтаксисе, указывая первым символом имени соответствующий модификатор (*$* для локальных объектов и *@* для глобальных). - -Технически, такая программная вставка просто переносится трансплайтером непосредственно в исходный текст генерируемого файла, а все идентификаторы NewLang специальным образом декорируются (добавляются специальные маркеры для их идентификации), после этого исходный текст подается на вход обычному компилятору С++. Для локальных объектов трансплайтер может генерировать код для прямого доступа к объекту на этапе компиляции, а для работы с глобальными объектами вынужден использовать runtime вызовы функции поиска в таблице символов. - ---- -*) - Программные вставки на языке реализации обрабатываются только во время компиляции - -*Например:* -``` -print(str) := { - %{ - printf("%s", static_cast<const char *>($str)); /* Прямой вызов С функции */ - %} -}; -``` - -### Чистые функции - -Чистая функция — это тоже обычная функция, только в том смысле, какой в него вкладывает функциональное программирование. Создания чистой функции происходит с помощью оператора **:-**, а сам оператор заимствован из языка Пролог. У чистой функции отсутствует доступ к контексту и глобальным переменным, поэтому она может обрабатывать только те данные, которые были ей переданы в качестве аргументов. - -Программные вставки на языке реализации внутри чистых функций не запрещены и могут использоваться, например, для отладки. Но делается это на страх и риск разработчика. Именно он отвечает за их «чистоту», например при вызове функций из внешних библиотек. -``` -Sum(arg1, arg2) :- {$arg1+$arg2;}; # Вернуть сумму аргументов -``` - - -### Простые чистые функции -Простые чистые функции — отдельный класс чистых функций, которые предназначены только для вычисления логического результата (т.е. они являются предикатами) и их отличает упрощенная формой записи. Тело простой чистой функции состоит из последовательности операторов, которые разделяются запятыми и заканчиваются, как и любое выражение, точкой с запятой. Все операторы простой чистой функции всегда приводятся к булевому значению, а итоговый результат функции вычисляется по одной из возможных логических операций: И, ИЛИ и исключающее ИЛИ. - -*Например:* -``` -func_and(arg1, arg2) :&&= arg1==3, arg2 > 0; # Простая чистая функция Логическое И -func_or(arg1, arg2) :||= arg1==3, arg2 > 0; # Простая чистая функция Логическое ИЛИ -func_xor(arg1, arg2) :^^= arg1==3, arg2 > 0; # Простая чистая функция Исключающее ИЛИ -``` - - -## Специальные типы данных: - -### Пусто (:None) -**:None** (пусто) — не содержит значения (точнее имеет одно значение None) и совместим с любым другим типом данных. Указывается в тексте программы как один подчерк «_». None имеют не инициализированные переменные и при попытке чтения из такой переменной возникает ошибка. - -Тип переменной может быть явно указан или выведен автоматически из присваиваемого значения. Присвоить новое значение уже инициализированной переменной можно только для совместимого типа, так как неявное преобразование типов не допускаются. - -``` -$var := _; # Создать не инициализированную переменную -$var2 := var; # Ошибка!!! Нельзя прочитать неинициализированную переменную var -$var = 1000; # У переменной будет тип Short (минимальный размер для хранения значения) -$var = 0,5; # Ошибка!!! Short ← Float не совместимы -$var = _; # Очистить значение переменной -$var = 0,5; # Теперь можно, т. к. None совместим с любым типом -``` - - -### Диапазон (:Range) -Диапазон — специальный тип данных, являющейся приблизительным аналогом типа «генератор» в Python. К диапазону можно обращаться как к итератору и он будет поочередно выдавать элементы в указанном интервале с заданным шагом. Диапазон в тексте программы указывается как два или три элемента через две точки, например 1..5 — диапазон от единицы до пяти с шагом по умолчанию 1. В качестве параметров диапазона можно указывать не только литералы, но и имена переменных. Например, *0,1..$stop..0,1* — диапазон от 0,1 до значения, указанного в переменной $stop с шагом 0,1. - -Диапазон для целых чисел можно использовать в качестве индекса у тензоров (точнее, у любых объектов, которые допускают доступ к своим элементам по индексу, т.е. тензоры, словари и текстовые строки). Фактический, это поведение аналогично *slice* в языке Python и *array[1:5]* в Python означает тоже самое, что и *array[1..5]* в NewLang. - -В качестве индекса у тензоров еще можно указать произвольное количество измерений с помощью многоточия, т.е. -``` -$tensor[…, 0] = 0; # Обнулить все первые элементы в каждом измерении. -``` - - - -## Преобразование типов -### Явное приведение типов -Несмотря на динамическую типизацию языка, если тип переменной указан явно, то автоматическое приведение типов не выполняется, и чтобы присвоить переменой значение не совместимого типа, требуется явное преобразование. - -Так как символьные названия типов относятся к деталям реализации, то явное преобразование в конкретный тип данных производится с помощью вызова функции с именем типа, т.е. :Bool(), :StrWide(), :Long() и т.д. - -Для преобразования любого типа данных в строку ещё можно использовать оператор конкатенации строк, которой преобразует любой тип данных в строковое представление. Но, так как строковых типов два (байтовые и широкие строки), то тип строки определяется первым аргументом в операторе конкатенации/сцепления **++**. Также преобразовать любое значение в строковое можно с помощью строки-шаблона. - -``` -"" ++ 123; # "123" - Строка широких символов -'' ++ 123; # '123' - Байтовая строка - -val := 12345; # Число -"$1"(val); # Будет строка "12345" -``` - -Так как тензоры могут иметь больше одного значения, то и в качестве аргументов могут принимать их произвольное количество, а итоговым результатом будет тензор, в котором все переданные данные преобразованы к требуемому типу автоматически. - -*Примеры:* - -``` -> tstr := :Tensor("Тест"); # Создать тензор из строки широких символов -[1058, 1077, 1089, 1090,]:Int - -> t2 := :Tensor[2,2]("Тест"); # Тоже самое, но тензор указанной размерности -[ - [1058, 1077,], [1089, 1090,], -]:Int - -> :StrWide(tstr) # Создать символьную строку из тензора -Тест - -> :Double(t2) # Изменить тип данных тезора без изменения размерности -[ - [1058, 1077,], [1089, 1090,], -]:Double - -> t3 := :Char[4]( t2 ) # Изменить размерность тензора и его тип (в данном случае с частичной потерей данных) -[34, 53, 65, 66,]:Char - - ->:Tensor( (1,2,3,) ); # Тензор из словаря -[1, 2, 3,]:Char - ->:Tensor( 'first second' ) # Байтовая строка в тензор -[102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char - ->:Tensor( (first='first', space=32, second='second',) ) # Получаем тензор из словаря с такими же данными -[102, 105, 114, 115, 116, 32, 115, 101, 99, 111, 110, 100,]:Char - ->:Double[10,2]( 0, ...) # Тензор заданного формата с нулями, где многоточие повторяет последние указанные данные до получения тензора требуемого размера -[ - [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], [0, 0,], -]:Double - ->:Int[3,2]( ... rand() ...) # Тензор со случайными данными, где между многоточиями указана функция, которую следует вызывать каждый раз при получении нового элемента тензора -# Пришлось придумывать новую конструкцию, т.к. многоточие перед именем, это оператор раскрытия словаря, а многоточие после имени, это повторение последнего значения до конца заданной размерности. -[ - [1804289383, 846930886,], [1681692777, 1714636915,], [1957747793, 424238335,], -]:Int - ->:Int[5,2]( 0..10 ); # Создание тензора из диапазона -[ - [0, 1,], [2, 3,], [4, 5,], [6, 7,], [8, 9,], -]:Int - ->:Tensor( 0..0.99..0.1 ); # Или даже так -[0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,]:Double -``` - - -# Операторы и управляющие конструкции -## Операторы: -Все операторы имеют парный аналог с присвоением значения: - -- **+** и **+=** - сложение арифметических типов данных; -- **-** и **-=** - вычитание арифметических типов данных; -- **/** и **/=** - деление (результат число с плавающей точкой); -- **//** и **//=** - целочисленное деление с округлением к меньшему числу (как в Python); -- *\** и *\*=* - умножение; -- *\*\** и **\*\*=** - возведение в степень (он же используется и для повторения текстовых строк); -- **++** и **++=** - конкатенация строк с автоматическим приведением аргументов к стоковому типу (символ инкремента специально используется вместо одиночного плюса для того, чтобы в явном виде разделить конкатенацию строк и операторы арифметического сложения). - - -## Операторы сравнения: -- **<**, **>**, **<=**, **>=** - классические для сравнения скаляров -- **==** и **!=** - операторы сравнения с автоматическим приведением совместимых типов для любых объектов -- **===** и **!==** - оператор точного сравнения для любых объектов (автоматического приведения типов не выполняется) - - -## Проверки типа (имени класса объекта): -Для оператора проверки имени класса объекта используется символ тильда **~**. Он немного похож на оператор *instanceof* в Java. Левым операндом должен быть проверяемый объект, а правым — проверяемый тип, который можно указать строкой литералом, переменной строкового типа или именем проверяемого класса непосредственно. Результатом операции будет истина, если правый операнд содержит название класса проверяемого объекта или он присутствует в иерархии наследования. -``` -name := "class"; # Строковая переменная с именем класса -var ~ name; -var ~ :class; # Имя типа -var ~ "class"; # Строка литерал с именем типа -``` - -## Утиная типизация -Оператор утиной типизации, два символа тильны **~~** — приблизительный аналог функции isinstance() в Python, который для простых типов сравнивает непосредственную совместимость типа левого операнда по отношению к правому. А для словарей и классов в левом операнде проверяется наличие всех имен полей, присутствующих у правого операнда, т.е.: - -``` -(field1=«value», field2=2,) ~~ (); # Истина (т. е. левый операнд словарь) -(field1=«value», field2=2,) ~~ (field1=_); # Тоже истина (т. к. поле field1 присутствует у левого операнда) -(field1=«value», field2=2,) ~~ (not_found=_); # Ложь, т.к. поле not_found у левого операнда отсутствует -``` - -Строгая утиная типизация **~~~** — для простых типов сравнивается идентичности типов без учета совместимости, а для составных типов происходит сравнение всех свойств с помощью оператора строгого равенства. Для данной операции, пустой тип совместим только с другим пустим типом. - - -# Управляющие конструкции -К управляющим конструкциям языка NewLang относятся условный оператор, два вида циклов, оператор оценки выражения, оператор прерывания последовательности выполнения команд и перехват прерывания. Операторы проверки условий всегда указываются в квадратных скобках, а последовательность команд для выполнения - в фигурных. - -## Условный оператор -В качестве оператора проверки условия используется синтаксическая конструкция, соответствующая по смыслу термину «следует», т.е. тире и угловая скобка **->** или с двумя тире для большей наглядности **-->**. Такая запись условного оператора очень похожа на математическую и легко объединяется в последовательности для проверки множественных условий вида «else if». - -В общем случае условный оператор имеет вид: `[ условие ] -> действие;` или `[ условие ] -> {действие};` или `[ условие1 || условие2 ] --> {действие}, [_] --> {действие иначе};` - -Для наглядности записанный с отступами: -``` -[ условие1 ] -> { действие1 }, - [ условие2 ] -> действие2, - [ условие3 ] -> действие3, - [_] -> {действие_иначе}; -``` - - -## Оценка выражения -Синтаксическая конструкция с помощью которой реализуется аналог оператора switch выглядит следующим образом: -``` -[ $var ] ==> { - [1] -> { code }; # Выполнится проверка условия $var == 1 - [1, 2] -> { code }; # Выполнится проверка условия ($var == 1 || $var == 2) - [_] -> { code default }; # Ветка условия иначе -}; -``` - -Причем в качестве оператора для оценки могут быть использован любые имеющиеся операторы сравнения на равенство: -- **==>** - проверка на равенство с приведением типов; -- **===>** - проверка на точное равенство; -- **~>** - проверка типа (имени класса); -- **~~>** - утиная типизация; -- **~~~>** - строгая утиная типизация. - -И если в качестве оператора сравнения использовать оператор утиной типизации, то оценка выражения превращается в классический Pattern Matching: -``` -$value := (f1=1, f2="2",); -[ $value ] ~~~> { - [ (f1=_, ), (f1=_, f2=0, ) ] -> { code }; # Поле f2 отсутствует или число - [(f1=_, f2="",), (f1=_, f2='',)] -> { code }; # Поле f2 строка - [_] -> { code default }; # Код по умолчанию -}; -``` - - -## Операторы циклов -Для указания операторов циклов используются управляющие **->>** или **-->>** (с двумя стрелками по направлению от проверки условия к телу цикла). И в зависимости от расположения условия и тела цикла, он может быть с предусловием (*while*) или постусловием (*do while*). Хотя пока эти синтаксические конструкции не "отлежались" и их можно считать временными из-за того, что их легко перепутать с условным оператором, и, возможно, имеет смысл заменить разные операторы цикла одной единственной конструкцией вида: **<-->** или **<<->>**, которая сильнее отличается от оператора следования. - -Но в настоящий момент циклы реализованы вот так: -``` -[условие while] ->> { - тело цикла while -}; - -{ - тело цикла do while -} <<-- [условие do while]; -``` - -Реализация цикла foreach на примере суммирования всех элементов словаря (или одномерного тензора): - -``` -summa := 0; -dict := (1,2,3,4,5,); -[ dict ] -->> { # Условие цикла, пока есть данные - item, dict := ... dict; # Результат оператора раскрытия словаря - первый его элемент перемещается в item - summa += item; # Вычисление суммы всех элементов словаря -}; - -``` - - -## Операторы прерывания (возврата) -В качестве оператора прерывания/возврата используется два символа минус **--**. Оператор позволяет прервать выполнение последовательности команд и/или вернуть данные из текущей функции/блока кода и является самым близким аналогом оператора **return** и **throw** одновременно. Для того чтобы вернуть данные, их необходимо указать между двумя операторами прерывания, т.е. `--100--; # Вернуть указанное значение`. Если возвращаемое значение не указано явно, то будет возвращено значение *None*. - - -## Следование (блок кода/лямбда функция) -Алгоритмическая конструкция, которая отвечает последовательное выполнение нескольких команд/операторов и возвращающая результат выполнения последнего из них. Также, результатом выполнения может быть значение, которое возвращается с помощью оператора прерывания (возврата). Это очень похоже на классическую лямбда функцию, только она выполняется сразу во время определения, а в переменную сохраняется уже результат её выполнения. - -Следование без перехвата прерывания оформляется в виде последовательности обычных и фигурных скобок, т.е. `(){ run code };` или тоже самое, но сохраняет результата выполнения в переменной: `$result := (){ run(); code() };`. Но если внутри такой функции будет выполнен оператор прерывания, то она никогда вернет управления и не сохранит возвращаемое значение в переменой *$result*! - -Чтобы перехватывать прерывания, в том числе и возвращаемые значения, необходимо использовать конструкция следования с перехватом прерываний, которая оформляется в виде последовательности обычных и **двойных** фигурных скобок, т.е. `$error := (){{ run(); error();code() }};`. Такая конструкция перехватывает все возвраты и прерывания, если они возникают во время выполнения последовательности команд. В этом случае любой результат будет сохранен в переменной *$error* как при нормальном завершении, так и в случае возникновения ошибки. - -Для более тонкой настройки перехвата прерываний следует использовать типизированную конструкцию, когда в явном виде указывается, какие типы прерываний следует перехватывать. `$runtime := (){{ run(); error(); code() }}:ErrorRuntime;`. Такая конструкция вернет результат только в случае успешного завершения (когда с помощью оператора прерывания возвращается не типизированное значение, например, `--"Строка"--;`), или при создании прерывания с указанием конкретного типа **--:ErrorRuntime("Описание ошибки")--;**. А вот при возникновении любого другого типизированного прерывания, значение перехвачено не будет и все отработает как самый первый вариант, т.е. без перехвата прерывания и без сохранения возвращаемого значения в переменную. - - -## Стратегия обработки ошибок -Обработка ошибок состоит из комбинации двух элементов: оператора прерывания выполнения с указанием типа возвращаемого значения и алгоритмической конструкции следование с возможностью перехвата прерывания заданного типа. - -Это немного отличается от классического варианта обработки исключений, который в обычных языках программирования обычно оформляется ключевыми словами try… catch… finally с различными вариациями. Ведь основная цель подобных синтаксических конструкций — выделить участок кода, где возможно возникновение ошибки, перехватить и обработать правильный тип данных (исключений), т.к. **NewLang** не делает различий между операторами возврата и генерации исключения. - -### Подход к обработке исключений следующий: -Программный код, который может привести к ошибке, заключается в двойные фигурные скобки, а результат выполнения такого блока кода присваивается переменной. После этого анализируется возвращенное значение, например, оператором сравнения по образцу: - -``` -$result := (){{ # начало аналога блока try - $value := call_or_exception1(); - [условие1] -> { -- :Error -- }; - [условие2] -> { -- $value -- }; - $value := call_or_exception2(); -}}; # конец аналога блока try - -[$result] ~> { # Для сравнения по образцу использовать оператор проверки типа (имени класса) - [:ErrorParser] -> {Код обработки ошибок парсера}; - [:ErrorRunTime] -> {Код обработки ошибок времени выполнения}; - [:Error] -> { Код обработки остальных ошибок }; - [_] -> { Обработка нормальных данных $value без ошибок }; -}; -``` - - -## Сборка REPL из исходников (пока только под Linux) -### Подготовка репозитория -- [<u>Скачать исходники</u>](https://github.com/rsashka/newlang) -- Скачать и развернуть архив [libtorch](https://pytorch.org/) в каталоге *contrib* (PyTorch Build: Stable (1.10.*) -> Your OS: Linux -> Package: LibTorch -> Language: C++ / Java -> Compute Platform: CPU -> Download here (cxx11 ABI): -[libtorch-cxx11-abi-shared-with-deps-1.10.2+cpu.zip](https://download.pytorch.org/libtorch/cpu/libtorch-cxx11-abi-shared-with-deps-1.10.2%2Bcpu.zip)) -- Активировать и скачать исходники субмодулей (`git submodule init && git submodule update`) -- В каталоге *contrib* запустить файл `build.sh` для сборки библиотеки libffi -- В каталоге *core* запустить файл `compile_syntax.sh` для генерации файлов парсера и лексического анализатора. Также может потребоваться установка утилит *flex* и *bison*. Если что, у меня установлены flex 2.6.4 и bison (GNU Bison) 3.7.4 - -### Собрать -- Юнит-тесты (newlang_test): в каталоге *core* выполнить команду `make CONF=UnitTest`\* -- Интерпретатор (nlc): в каталоге *core* выполнить команду `make CONF=Debug`\* - ---- -\*) - Сборка проекта выполняется обычной утилитой make, но сборочные файлы генерируются автоматически в давно устаревшей версии NetBeans 8.2, т.к. это единственная универсальная среда разработки с поддержкой Makefile "из коробки", тогда как в текущей версии Apache NetBeans полноценная поддержка разработки на С/С++ вообще отсутствует. Начал постепенный переход на использование редактора VSCodium (аналога VSCode, в котором вычищена телеметрия от Microsoft) и генерацию скриптов сборки с помощью сmake, но этот процесс пока не завершен. - - -# Планы на будущее -Текущая версия языка значительно обогатилась возможностями, но все еще является тестовой платформой для проверки декларируемых концепций и основного синтаксиса. Если говорить о планах, то в настоящий момент роадмап развития NewLang следующий: -- Реализовать макросы для более привычного использования языка (за счет использования DSL); -- Добавить в арифметические типы длинные числа и дроби; -- Сделать какую-нибудь логическую игру (крестики нолики, судоку или что-то похожее) с алгоритмическим выбором следующего хода и его вычислением с помощью машинного обучения; -- Написать еще больше разных примеров для оценки синтаксиса; -- Зафиксировать синтаксис с учетом полученного опыта и обратной связи; -- Восстановить работоспособность компилятора для генерации исполняемых файлов; -- Сделать очередную большую чистку кода; -- Переработать и задокументировать получившуюся семантику языка с учетом всех возможностей и выпустить первую полнофункциональную версию NewLang. diff --git a/site/content/en/blog/release-0.2.md b/site/content/en/blog/release-0.2.md deleted file mode 100644 index 9bc91247..00000000 --- a/site/content/en/blog/release-0.2.md +++ /dev/null @@ -1,155 +0,0 @@ ---- -slug: release-v0.2 -title: Релиз языка программрования NewLang 0.2 -date: 2022-08-12 ---- - - -![КДПВ](/blog/langs.jpeg) - - -{{% pageinfo %}} - -Внимание!!! - -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. - -Актуальную версию синтаксиса языка можно посмотреть [тут](/docs/). - -{{% /pageinfo %}} - - -*NewLang* - это язык программирования высокого уровня в котором можно сочетать стандартные алгоритмические конструкции с декларативным программированием и тензорными вычислениями для задач машинного обучения. - -Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан не на использовании зарезервированных ключевых слов, а на строгой системе грамматических правил с использованием знаков препинания (в список которых входят и операторы языка). - -*NewLang* находится в процессе активного развития и это второй публичный релиз в котором добавлены существенные новые возможности и произошли некоторые изменения по сравнению с [предыдущей версией](https://habr.com/company/timeweb/blog/673176/). - - -## Особенности языка: -- Возможность работы как в режиме интерпретатора, так и компилятора*. -- Динамическая и статическая типизация с возможностью указания типов в явном виде. -- Статическая типизация является условно строгой (автоматическое приведение типов отсутствует, но допускается преобразование между некоторыми типами данных, например, целое число может быть автоматически преобразовано в вещественное или рациональное, но не наоборот). -- Автоматическое управление памятью. -- ООП в виде явного наследования классов и «утиная» типизация. -- На уровне синтаксиса поддержка нескольких типов функций (обычные и чистые функции без побочных эффектов). -- Необязательные и именованные параметры функций. -- Возможны вставки кода на языке реализации (С/С++)*. -- Простая интеграция с уже существующими программными библиотеками (в том числе импорт нативных переменных и функций из С/С++). -- Имеется REPL read-eval-print loop — «цикл: чтение — вычисление — вывод». - -## Новые глобальные фичи: -- Добавлены макросы. Теперь можно делать собственные языковые диалекты и использовать более привычную запись алгоритмических конструкций с использование ключевых слов. -Например, цикл -``` -[ cond ] <-> { - тело цикла -}; -``` -можно записать в более привычный нотации -``` -\while (cond) { - тело цикла -}; -``` - -- Добавлены итераторы для перебора элементов словарей или для запросов к другим контейнерам (например, к базам данных). На уровне базового синтаксиса поддерживается фильтрация данный, включая функциональный аналог LINQ за счет применения функций обратного вызова в качестве условия фильтра. -- Добавлен новый тип данных — рациональные числа с неограниченной точностью. Они записываются в виде обыкновенной дроби, у которой разделитель бекслеш, например единицу можно записать `1\1`, а число 0.5 как `1\2`. -- Реализован оператор распаковки словаря **…** (многоточие), который можно использовать чтобы передать несколько аргументов при вызове функции или для присвоения значения сразу нескольким переменным. -- Теперь оператор присвоения поддерживает установку значений сразу нескольким переменным. С правой стороны от оператора присвоения может находится одно или несколько значений или оператор распаковки словаря. Причем словарь может быть указан и с левой стороны от оператора присвоения и таким образом можно записать самый простой способ перебора всех его элементов, когда в цикле первый элемент словаря сохраняется в переменную *item*, а из самого словаря удаляется: -``` -[ dict ] <-> { - item, dict := ... dict; -}; -``` - -## Изменения в синтаксисе: -- Изменена запись циклов. Вместо двух разных типов с предусловием и постусловие, теперь используется единая форма записи, а тип цикла определяется взаимным расположением условия и его тела. -- Изменены названия арифметических и некоторых других типов данных на более логичные. В именах арифметических типов теперь указан их размер (Int8, Int16 … Float32, Float64 и т.д.). -- Многострочные комментарии стали вложенными - - -## Подробная информация о языке: -- [Основные правила синтаксиса:](/docs/syntax/) -- [Встроенные типы данных:](/docs/types/) -- [Операторы и управляющие конструкции:](/docs/ops/) - -## Примеры кода -<spoiler title="Привет, мир!"> -``` -#!../output/nlc --eval - -# Определение функции hello -hello(str) := { - - # Импорт стандартной C функции - printf := :Pointer('printf(format:FmtChar, ...):Int32'); - - # Вызов C функции с проверкой типов аргументов по строке формата - printf('%s', $str); - - # Возврат значения из функции hello - $str; -}; - -hello('Привет, мир!'); # Вызвать функцию -``` -Вывод (первая строка выводится с помощью printf, а вторая - возвращаемое значение функции hello): -``` - Привет, мир! - Привет, мир! -``` </spoiler> - -<spoiler title="Пример скрипта для вычисления факториала 1000"> -``` -#!../output/nlc --eval - -@fact := 1\1; # Рациональное число без ограничения точности -@mult := 1000..1..-1?; # Сделать из диапазона итератор для множителей от 1000 до 2 -[mult ?!] <-> { # Цикл, пока не закончатся данные итератора - # Получить текущий множитель и перейти на следующий элемент итератора - fact *= mult !; -}; -fact # Вывести итоговый результат -``` -Вывод: -``` -402387260077093773543702433923003985719374864210714632543799910429938512398629 -020592044208486969404800479988610197196058631666872994808558901323829669944590 -997424504087073759918823627727188732519779505950995276120874975462497043601418 -278094646496291056393887437886487337119181045825783647849977012476632889835955 -735432513185323958463075557409114262417474349347553428646576611667797396668820 -291207379143853719588249808126867838374559731746136085379534524221586593201928 -090878297308431392844403281231558611036976801357304216168747609675871348312025 -478589320767169132448426236131412508780208000261683151027341827977704784635868 -170164365024153691398281264810213092761244896359928705114964975419909342221566 -832572080821333186116811553615836546984046708975602900950537616475847728421889 -679646244945160765353408198901385442487984959953319101723355556602139450399736 -280750137837615307127761926849034352625200015888535147331611702103968175921510 -907788019393178114194545257223865541461062892187960223838971476088506276862967 -146674697562911234082439208160153780889893964518263243671616762179168909779911 -903754031274622289988005195444414282012187361745992642956581746628302955570299 -024324153181617210465832036786906117260158783520751516284225540265170483304226 -143974286933061690897968482590125458327168226458066526769958652682272807075781 -391858178889652208164348344825993266043367660176999612831860788386150279465955 -131156552036093988180612138558600301435694527224206344631797460594682573103790 -084024432438465657245014402821885252470935190620929023136493273497565513958720 -559654228749774011413346962715422845862377387538230483865688976461927383814900 -140767310446640259899490222221765904339901886018566526485061799702356193897017 -860040811889729918311021171229845901641921068884387121855646124960798722908519 -296819372388642614839657382291123125024186649353143970137428531926649875337218 -940694281434118520158014123344828015051399694290153483077644569099073152433278 -288269864602789864321139083506217095002597389863554277196742822248757586765752 -344220207573630569498825087968928162753848863396909959826280956121450994871701 -244516461260379029309120889086942028510640182154399457156805941872748998094254 -742173582401063677404595741785160829230135358081840096996372524230560855903700 -624271243416909004153690105933983835777939410970027753472000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000\1 -``` </spoiler> - -## Как посмотреть? -- [Загрузить собранный REPL и тесты (пока только под Ubuntu)](https://github.com/rsashka/newlang/releases/download/v0.2.0/nlc_bin.tar.xz) -- Для запуска бинарных файлов потребуются разделяемые библиотеки libLLVM-13 и libtorch: [архив только с нужными библиотеками](https://github.com/rsashka/newlang/releases/download/v0.2.0/nlc_so.tar.xz). -- Так же все можно собрать напрямую из исходников по инструкции в [репозитории](https://github.com/rsashka/newlang) \ No newline at end of file diff --git a/site/content/en/blog/release-0.3.md b/site/content/en/blog/release-0.3.md deleted file mode 100644 index bd5489fb..00000000 --- a/site/content/en/blog/release-0.3.md +++ /dev/null @@ -1,253 +0,0 @@ ---- -slug: release-v0.3 -title: Релиз языка программрования NewLang 0.3 -date: 2022-11-07 ---- - -![КДПВ](/blog/langs.jpeg) - - -{{% pageinfo %}} - -Внимание!!! - -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. - -Актуальную версию синтаксиса языка можно посмотреть [тут](/docs/). - -{{% /pageinfo %}} - - -NewLang — это язык программирования высокого уровня общего назначения. Основной особенностью языка является простой, логичный и не противоречивый синтаксис, который основан на строгой системе грамматических правил. За счет использования макросов, синтаксис языка легко расширяется до более привычного вида на основе ключевых слов. - -NewLang находится в процессе активного развития. Это третий публичный [релиз](https://github.com/rsashka/newlang/releases/tag/v0.3.0) в который добавлены новые существенные возможности по сравнению с предыдущей версией. - - -## Зачем нужен *NewLang*? -У всех современных языков программирования происходит постоянное развитие (усложнение) синтаксиса по мере выхода новых версий. Это является своего рода платой за появление новых возможностей и воспринимается пользователями как естественное явление. - -Но одновременно является и серьезной проблемой, так как с выходом версий добавляются новые ключевые слова и синтаксические конструкции, что неизбежно повышает порог входа для новых пользователей. Еще одним следствием этого процесса становится постоянное повышение сложности разработки и поддержки уже созданных программных продуктов, когда старый код дорабатывается с применением уже новых стандартов. - -У *NewLang* сложность языковых конструкций ограничена естественным образом за счет разделения синтаксиса языка на две части - это упрощает его изучение и использование. - -*Основной синтаксис* — для написания программ в объектно-ориентированном (императивном) и декларативном стилях, который основан не на зарезервированных ключевых словах, а на системе строгих [грамматических правил](/docs/syntax/). Имеется возможность расширения основного синтаксиса за счет использования макросов. *Расширенный синтаксис* — программные вставки на языке реализации (С/С++), когда основного синтаксиса становится недостаточно. - -Еще одно неудобство современных языков в том, что большинство из них были созданы до начала эпохи машинного обучения, поэтому тензорные вычисления у них выполнены в виде отдельных библиотек. Это же касается и вычислений с неограниченной точностью, которые так же требуют применения дополнительных библиотечных функций. - -У *NewLang* тензорные вычисления и рациональные числа неограниченной точности доступны «из коробки». Они поддерживаются на уровне синтаксиса для записи литералов соответствующих типов, а простые арифметические типы данных являются скалярами (тензорами нулевой размерности). Реализация тензорных вычислений сделана на базе библиотеки [libtorch](https://pytorch.org/), а рациональные числа с использованием [OpenSSL](https://github.com/openssl/openssl/blob/master/crypto/bn/README.pod). - - -## Новые глобальные фичи и изменения в синтаксисе: - -### Простые чистые функции удалены -Раньше я пытался использовать синтаксис предикатов из Пролога, в котором проверки условий записываются через запятую. Но эта идея оказалась провальной, а сами операторы просто ужасными (тестировал разные варианты, но каждый раз получал много отрицательных отзывов), поэтому сейчас решил полностью от них отказаться. - -Они получались не только сложными для восприятия, но и по факту не нужными, так как легко заменялись обычной функцией с комбинации обычных логических операций. - -### Зафиксирован синтаксис операторов проверки [условия](/docs/ops/if/) и [циклов](/docs/ops/while/). -Изменен и упрощен синтаксис операторов проверки условия (импликации) и цикла, для которых оставлено только по одному варианту. Проверка условия записывается в виде оператора математического следования **-->**, а цикл с помощью оператора **<->**. - -Но для упрощения записи можно пользоваться макросами, тогда в этом случае операции проверки условий и циклы превращаются в классические -``` -\if(...){ - ... -} \elif(...) { - ... -} \else { - ... -}; -``` -или -``` - \while( ... ){ - ... -}; -``` - -### Конструкция else у операторов цикла -Теперь оператор цикла **while** поддерживает конструкцию [**else**](/docs/ops/while/), которая выполняется если условие входа в цикл не было выполнено. *Это поведение отличается от аналогичных конструкций в языке Python, у которого секция **else** выполняется всегда, кроме прерывания цикла по break.* - -Ветка **else** у оператора цикла записывается так же как и ветка иначе в условном операторе, т. е. -``` -[ cond ] <-> { - ... -}, [_] --> { - ... -}; -``` -Или тоже самое, но с использованием макросов: -``` -\while(cond) { - ... -} \else { - ... -}; -``` - -### Пространства имен -В синтаксис NewLang добавлены [пространства имен](/docs/syntax/namespace/), в стиле очень похожим на С++. Имена разделяются двойным двоеточием, а для определение пространства имен, его нужно указать перед открывающейся фигурной скобкой. -``` -ns { - name { - var := 0; # Имя переменной будет ns::name::var - ::var := 1; # Переменная из глобального пространства имен - } -} -``` - -### Программные модули -Реализована концепция программных модулей - которая повторяет концепцию иерархического расположения файлов в структуре каталогов файловой системы, как в языках Python и Java. - -Имя модуля начинается на префикс **@**, а структура каталогов указывается через точку. Причем концепции программных модулей и пространства имен объединены, и полное имя переменой из предыдущего абзаца будет `@root.dir.module::ns::name::var`, где **root** и **dir** это каталоги в файловой системе, а **module** — имя файла. - -### Объектно ориентированное программирование -Реализована часть концепции ООП и добавлена поддержка [определения классов](/docs/types/class/) и их наследование, которая сейчас выглядит следующим образом: -``` -:NewClass := :Class() { # Новый тип (класс) - field := 1; - method() := {}; -}; -obj := :NewClass(); # Экземпляр класса -``` -Неожиданно для самого себя понял, что имея полный набор вариантов проверок при создании объектов (**::=** - создать новый объект, **:=** - создать новый или присвоить значение существующему, **=** - только присвоить значение, а если объект не существует будет ошибка), концепция переопределения наследуемых функций не требует вообще никаких ключевых слов: -``` -:NewClass2 := :NewClass() { # Новый класс на базе существующего - field ::= 2; # Будет ошибка, т. к. поле field уже есть в базовом классе - method() = {}; # Аналог override, т.к. method должен существовать в базовом классе -}; -``` - -### Прерывания, возврат и обработка ошибок -Изменена, а точнее полностью переделана идеология возвратов из функций и обработки ошибок. -Теперь она чем-то похожа на подход, примененный в Ruby. Любая последовательность команд заключенные в фигурные скобки (в том числе тело функции), рассматривается как блок кода у которого нет специального оператора аналога **return**, который возвращает какое либо значение. -Просто любой блок кода всегда возвращает последнее вычисленное значение (это чем то похоже на оператор «запятая» в языках C/C++). - -Для того, чтобы прервать выполнение кода используются две разные команды - прерывания, которые условно можно назвать *положительным* и *отрицательным* результатом. Что примерно соответствует семантике их записи. -"Отрицательное" прерывание записывается в виде двух минусов, а "положительное" прерывание в виде двух плюсов, т.е. **-\-** или **++**. - -По умолчанию данные операции возвращают пустое значение. Чтобы прерывание вернуло результат, возвращаемые данные нужно записывать между парой соответствующих символов, -т.е. **-\-** 100 **-\-**, что является близким аналогом оператора `return 100;` в других языках программирования, а **++**«Строка»**++** - аналогом `return «Строка»;`. - -Хотя более точным аналогом этих операторов будет все таки не **return**, а **throw**, -т.к. эти команды не только прерывают выполнение последовательности команд в блоке, но их еще можно «ловить». -Для этого используется блок кода с соответствующей семантикой, **{+** … **+}** - блок кода, -который перехватывает положительные прерывания и **{-** … **-}** - блок кода, который перехватывает прерывания, созданные операторами **--**. - -Подобная концепция (в явном виде не разделять возвраты из функций и обработку исключений), -хоть и выглядит немного необычной, но позволяет реализовывать несколько очень полезных финтов, -которые сложно реализуемые в обычных языках программирования. - -Например, возврат из нескольких вложенных функций без необходимости обрабатывать результат возврата каждой из них. -В этом примере функция *Test* перехватывает "положительные" прерывания из вложенных функций: -``` - Test0(arg) := { \if($arg==0) \return("DONE - 0"); «FAIL» }; - Test1(arg) := { \if($arg==1) \return("DONE - 1"); Test0($arg); }; - Test(arg) := {+ \if($arg >= 0) Test1($arg); $arg; +}; - - Test(0); # Вернет «DONE — 0» возврат из вложенной функции Test0 - Test(1); # Вернет «DONE — 1» возврат из вложенной функции Test1 - Test(2); # Вернет «FAIL» возврат из вложенной функции Test0 - Test(-2); # Вернет -2 — возврат из функции Test -``` -Есть еще блок `{* … *}`, который перехватывает оба типа прерываний. Такой блок кода поддерживает типизацию возвращаемого значения, что позволяет в явном виде указывать типы данных, которые нужно перехватывать. -Например, `{* ... *} :Type1` — будет перехвачено прерывание вида `++ :Type1 ++` или `--:Type1--`, что позволяет очень гибко формировать логику работы программы. - -Блоки кода с перехватом исключений также поддерживают оператор иначе (*\else*) который, по аналогии с оператором *\else* в циклах, выполняется только тогда, если прерывания не произошло. - -Можно указать сразу несколько типов, которые нужно перехватывать: -``` - {* - .... - *} <:Type1, :Type2, :Type3>; -``` - -## Бинарная сборка под Windws: -В текущем релизе версия clang повышена 15, а вызовы нативных функций опять реализованы с помощью libffi, что в итоге позволило собрать бинарную сборку не только под Linux, но и под Windows. И теперь чтобы поиграться с REPL read-eval-print loop можно скачать уже готовый бинарник. - - -## Подробная информация о языке: -- [Синтаксис *NewLang*](/docs/syntax/) -- [Подробное описание типов данных](/docs/types/) -- [Операторы и управляющие конструкции](/docs/ops/) -- [Вся документация по *NewLang* на одной странице](/docs/_print/) - -## Обратная связь -Если у вас появятся предложения по развитию нового или улучшению уже существующего функционала *NewLang*, [пишите](https://github.com/rsashka/newlang/discussions). - - -## Примеры кода - -``` -#!../output/nlc --eval -# Определение функции hello -hello(str) := { - # Импорт стандартной C функции - printf := :Pointer('printf(format:FmtChar, ...):Int32'); - # Вызов C функции с проверкой типов аргументов по строке формата - printf('%s', $str); - # Возврат значения из функции hello - $str; -}; - -hello('Привет, мир!'); # Вызвать функцию</code> -``` -Вывод (первая строка выводится с помощью printf, а вторая — возвращаемое значение функции hello): -``` - Привет, мир! - Привет, мир! -``` -Пример скрипта для вычисления факториала 1000 -``` -#!../output/nlc --eval - -fact := 1\1; # Рациональное число без ограничения точности -mult := 1000..1..-1?; # Сделать из диапазона итератор для множителей от 1000 до 2 -[mult ?!] <-> { # Цикл, пока не закончатся данные итератора - # Получить текущий множитель и перейти на следующий элемент итератора - fact *= mult !; -}; -fact # Вывести итоговый результат -``` -Вывод: - -<spoiler title="Много цифр"> -402387260077093773543702433923003985719374864210714632543799910429938512398629 -020592044208486969404800479988610197196058631666872994808558901323829669944590 -997424504087073759918823627727188732519779505950995276120874975462497043601418 -278094646496291056393887437886487337119181045825783647849977012476632889835955 -735432513185323958463075557409114262417474349347553428646576611667797396668820 -291207379143853719588249808126867838374559731746136085379534524221586593201928 -090878297308431392844403281231558611036976801357304216168747609675871348312025 -478589320767169132448426236131412508780208000261683151027341827977704784635868 -170164365024153691398281264810213092761244896359928705114964975419909342221566 -832572080821333186116811553615836546984046708975602900950537616475847728421889 -679646244945160765353408198901385442487984959953319101723355556602139450399736 -280750137837615307127761926849034352625200015888535147331611702103968175921510 -907788019393178114194545257223865541461062892187960223838971476088506276862967 -146674697562911234082439208160153780889893964518263243671616762179168909779911 -903754031274622289988005195444414282012187361745992642956581746628302955570299 -024324153181617210465832036786906117260158783520751516284225540265170483304226 -143974286933061690897968482590125458327168226458066526769958652682272807075781 -391858178889652208164348344825993266043367660176999612831860788386150279465955 -131156552036093988180612138558600301435694527224206344631797460594682573103790 -084024432438465657245014402821885252470935190620929023136493273497565513958720 -559654228749774011413346962715422845862377387538230483865688976461927383814900 -140767310446640259899490222221765904339901886018566526485061799702356193897017 -860040811889729918311021171229845901641921068884387121855646124960798722908519 -296819372388642614839657382291123125024186649353143970137428531926649875337218 -940694281434118520158014123344828015051399694290153483077644569099073152433278 -288269864602789864321139083506217095002597389863554277196742822248757586765752 -344220207573630569498825087968928162753848863396909959826280956121450994871701 -244516461260379029309120889086942028510640182154399457156805941872748998094254 -742173582401063677404595741785160829230135358081840096996372524230560855903700 -624271243416909004153690105933983835777939410970027753472000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000000000000000000\1 -</spoiler> - -## Как посмотреть? -- [Бинарная сборка и тесты под Windows](https://github.com/rsashka/newlang/releases/download/v0.3.0/nlc_win_64.zip) -- [Бинарная сборка и тесты под Ubuntu](https://github.com/rsashka/newlang/releases/download/v0.3.0/nlc_lin_64.tar.xz) -- Для запуска бинарных сборок потребуются разделяемые библиотеки libLLVM-15 и libtorch ([архив с библиотеками для Windows](https://github.com/rsashka/newlang/releases/download/v0.3.0/nlc_dll.zip)), ([архив с библиотеками для Ubuntu](https://github.com/rsashka/newlang/releases/download/v0.3.0/nlc_so.tar.xz)). -- Так же все можно собрать напрямую из исходников по инструкции в [репозитории](https://github.com/rsashka/newlang) \ No newline at end of file diff --git a/site/content/en/blog/release-0.4.md b/site/content/en/blog/release-0.4.md index e3e5f102..7f716ebf 100644 --- a/site/content/en/blog/release-0.4.md +++ b/site/content/en/blog/release-0.4.md @@ -1,23 +1,23 @@ --- slug: release-v0.4 -title: Релиз языка программрования NewLang 0.4 +title: Release of the programming language NewLang 0.4 date: 2023-06-06 #draft: true --- - -![КДПВ](/blog/langs.jpeg) - - -{{% pageinfo %}} - -Внимание!!! - -"nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии. - -Актуальную версию синтаксиса языка можно посмотреть [тут](/docs/). - -{{% /pageinfo %}} - - -ssssssssssssssssssssssssssssssssssssssssssssss \ No newline at end of file +## New features and changes in the syntax of NewLang +- Reworked the definition of object types using [prefix naming (sigils)](https://newlang.net/docs/syntax/naming/) +- Interrupting the execution flow and returning can now be done for [named code blocks](https://newlang.net/docs/ops/throw/). +- Simplified the syntax for importing [native variables and functions (C/C++)](https://newlang.net/docs/types/native/) +- Stabilized the syntax for [initializing tensor, dictionary, and function argument values](https://newlang.net/docs/ops/create/#comprehensions) with initial data. +- Added built-in macros for writing code using keywords in a [DSL style](https://newlang.net/docs/syntax/dsl/) + +## New compiler features (nlc) +- Completely redesigned the macroprocessor. +- Reworked the compiler architecture with division into parser, macroprocessor, syntax analyzer, interpreter, and code generator. + +## Miscellaneous +- The documentation [website](http://newlang.net) has been translated to [Hugo](https://gohugo.io/) and made bilingual. +- Instead of binary builds, a section [Playground and example code](https://newlang.net/playground/) has been added to the website for small experiments. +- Transition to clang-16 has been completed (transition to clang-17 and newer is planned after full implementation of coroutines and support for extended floating-point number formats). +- The number of project contributors has increased to more than one! diff --git a/site/content/en/blog/unusual-prog.md b/site/content/en/blog/unusual-prog.md deleted file mode 100644 index d91d9bb9..00000000 --- a/site/content/en/blog/unusual-prog.md +++ /dev/null @@ -1,211 +0,0 @@ ---- -slug: unusual-prog -title: Необычная концепция синтаксиса языка программирования -date: 2021-05-24 ---- - -![КДПВ](/blog/langs.jpeg) - -{{% pageinfo %}} - -Внимание!!! - -Данная статья содержит описание синтаксиса NewLnag предыдущей версии. - -Актуальную версию синтаксиса языка можно посмотреть [тут](/docs/). - -{{% /pageinfo %}} - - -Хочу представить на обсуждение читателей немного необычный концепт языка программирования, в котором отсутствует проблема, -присущая практически всем промышленным языкам - постоянное увеличение сложности синтаксиса языка из-за его естественного развития по мере выхода новых версий и добавления новых фич. -Эта проблема описана в статье ["Простое сложное программирование"](/blog/complex-prog/) и [Какая "идеальная" цель развития у языков программирования?](/blog/lang-final/) - -После нескольких экспериментов с синтаксисом, хочется проверить выработанную идею на широкой аудитории [Хабра](https://habr.com/companies/timeweb/articles/558738/), которая как нельзя лучше подходит для этих целей. - -Особенности языка: -- Низкий порог входа и естественное ограничение уровня сложности в течение длительного времени даже при условии постоянного развития самого языка. -- Возможность писать код программы как в декларативной, так и в императивной парадигме с использованием процедурного, модульного и объектно-ориентированного подхода. - -Ну и в соответствии с собственным наблюдением [Хабр — ума палата](https://habr.com/post/539674/), буду рад любым комментариям и предложениям, которые помогут протестировать или улучшить предлагаемое решение. - -## Введение -Первой необычной особенностью языка является полное отсутствие зарезервированных ключевых слов. -Точнее, планируется использовать только одно единственное ключевое слово (название языка), которое может быть как главной точкой входа в приложение, -так и способом доступа к настройкам языка под конкретную предметную область, например при необходимости реализации [DSL парадигмы](https://ru.wikipedia.org/wiki/Предметно-ориентированный_язык). - -В настоящий момент название языка не выбрано, поэтому для примеров используется просто слово _lang_, которое в будущем будет изменено. - -Данная особенность (отсутствие зарезервированных ключевых слов) реализуется за счет того, грамматика языка основана на использовании общеупотребительных символов и классических знаков препинания, -а все остальные букво-символьные последовательности при парсинге программы рассматриваются как "токены". - -Компилятор языка реализуется как [transpiler](https://ru.wikipedia.org/wiki/Транспайлер) - преобразование исходного кода программы, -написанной на одном языке программирования, в эквивалентный исходный код на другом языке. -Первые эксперименты с синтаксисом я начинал на Python, но после осознания необходимости разработки не только интерпретатора, -но и компилятора непосредственно в исполняемый код, решил остановиться на C++. Хотя в принципе, язык реализации может быть любым. - -Использование [транспиляции](https://ru.wikipedia.org/wiki/Транспайлер) при реализации компилятора решает сразу множество очевидных и не очень задач. -Сразу отпадает необходимость разрабатывать низкоуровневый компилятор в исполняемый процессорный код, -а в моем случае основным бонусом такого подхода становится возможность использования императивной парадигмы программирования за счет вставок кода непосредственно в исходный код приложения на языке реализации. - -И именно этот момент позволяет естественно разделить декларативный и императивный способ написания программы. -В этом случае в декларативной парадигме реализуется только одна из трех базовых управляющих конструкций, -необходимых и достаточных при реализации [любого алгоритма](https://ru.wikipedia.org/wiki/Структурное_программирование) — _следование_. - -Другими словами, в декларативном стиле описывается только _последовательность_ операций, которые следуют одна за другой, -но отсутствует возможность запрограммировать циклы или ветвление (переходы) по условию. -Из-за этого в декларативном стиле можно записать только следующие типы языковых конструкций: - -- комментарий -- определение переменной и присвоение ей значения -- создание объекта и назначение его свойствам значений по умолчанию -- создание функции (метода для всего класса объектов) -- вызов функции или итератора -- непосредственная вставка кода на языке реализации - -Так как цель текущей публикации - протестировать общую концепцию, то начну сразу с примеров без длинного описания подробностей, а некоторые нюансы буду комментировать по ходу дела. -Тем более, самая главная цель "низкий порог входа" само собой подразумевает возможность самостоятельно разобраться в синтаксисе. -Тем не менее, совсем без знаний языка реализации не обойтись и начальные знания в программировании на С/С++ все равно необходимы. - -## "Привет, мир!" в императивной парадигме -Определение обычной функции выполняется с помощью оператора присвоения ":=", а программный код на языке реализации (в данном случае на C++) -заключается в фигурные скобки. Простой пример вывода строки на экран выглядит примерно так: - -```cpp - print(str="") := { printf("%s", static_cast<char *>($str)); } -``` -Функция **print** с аргументом по умолчанию в виде пустой строки внутри себя вызывает обычный printf из стандартной библиотеки. - -Соответственно "Привет, мир!" в императивной парадигме программирования будет выглядеть тривиально: - -```cpp - #!/bin/lang - print(str="") := { printf("%s", static_cast<char *>($str)); }; - @print("Привет, мир!\n"); -``` -Из примера видно, что обращение к аргументам внутри С++ кода происходит с использованием символа **$**, который указывается вначале именованного аргумента. -Кроме этого, для доступа к аргументам функции можно обращаться по их порядковым номерам начиная с первого ($1, $2, $3 и т. д.). -Зарезервированный аргумент $0 содержит сам объект, метод которого вызывается или _nullptr_, если функция не принадлежит объекту. - -_Обычные_ функции являются именно обычными функциями в понимании С/С++. -Внутри них можно писать совершенно любой код, включая проверки условий, циклы, вызовы других функций и т.д. -Технически, код такой функции парсится на предмет замены использованных аргументов, -специальным образом декорируется её имя и добавляются специальные маркеры для идентификации содержимого. -После этого исходный текст готов для сборки обычным С++ компилятором для превращения в динамическую библиотеку -и после её загрузки функцию можно будет вызвать в любой момент (для вызова функции перед её именем необходимо указать символ **"@"**). - -Непосредственное выполнение файла в режиме интерпретатора происходит в два этапа. На первом этапе из текста программы генерируется временный С++ файл с исходным кодом всех функций, этот файл компилируется gcc и собирается динамическая библиотека. - -На втором этапе, собранная динамическая библиотека загружается средой выполнения, а исходный текст программы начинает последовательно выполнятся интерпретатором (все строки, за исключением определений функций). - -Есть еще вариант, когда вместо интерпретации кода программы, генерируется С++ файл не только для функций, но и для основной части приложения. -Тогда на выходе компилятора будет уже обычный бинарный файл, хотя в том случае оперативно поправить текст программы уже не получится. - -## Логическое программирование в декларативной парадигме -Так как самым известным языком логического программирования в декларативном стиле считается Prolog, -поэтому приведу простой пример программы Brother (поиска братьев) на Прологе и эквивалентный ему код на новом языке. - -Prolog: - -```bash - male("Tom"). - male("Tim"). - male("Jake"). - female("Janna"). - parent("Tom","Jake"). - parent("Janna","Jake"). - parent("Tom","Tim"). - - brother(X,Y):- parent(Z,X),parent(Z,Y),male(X),male(Y),X\=Y. -``` -Вывод: **(Jake, Tim) (Tim, Jake)** - -Тот же самый пример: - -```bash - #!/bin/lang - human:=@term(sex=,parent=); - Tom:=@human(male); - Janna:=@human(female); - Jake:=@human(male, (Tom, Janna,)); - Tim:=@human(sex=male, parent=(Tom,)); - - human::brother(test=human!) &&= $0!=$test, $0.sex==male, @intersec($0.parent, $test.parent); - - human.brother? -``` -Вывод: **[Tim.brother(Jake), Jake.brother(Tim),]** - -Надеюсь, что синтаксис интуитивно понятен, особенно при наличии эквивалентного кода на Прологе, но на всякий случай поясню отдельные моменты. - -```bash - human:=@term(sex=,parent=); -``` -В этой строке создается объект с именем "human" и двумя свойствами "sex" и "parent", -значения которых по умолчанию не определены, а родителем является системный объект "term". -Использование символа **"@"** в начале термина обозначает вызов существующей функции с параметрами, указанными в скобках. -В данном случае вызывается конструктор системного объекта "term", а возвращаемым результатом является новый термин "human", -который можно воспринимать как один экземпляр класса, так и как имя целого класса, если он будет выступать в качестве родителя для других объектов. - -```bash - Tom:=@human(male); - Janna:=@human(female); - Jake:=@human(male, (Tom, Janna,)); - Tim:=@human(parent=(Tom,), sex=male); -``` -Первые две строки создают объекты "Tom" и "Janna", у которых свойство "sex" установлено в значения "male" и "female" соответственно. -А в последней строке при создании объекта Tim значения свойств задается с указанием их имени. - -Конструкции _(Tom, Janna,)_ и _(Tom,)_, это определение константного литерала с типом словарь, которые присваиваются указанным свойствам. - -Чтобы определение словаря не путать с указанием аргументов при вызове функции, в нем содержится обязательная финальная запятая перед закрывающей скобкой. -Это правило (финальная запятая перед закрывающей скобкой) действует и при определении литерала массива, только для записи которого используются скобки не круглые, а квадратные (например **[,]** - пустой массив). -Основным отличием словаря от массива, заключаются в способах доступа к их элементам. -Для доступа к элементу массива используется целочисленный индекс, а в словаре может быть использован как индекс, так и имя элемента при его наличии. -Между словарем и массивом есть еще отличия, но сейчас они не принципиальны. - -И предпоследняя строка в примере: - -human::brother(test=human _!_) **&&=** _$0_ != _$test_, _$0_.sex==male, @intersec(_$0_.parent, _$test_.parent); - -это определение <i>простой чистой</i> функции "brother" для всех объектов, производных от "human". -Данная функция принимает один именованный аргумент "test", значением по умолчанию которого является _итератор_ объектов класса "human". - -Оператор **&&=** означает определение _простой чистой_ функции, т. е. функции без внешних зависимостей, -которая не имеет доступа к глобальному контексту, а результат выполнения которой является логическое значение, -которое вычисляется по схеме [логическое И](https://ru.wikipedia.org/wiki/Конъюнкция) для всех условий, указанных в теле функции через запятую. - -Выполнение и вывод результата выполнения программы происходит в строке -`human.brother?` - -Восклицательный и вопросительный знаки обозначают [итератор](https://ru.wikipedia.org/wiki/Итератор). Итератор "**!**" возвращает один текущий элемент из коллекции и передвигает указатель на следующий, -а итератор "**?**" возвращает сразу всю коллекцию объектов целиком. - -Другими словами при выполнении строки программы _human.brother **?**_ происходит последовательный перебор всей коллекции объектов типа "human", -где у каждого объекта выполняется функция "brother" с аргументами по умолчанию. -А так как в качестве аргумента по умолчанию указан итератор _human **!**_, то в качестве аргумента последовательно предается каждый из элементов указанного класса. -По сути, при выполнении этой строки происходит полный перебор всех возможных комбинаций объектов класса "human" каждый с каждым. - -> Более подробное описание работы итератора и причина выбора такого синтаксиса опубликовано в отдельной статье <a href="https://habr.com/company/timeweb/blog/559916/">Лаконичный итератор для декларативного синтаксиса</a> - -Результат выполнения будет состоять из тех пар объектов, для которых функция "brother" вернет истину, т.е. результат выполнения будет массив из двух пар объектов **[Tim.brother(Jake), Jake.brother(Tim),]**. - - -## Формулировка проверяемой концепции -Тестируемая концепция заключается в следующем. Синтаксис языка программирования состоит как бы из двух частей, -каждая из которых является относительно независимой и в тоже время они связаны между собой. - -Первая часть сложная — предназначена для описания алгоритмов в _императивном стиле_ на обычном языке программирования, -поэтому внутри функций разработчику доступны все возможности языка реализации. - -Вторая часть простая (по сравнению с первой) — предназначена только для логического описания задачи в _декларативном стиле_. -Именно эта часть используется для начального уровня использования, а естественное ограничение только на последовательное выполнение операторов -(т.е. отсутствие циклов и ветвлений) не доставляет чрезмерных сложностей в понимании исходного текста программы даже в будущем по мере развития языка. - -Связь между двумя вариантами синтаксиса прозрачна и реализуется за счет совместного использования переменных и функций, -декларация и обращение к которым происходит в едином стиле в обоих случаях за счет унификации синтаксиса на уровне использования знаков препинания. - -Сейчас я специально не привожу полного синтаксиса и подробного описания остальных возможностей языка, т.к. компилятор пока не готов для публичной презентации. -Но буду крайне благодарен за любой отклик или дельные предложения в отношении предложенной концепции. - -Особенно это касается возможных конфликтов по синтаксису в представленных примерах. diff --git a/site/content/en/docs/_index.md b/site/content/en/docs/_index.md index cf7ee875..e192282c 100644 --- a/site/content/en/docs/_index.md +++ b/site/content/en/docs/_index.md @@ -5,19 +5,12 @@ menu: {main: {weight: 20}} weight: 20 --- -Основные материалы по языку программирования NewLang. +{{% pageinfo %}} -Описание акутально для текущей версии 4.0 +The materials are in the process of being translated into English! +{{% /pageinfo %}} -clang-17 не поддерживает: -| Feature | Proposal | Available | -|-------------------|-------------------|---------------------------------------| -| Coroutines | P0912R5 |*Partial* Fully supported on all targets except Windows, which still has some stability and ABI issues. -| Extended floating-point types and standard names | P1467R9 | No -| Concepts | P0848R3 | Clang 16 (Partial) -| Modules | | No | +Basic materials on the NewLang programming language. - -### Начиная с C++ should adopt the same characters for C++26. -- Add **@**, **$**, and ` to the basic character set P2558R2 Yes \ No newline at end of file +The description is valid for the current [version 0.4](https://github.com/rsashka/newlang/releases/tag/v0.4.0) diff --git a/site/content/en/docs/syntax/_index.md b/site/content/en/docs/syntax/_index.md index 85a3a722..49230fb0 100644 --- a/site/content/en/docs/syntax/_index.md +++ b/site/content/en/docs/syntax/_index.md @@ -7,12 +7,9 @@ weight: 1 simple_list: true --- -- Операторы разделяются точкой с запятой «;». -- Отступы и переводы строк игнорируются. -- Однострочные комментарии начинаются с символа «#» до перевода строки, что соответствует комментариям в стиле Python и Bash. -- Многострочные комментарии соответствуют стилю С/С++ и должны располагаться между символами /\* и \*/. Многосточные комментарии могут быть вложенными. -- Последовательность команд [(блок кода)](/docs/ops/block/) заключаются в фигурные скобки "**{**" и "**}**". -- Большинство операторов являются выражениями и возвращают результат выполнения последней операции. - - - +- Operators are separated by a semicolon ";". +- Indentations and line breaks are ignored. +- Single-line comments start with the symbol "#" until the end of the line, following the style of Python and Bash comments. +- Multi-line comments follow the C/C++ style and should be enclosed between "/\*" and "\*/". Multi-line comments can be *nested*. +- Command sequences [(code block)](/docs/ops/block/) are enclosed in curly braces "**{**" and "**}**". +- Most operators are expressions and return the result of the last operation. \ No newline at end of file diff --git a/site/content/en/docs/syntax/dsl.md b/site/content/en/docs/syntax/dsl.md index 86a3d00d..1c51d741 100644 --- a/site/content/en/docs/syntax/dsl.md +++ b/site/content/en/docs/syntax/dsl.md @@ -6,239 +6,78 @@ weight: 200 --- -## DSL - ### Features of associative memory The syntax of the *NewLang* language is based on strict rules without the use of keywords, and no matter how logical it may seem, association by keywords is much easier to remember, for example, **if**, than the combination *minus minus right angle bracket* **-->**. Because of this, it makes sense to use not a "pure" basic syntax, but a more familiar dialect with the use of keywords. -### Syntax based on keywords -In the dsl.nlp file, there is a set of macros that expand the basic syntax of *NewLang*, based on rules, -with a set of predefined keywords as in classical programming languages. -And if necessary, they can be adapted or supplemented for your own domain. - - -## Константы -### Логические -- **true** - 1 -- **yes** - 1 -- **false** - 0 -- **no** - 0 - -### Системные имена -- **this** - Текущий объект (**$0**) -- **parent** - Родительский объект (**$$**) -- **last** - Результат выполнения последнего оператора (**$^**) - -!!!!!!!!- **args** - Все аргументы функции (**$\***) - -!!!!!!!!- **sys** - Системный контекст запущенной программы (**@@**) -!!!!!!!!- **current** - Текущий модуль (**@$**) -!!!!!!!!- **cmd** - Все аргументы выполняющегося приложения из командной строки (**@\***) - -!!!!!!!!!!1### Типовые функции и проверки -!!!!!!!!!!- **run('filename')** - Выполнить указанный файл (**@@('filename')**) -!!!!!!!!!!- **ifmain** - Проверка, если текущий модуль основной (**[@$.$0] -->** { ... }) -!!!!!!!!!!- **ifload** - Проверка, если текущий модуль загружается впервые (**[@$.__load__] -->** { ... }) - -### Операторы -- **match(cond)** - Оператор [оценки выражения](https://newlang.net/ops.html#оценка-выражения) -- **if(...)** - Первый условный оператор (**[\$*]-->** { ... }) -- **elif(...)** - Второй и все последующие (**,[\$*]-->** { ... }) -- **else** - Оператор *иначе* (**,[_]-->** { ... }) - -- **while(cond)** - Оператор цикла с предусловием (**[@$cond] <->** { ... } ) -- **dowhile(cond)** - Оператор цикла с постусловием ({ ... } **<->[@$cond]**) - -- **iter(obj, ... )** - Создание итератора ( **@$obj** ? (@$*) ) -- **next(obj, ... )** - Следующий элемент итератора ( **@$obj** ! (\$*) ) -- **curr(obj, ... )** - Текущий элемент итератора ( **@$obj** !? (\$*) ) -- **first(obj)** - Перейти на первый элемент итератора ( **@$obj** !! ) -- **all(obj)** - Получить сразу все элементы итератора ( **@$obj** ??) - - -### Прерывания -- **return** - Положительное прерывание (**++**) -- **return(...)**- Положительное прерывание с возвратом значения (**++** @$value **++**) - -- **error** - Отрицательное прерывание (**-\-**) -- **error(...)** - Отрицательное прерывание с возвратом значения (**-\-** @$value **-\-**) - -- **break+** и **break-** - Выход из цикла: -``` - while(...) {+ - ++ :Break ++ - +} - while(...) {- - -- :Break -- - -} -``` -- **continue+** и **continue-** - В начало цикла: -``` - while(...) {+ - ++ :Continue ++ - +} - while(...) {- - -- :Continue -- - -} -``` - - - - - -obj { - .field = 1; - .prop(); -}; - -#Python -# 1) without using with statement -file = open('file_path', 'w') -file.write('hello world !') -file.close() - - - -# 2) without using with statement -file = open('file_path', 'w') -try: - file.write('hello world') -finally: - file.close() - -open('file_path', 'w') { - .write('hello world !'); - .close(); -} - - -Python3 - -# using with statement -with open('file_path', 'w') as file: - file.write('hello world !') - - -# a simple file writer object - -class MessageWriter(object): - def __init__(self, file_name): - self.file_name = file_name - - def __enter__(self): - self.file = open(self.file_name, 'w') - return self.file - - def __exit__(self, *args): - self.file.close() - -# using with statement with MessageWriter - -with MessageWriter('my_file.txt') as xfile: - xfile.write('hello world') - - - - - -# a simple file writer object -:MessageWriter { - def __init__(self, file_name): - self.file_name = file_name - - def __enter__(self): - self.file = open(self.file_name, 'w') - return self.file - - def __exit__(self, *args): - self.file.close() -} - -# using with statement with MessageWriter - -MessageWriter('my_file.txt') { - .write('hello world'); -}; - - - - - - - -from contextlib import contextmanager - - -class MessageWriter(object): - def __init__(self, filename): - self.file_name = filename - - @contextmanager - def open_file(self): - try: - file = open(self.file_name, 'w') - yield file - finally: - file.close() - - -# usage -message_writer = MessageWriter('hello.txt') -with message_writer.open_file() as my_file: - my_file.write('hello world') - - +*NewLang* already contains a set of macros that extend the basic rule-based syntax of *NewLang*, +a set of predefined keywords as in classical programming languages, +which can be adapted or supplemented to suit your own subject area. +### Constants +- *@true* - 1 +- *@yes* - 1 +- *@false* - 0 +- *@no* - 0 -:MessageWriter(object) { - def __init__(self, filename): - self.file_name = filename - - @contextmanager - def open_file(self): - try: - file = open(self.file_name, 'w') - yield file - finally: - file.close() - -} +- *@this* или *@self* - Current object +- *@super* - Parent object +- *@latter* or *@last*- Result of the last operation -# usage -message_writer = MessageWriter('hello.txt') -with message_writer.open_file() as my_file: - my_file.write('hello world') +### Logical operators +- *@and* - Logical **AND** +- *@or* - Logical **OR** +- *@xor* - Logical **Exclusive OR** +- *@not(value)* - Logical negation +### Operators +- *@if(...)* - First conditional statement +- *@elif(...)* - Second and all subsequent conditional statements +- *@else* - Operator *otherwise* +- *@while(...)* - Loop operator with precondition +- *@dowhile(...)* - Loop operator with postcondition +- *@loop* - Infinite loop operator -# Приложения +- *@break $label* - Operator to break out of a named named block of code +- *@continue $label* - Jump operator to the beginning of a named block of code +- *@return( result )* - Operator for returning a value and exiting a function +- *@throw( error )* - Operator for creating an exception and returning an error +- *@match( ... )* - Expression evaluation operator +- *@case( ... )* - Pattern comparison operator +- *@default* - Selection operator -## Предопределенные макросы +- *@iter(obj, ... )* - Creating an iterator +- *@next(obj, ... )* - Get the next element of the iterator +- *@curr(obj, ... )* - Get the current iterator element +- *@first(obj)* - Go to the first element of the iterator +- *@all(obj)* - Get all elements of the iterator at once -При работе парсера *NewLang* автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. -Данные предопределенные макросы можно использовать как обычные константы. -- \_\_FILE\_\_ или \_\_FILE_NAME\_\_ - имя и полный путь текущего файла -- \_\_LINE\_\_ или \_\_FILE_LINE\_\_ - содержит номер текущей строки в файле -- \_\_FILE_TIMESTAMP\_\_ - дату и время последней модификации текущего файла в строковом представлении -- \_\_FILE_MD5\_\_ - md5 хеш текущего файла в строковом виде -- \_\_COUNTER\_\_ - целочисленный счетчик, который увеличивает свое значение при каждом обращении +## Predefined macros +When the *NewLang* parser is running, several reserved macros are automatically generated, +some of which correspond to preprocessor macros in C/C++. +These predefined macros can be used as regular constants. -- \_\_DATE\_\_ - дата начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов) -- \_\_TIME\_\_ - время начала запуска компилятора (имеет одно и тоже значение для всех обрабатываемых файлов) -- \_\_TIMESTAMP\_\_ - дату и время начала запуска компилятора (например: "Fri 19 Aug 13:32:58 2016") -- \_\_TIMESTAMP_ISO\_\_ - дату и время начала запуска компилятора в формате ISO (например: "2013-07-06T00:50:06Z") +- \_\_FILE\_\_ or \_\_FILE_NAME\_\_ - name and full path of the current file +- \_\_LINE\_\_ or \_\_FILE_LINE\_\_ - contains the number of the current line in the file +- \_\_FILE_TIMESTAMP\_\_ - date and time of the last modification of the current file in string representation +- \_\_FILE_MD5\_\_ - md5 hash of the current file in string form +- \_\_COUNTER\_\_ - an integer counter that increases its value with each access -- \_\_NLC_VER\_\_ - Страшая и младшая версия компилятора NewLang (8 битное число, по 4 бита на цифру) -- \_\_NLC_DATE_BUILD\_\_ - текстовая строка с датой сборки компилятора NewLang (например, "23.06.04 20:51:39") -- \_\_NLC_SOURCE_GIT\_\_ - текстовая строка с идентификатором исходных файлов NewLang git репозитория, использованных при сборке компилятора (например, "v0.3.0-fef8c371") -- \_\_NLC_SOURCE_BUILD\_\_ - дата сборки и git идентификатор исходных файлов NewLang одной текстовой строкой (например, "v0.3.0-fef8c371 23.06.04 20:51:39") +- \_\_DATE\_\_ - start date of the compiler launch (has the same value for all processed files) +- \_\_TIME\_\_ - start time of the compiler launch (has the same value for all processed files) +- \_\_TIMESTAMP\_\_ - date and time when the compiler started running (for example: "Fri 19 Aug 13:32:58 2016") +- \_\_TIMESTAMP_ISO\_\_ - date and time when the compiler started running in ISO format (for example: "2013-07-06T00:50:06Z") +- \_\_NLC_VER\_\_ - Older and younger version of the NewLang compiler (8-bit number, 4 bits per digit) +- \_\_NLC_DATE_BUILD\_\_ - text string with the build date of the NewLang compiler (for example, "06/23/04 20:51:39") +- \_\_NLC_SOURCE_GIT\_\_ - text string with the identifier of the NewLang git repository source files used to build the compiler (for example, "v0.3.0-fef8c371") +- \_\_NLC_SOURCE_BUILD\_\_ - build date and git identifier of NewLang source files in one text line (for example, "v0.3.0-fef8c371 06/23/04 20:51:39") \ No newline at end of file diff --git a/site/content/en/docs/syntax/macros.md b/site/content/en/docs/syntax/macros.md index 093b9cfb..e49f2b9e 100644 --- a/site/content/en/docs/syntax/macros.md +++ b/site/content/en/docs/syntax/macros.md @@ -1,559 +1,129 @@ --- -title: Макросы -# description: Правила синтаксиса языка -# date: 2017-01-05 +title: Macros weight: 50 --- +Macros are also used to transform the original code of *NewLang* into a more familiar syntax based on [keywords](/docs/syntax/dsl/), +as such text is much easier to understand when reading the original code later. -Макросы в **NewLang**, это один или несколько последовательных терминов, которые заменяются на другой термин -или на целую синтаксическую конструкцию (последовательность лексем). +In **NewLang**, macros are one or more consecutive terms that are replaced with another term or a whole syntactic construction (a sequence of lexemes). -Макросы обработываются во время работы **лексера**, т.е. перед передачей последовательности лексем в парсер, -что позволяет с их помощью изменять даже сам синтаксис языка, например, при реализации собственных диалектов DSL. +Macros are processed during the operation of the **lexer**, i.e., before passing the sequence of lexemes to the parser, +allowing fragments of the language syntax to be modified using macros, for example, when implementing custom DSL dialects. -### Определение макросов +### Defining Macros -Определение макросов аналогично [определению](/docs/ops/create/) других объектов и состоит из трех частей -**<имя макроса> <оператор создания/присвоения> <тело макроса>** и завершающая точка с запятой "**;**", -т.е. применяются обычные операторы **::=**, **=** или **:=** для создания нового или переопределения уже существующего объекта, -а имя макроса указывается между двумя символами **"@@"** и может содержать одну или нескольких лексем (терминов). +The definition of macros is similar to the [definition](/docs/ops/create/) of other objects and consists of three parts +**<macro name> <creation/assignment operator> <macro body>** and ends with a semicolon "**;**", i.e., +normal operators **::=**(**::-**), **=**, or **:=**(**:-**) are used to create a new or redefine an existing object, +and the macro name is indicated between two symbols **"@@"** and can contain one or more lexemes (terms). -Все макросы относятся к глобальному пространству имен, поэтому первый термин в имени макроса должен быть уникальным, -иначе он будет прекрывать имена локальных и глобальных переменных при [разрешении имен](/docs/syntax/naming/), -если они указаны в коде без квалификаторов. +All macros belong to the global namespace, so the first term in the macro name must be unique, +otherwise it will override local and global variables during [name lookup](/docs/syntax/naming/#name-lookup) +if they are written in the program text without [qualifiers (sigils)](/docs/syntax/naming/#sigil). -??????????????????????? -Чистые (гигиеничные) макросы, **::-** **:-**, аргумента и переммые в которых гарантиованно не пересекаются с пространством имен программы????????????????? +Using the operators **::-** and **:-** creates pure (hygienic) macros, arguments and variables in which are guaranteed not to intersect with the program's namespace. +The body of a macro can be a valid language expression, a sequence of lexemes (enclosed in double at symbols **"@@"**, +i.e. **`@@ lexeme1 lexeme2 @@`**), or a regular text string (which should be specified between triple at symbols **"@@@"**, +i.e. **`@@@ text string @@@`**). -Телом макроса могут быть корректное выражение языка, последовательность лексем (которые заключается в двойные собачки **"@@"**, -т.е. **`@@ лексема1 лексема1 @@`**) или обычная текстовая строка (которую нужно указать между тройными собачками **"@@@"**, т.е. **`@@@ текстовая строка @@@`**). +In the macro name after the first term, one or more templates may be present. +A *template* is a term that, when matching a sequence of lexemes with the macro identifier, +can be replaced by any other single term (effectively, this is pattern/template matching). -В имени макроса, кроме первого термина, могут присутствовать один или несколько шаблонов. -*Шаблон* — это термин, который при сопоставлении последовательности лексем с идентификатором макроса -может заменяться любым другим одиночным термином (т.е. фактически это сопоставление по образцу/шаблону). +To create a template term, a dollar sign should be placed at the beginning of its identifier (which corresponds to a qualifier of a local variable), +i.e. the macro name `@@ FUNC $name @@` will correspond to the sequence of lexemes as `FUNC my_func_name` as well as `FUNC other_name_func`. -Для создания термина-шаблона в начале его идентификатора нужно поставить знак доллара (что соответствует квалификатору локальной переменой), -т.е. имя макроса `@@ FUNC $name @@` будет соответствовать последовательности лексем как `FUNC my_func_name`, так и `FUNC other_name_func`. +To remove a macro, a special syntax is used: `@@@@ name @@@@;` or `@@@@ two terms @@@@;`, +i.e. you need to specify the macro identifier between four characters **"@@@@"**. -Для удаления макроса используется специальный синтаксис: `@@@@ name @@@@;` или `@@@@ два термина @@@@;`, -т.е. необходимо указать идентификатор макроса между четырмя символами **"@@@@"**. +```python + # Macro body from a text string (as in C/C++ preprocessor) + @@macro_str@@ := @@@ string - macro body @@@; # String for the lexer -```bash - # Тело макроса из текстовой строки (как в препроцессоре С/С++) - @@macro_str@@ := @@@ строка - тело макроса @@@; # Строка для лексера - - # Удаления макроса @macro_str + # Removing macro @macro_str @@@@ macro_str @@@@; ``` -### Аргументы макросов и их раскрытие +### Macro Arguments and Expansion {#args} -Макросы можно определять как с аргументами (параметрами в скобках), так и без них. -Если макрос был определен с аргументами, то их проверка будет выполнятся макропроцессором при определении и раскрытии макроса. -Если макрос был определен без аргументов, то их наличие макропроцессором игнорируется. +Macros can be defined with arguments (parameters in parentheses) or without them. +If a macro was defined with arguments, their validation will be performed by the macro processor during definition and expansion of the macro. +If a macro was defined without arguments, the presence of arguments will be ignored by the macro processor. -Так как макропроцессор считает макросы с аргументами и без оных идентичными, то нельзя создать два макроса -с одинаковыми именами, один из которых будет с аргументами (скобками), а другой без них. +The macroprocessor considers macros with and without arguments identical, +so it is not possible to create two macros with the same name, one with arguments (in parentheses) and the other without. -Поэтому, если требуется использовать макрос в двух разных вариантах (с аргументами и без них), -тогда следует определять макрос без аргументов и в этом случае контроль параметров будет производить компилятор. +Therefore, if you need to use a macro in two different ways (with arguments and without), +you should define the macro without arguments, and in this case, the parameter control will be done by the compiler. ```bash - @@macro@@ := term; # Макрос без аргументов + @@ macro @@ := term; # Macro without arguments - macro(args); # ОК -> term(args); - macro; # ОК -> term; + macro(args); # OK -> term(args); + macro; # OK -> term; - # Но - @@call()@@ := term(); + # But + @@ call() @@ := term(); - call(); # ОК -> term(); - call; # Ошибка (@call определен с аргументами) + call(); # OK -> term(); + call; # Error (@call is defined with arguments) ``` -Если при определении макроса указаны аргументы, то место для их вставки в теле макроса -записывается как имя локальной переменой, перед которой добавлен символ **"@"**, т.е. **@$arg**. - -Произвольное количество аргументов у макроса отмечается троеточием **"..."**, а место для их вставки отмечается в теле макроса лексемой **"@$..."**. - -Место для вставки числа реально переданных аргументов отмечается лексемой **"@$#"**. -Если требуется вставить переданные аргументы в виде элементов словаря, -то место для вставки отмечается лексемой **"@$\*"**. - -По аналогии с препроцессором С/С++, для соединения двух лексем в одну, в теле макроса используется оператор **"@##"**, -а для преобразование лексемы в текстову строку применяется операторы **@#**, **@#"** или **@#'**, например, -`@@macro($arg)@@ := @@ func_ @## @$arg( @#" arg ) @;`, тогда вызов `macro(name);` будет преобразован в `func_name ("name");` - - -{{% pageinfo %}} - -#### Ограничения макропроцессора в текущей версии - -На текущий момент макросы реализованы в минимальном объеме для самых простых сценариев использования: - -- DSL для keyword based syntax (if, else, return, match, while и т.д.) - (1 термин с произвольными аргументами и без) - требуется сейчас !!! - -*Парсер при обработке макросов может анализировать информацию о типах данных, если она указана.* -*Но на текущий момент типы данных в макросах никак не обрабатываются и это одна из обязательных фич, которая будет реализована в будущем.* +If arguments are specified when defining a macro, the place for their insertion in the body of the macro is written +as the name of a local variable with the symbol **"@"** added before it, i.e. **@$arg**. -- Определения (func, class) - (несколько терминов с аргументами и без аргументов) - Реализация ООП и импорт С++ классов -- Модификации при определениях (override) - (несколько терминов и шаблоны с аргументами и без аргументов) - Реализация ООП и импорт С++ классов +The place for inserting the number of actual arguments passed is marked by the lexeme **"@$#"**. +If it is necessary to insert the passed arguments as a dictionary, the place for insertion is marked by the lexeme **"@$\*"**. -{{% /pageinfo %}} +If the macro takes an arbitrary number of arguments (the macro arguments are terminated by an ellipsis), +the place for their insertion in the body of the macro is marked by the lexeme **"@$..."**. +Analogous to the C/C++ preprocessor, to concatenate two lexemes into one, the operator **"@##"** is used in the body of the macro, +and to convert a lexeme into a text string, the operators **@#**, **@#"**, or **@#'** are applied, for example, +`@@macro($arg)@@ := @@ func_ @## @$arg( @#" arg ) @;`, then the call `macro(name);` will be transformed into `func_name ("name");` -# МАКРОСЫ БЕЗ АРГУМЕНТОВ ИЛИ ВСЕ АРГУМЕНТЫ СРАЗУ !!!!! -# анализа аргументов или их типов не производится !!! +Examples of using macros: +```python + # Ordinary macros (the body of the macro is a correct expression) + @@ macro @@ := replace(); + @@ macro2(arg) @@ := { call(@$arg); call()}; - - - -Lambda -@@ lambda $name(...) @@ ::= @@ @$name( @$... ) ::= ( _( @$... ) ::= @__PRAGMA_FINALIZE__( @\), {, {+, {-, {* ) @@ - - -### Примеры использования макросов - -```bash - # Обычные макросы (тело макроса корректное выражение) - @@macro@@ := replace(); - @@macro2(arg)@@ := { call(@$arg); call()}; - - # Тело макросов из последовательности лексем - @@if(...)@@ := @@ [ \$if(*) ]--> @@; # Выражение может быть не полным - @@elif(...)@@ := @@ ,[ \$elif(*) ]--> @@; - @@else@@ := @@ ,[_]--> @@; + # The body of the macros from a sequence of tokens + @@ if(...) @@ := @@ [ @$... ]--> @@; # The expression may not be complete + @@ elif(...) @@ := @@ ,[ @$... ]--> @@; + @@ else @@ := @@ ,[...]--> @@; - # Запись условного оператора с использованием - # определенных выше макросов - if( condition ){ + # Writing a conditional statement using + # the macros defined above + @if( condition ){ ... - } elif( condition2 ) { + } @elif( condition2 ) { ... - } else { + } @else { ... }; ``` - - - - - - - - - -Зачем нужна трансформация синтаксиса? -Нативная поддержка других языков нужна чтобы не переписывать легаси код на этих языках. - -Чтобы можно было использовать существующие исходники как собственные требуется настройка работы -препроцессора и лексера под конкретный язык программирования (описание DSL). -Для **С/С++** потребуется выделять лексером комментарии из-за пересечения синтаксиса (которые сейчас игнорируются). -Для **Python** требуется выделять лексером отступы (которые сейчас тоже игнорируются), причем потребуется реализация не только синтаксиса, -но и зависимых пакетов с последующая трансляцией этого кода в С++, что в настоящий момент делать не целесообразно (cython ???). - -Но так как возможность трансформации кода с других языков программирования принципиальная возможна, -стоит над этим думать только после полноценного релиза NewLang и его перехода в прод. - - - -Для реализации DSL требуется передача команд в парсер для управления его работой (по аналогии с командой #pragma) -Но так как обработка таких команд должна происходить в лексере до передачи данных в парсер (анализатор), -то команды для макропроцессора должны быть в максимально простом виде и состоять из элементов, -которые лексер может самостоятельно идентифицировать, т.е. термины, строки и цифры (без выражений и именованных аргументов). - -После обработки такой команды она анализируется макропроцессором и удаляется из потока лексем, т.е. в парсер (анализатор) не передается. -Но в случае ошибки с синтаксисе, данные команды нужно уметь однозначно идентифировать и самый простой способ, -комбинация признака макроса и системного имени, т.е. что-то вроде -``` - @__PRAGMA_DIAG__(push) - @__PRAGMA_DIAG__(ignored, "-Wundef") - @__PRAGMA_DIAG__(warning, "-Wformat") - @__PRAGMA_DIAG__(error "-Wuninitialized") - @__PRAGMA_DIAG__(pop) - - #pragma message "Compiling " __FILE__ "..." - @__PRAGMA_MESSAGE__("Compiling ", __FILE__, "...") - - #pragma error "Error " __FILE__ "..." - @__PRAGMA_ERROR__("Error ", __FILE__, "...") - - -#define DO_PRAGMA(x) _Pragma (#x) -#define TODO(x) DO_PRAGMA(message ("TODO - " #x)) - -@@TODO( ... )@@ := @__PRAGMA_MESSAGE__("TODO - ", @*) - -@TODO(Remember to fix this) # note: TODO - Remember to fix this - -\\.__lexer__ignore_space__ = 1; -\\.__lexer__ignore_indent__ = 1; -\\.__lexer__ignore_comment__ = 1; -\\.__lexer__ignore_crlf__ = 1; - - -``` - - -Таким образом можно трансформировать условный оператор на питоне в синтаксис NewLang следующим макросом: -``` - -#pragma clang attribute push -#pragma clang diagnostic ignored "-Wundef" -#pragma clang diagnostic ignored "-Wunused-variable" - - -#elif __GNUC__ - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wuninitialized" - -#pragma GCC diagnostic ignored "-Wall" -#pragma GCC diagnostic ignored "-Wextra" - - @pragma warning(pop) - - @@ pragma warning(...) @@ := __PRAGMA_TERM_DIAG_WARNING__(); -@__PRAGMA_DIAG__(warning, pop); - -Обработка терминов в макропроцессоре в максимально простом виде. -Агрументы только термины, строки и цифры без вложенных выражений и именованных аргументов, -т.е. только элементы, которые может самостоятельно идентифицировать лексер. - -@warning("--") - @@ if ... : @@ := @@ [ @$* ]-> __TERM_BLOCK_INDENT__("{", force_semicolon=1) @@ - - if __name__ == "__main__": - run1() - run2() - - [ __name__ == "__main__" ]-> { - run1(); - run2(); - }; - - - -``` - - - - - - - - -Ключ --parser-syntax-only только текстовый парсинг исходного кода без загрузки модулей, раскрытия макросов и проверки имен. - -Ключ --parser-no-macros - без раскрытия макросов -Ключ --parser-no-module - без загрузки модулей (и мокросов, если они в них определяются) -Ключ --parser-no-check-prototype - без проверки имен при обращении - -prototype -@__PRAGMA_PROTOTYPE__(define) -@__PRAGMA_PROTOTYPE__(implement) - -$$ - -\\$ - корень системы (система) - -\$ - текущий модуль - -# Макросы для конвертора проверки в Python -# if __name__ == "__main__": - -@@ __name__ @@ ::= @@ \$. @__PRAGMA_NO_MACRO__() __name__ @@ -@@ if $... @\: @@ ::= @@ [ @$... ] --> @@ - -@if( \$.__name__ == "__main__" ) { - - -} - -\\каталог\модуль() - статический импорт модуля -\\("каталог\модуль")() - динамический импорт модуля - - -printf := :Pointer('printf(format:FmtChar, ...):Int32'); -printf := %printf(format:FmtChar, ...):Int32; - - -# Регистрация прототипа нативной функции -@prototype -%puts(format:StrChar):Int32; - -# Импорт нативной функции с предварительной проверкой её наличия во время компиляции (статическая линковка) -puts2(format:StrChar):Int32 := %puts(format:StrChar):Int32; -# Импорт нативной функции по её прототипу во время выполнения (динамическая линковка) -puts3(format:StrChar):Int32 := :Pointer('puts(format:StrChar):Int32'); - -%puts('Тест вывода строки'); # Линковка с нативной функцией во время компиляции и непосредственный вызов с оптимизацией передачи параметров -puts2('Тест 2 вывода строки'); # Линковка с нативной функцией во время компиляции -puts3('Тест 3 вывода строки'); # Линковка с нативной функцией во время выполнения при первом вызове puts3 - - - -- Парсинг исходного текста без раскрытия макросов и загрузки модулей -- Парсинг исходного текста с раскрытием макросов (требуется загрузка модулей для зависимых и переопределяемых макросов) -- Загружатся модули могут как в виде исходников (которые требуется парсить и компилировть/выполнять) -или в виде бинарников (в них должны быть список макросов, типов и имена объектов) -- После парсинга получается список **имен** макросов, типов и объектов (TermPtr) -- После выполнения модуля - список **имен** заполняется реальными объектами (ObjPtr). - - -# Компиляция файла -- Парсинг исходника для построения AST (без анализа имен, связей, загрузки модулей и пр. только исходые тексты с раскрытием макросов -- - - -# Систематизация реализации макросов - -последовательность лексем MACRO_SEQ мужду @@ @@ сохраняется в m_block, так как фрагменты блоков не могут быть идентификаторами - -Разбор макросов происходит в лексере. Определением макроса всегда является целая строка, -которая заканчивается точкой с запятой, а идентификатором макроса всегда выступает последовательность лексем: -```bash - @@ id @@ := macro; - @@ id @@ := @@ @@; - @@ id @@ := @@@ @@@; -``` -Хранилищем текущих максросов является объект класса MacroBuffer. -Последовательность лексем идентификатора (id) макроса должна сохраняется в отдельном поле термина и однозначно его идентифицирует. -Первый термин в идентификаторе хранится как ключ hashmap, а дальше происходит поиск полным перебором. -Этапы работы с макросами - -- Входные термины из лексера получаются вызовом GetNextToken, внутри которой и происходит раскрытие макросов. -Внутренний буфер заполняется до окончания строки (выражения), т.е. до символа ';' или <END>, после чего производится -поиск макросов в объекте MacroBuffer для текущей последовательности лексем в буфере. - -- Если макрос найден, то соответствющая ему последоваетльность заменяется на тело макроса и происходит переход -на повторный анализ входного буфера. - -- Если макрос не найден, то данные передаются в парсер для дальнейшего синтаксическго анализа. - -- Для этого во входном потоке лексем (parser.y) во время оператората создания/присвоения вызывается функция проверки на макрос. -MacroBuffer::CheckMacroAndConvertDel($$), и после этого выходному значению присваивается результат выполнения driver.MacroEval($$), -и в дальнейшем этот макрос никак не обработывается. - -- Создание макросов, проверка на дубликаты и логические ошибки в определении происходит путем обращения к методам объекта MacroBuffer. - - - - - - - /* - * Макросы хрянтся как фрагменты AST в виде объектов типа Term, - * так как создаются после обработки парсером по правилам стандратной грамматики. - * - * Но анализ входных данных на предмет раскрытия макросов проиходит из потока (последовательности) лексем, - * т.е. **ДО** обработки парсером, так как при раскрытии макросов может меняться грамматика выражений. - * - * Функция \ref CompareMacro сравнивает входной буфер (последовательность лексем) - * на предмет возможного соответствия одному конкретному макросу. - * Сравниваются только ключевые словам без учета аргументов в скобках, - * но само наличие аргументов проверяется ?????????????????? - * - * Проблема: - * К функции можно обратится с целью её вызова (указав после имени скобки), - * так и по имени без скобок (например для получения ссылки на объект). - * Так и к переменной можно обратиться только по имени, - * так и указав скобки после имени как к функции (при копировании объекта). - * - * Сделать один макрос под оба сценария (со скобками и без скобок) не получится, так как непонятно, - * что делать с аргументами при раскрытии тела макроса, когда они не указаны. - * - * Но может быть следует переименовывать только одно имя без учета скобок, - * например, оставив такую возможность только для одиночных макросов. - * - * \name -> name или name (...), hash: name - * но \name(...) -> name(...), а name - ошибка !!!! hash: name - * - * Или все же следует различать макросы со скобками и без скобок как два разных объекта??? - * \name := name2; и \name(...) := name2(...); будут разными объектами - * - * Или добавить макросы-алиасы без аргументов только для переименования отдельных терминов? - * \alias :- name2; но как их отличать от обычных макросов в операции удаления? - * Или вообще не нужно отличать и оставить только один варинат (либо макрос, либо алиас) - * Тода вопрос со скобками закрывается сам собой, алиасы всегда без скобок, - * макросы со скбками или без скобок, но должно быть полное соответствие. - * - * @ name name2 @ -> name name2, но name name2(...) - ошибка!!! (hash: name,name2) - * @ name name2(...) @ -> name name2(...), но name name2 - ошибка !!!! (hash: name,name2) - * @ name name2[...](...) @ -> name name2[...](...), но name name2 - ошибка !!!! ( hash: name,name2 ) - * @ name $tmpl[...](...) name3@ -> name $tmpl[...](...) name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 ) - * - * Но! - * @ name name2 @ ::- -> name name2 - ок, но name name2(...) - ок - * @ name $tmpl name3@ ::- -> name $tmpl[...](...) name3 - ок, name $tmpl(...) name3[...] - ок - * - * - * - * Для последовательности лексем требуется полное соответствие с учетом скобок ??? - * и может ли быть несколько скобок одного типа (несколько крыглях, или несколько квардратных???? - * <Может быть несколько скобок одного типа, например, при указании типа у аргументов или типа возвращаемого значения.> - * - * @ name name2 @ -> name name2, но name name2(...) - ошибка!!! (hash: name,name2) - * @ name name2(...) @ -> name name2(...), но name name2 - ошибка !!!! (hash: name,name2) - * @ name name2[...](...) @ -> name name2[...](...), но name name2 - ошибка !!!! ( hash: name,name2 ) - * @ name $tmpl[...](...) name3@ -> name $tmpl[...](...) name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 ) - * - * Проблема скобок возникает из-за сценария замены одного термина на другой, - * который есть в препроцессоре С/С++, но отсутствует при реализации с использованием шаблонов. - * - * - */ - - - - - - -Макросы используются и для превращеня исходного кода *NewLang* в более привычный синтаксис на основе [ключевых слов](https://newlang.net/syntax_dsl.html), так как такой тест гораздо легче воспринимается при последующем чтении исходного кода. - - -[Например:](https://newlang.net/syntax_dsl.html). -``` - @@if(...)@@ ::= @@ [ \$* ]--> @@; - @@while(...)@@ ::= @@ [\$*] <-> @@; - @@return $arg@@::= @@ -- \$arg -- @@; - @@true@@ ::= 1; -``` - -Тогда цикл до 5: -``` -count:=1; -[ 1 ] <-> { - [count>5] --> { - -- 42 --; +For example, a loop up to 5: +```python + count := 1; + [ 1 ] <-> { + [ count > 5 ] --> { + -- 42 --; + }; + count+=1; }; - count+=1; -}; ``` -будет выглядеть более привычно -``` -count:=1; -while( true ) { - if(count>5) { - return 42; +This will look more familiar: +```python + count := 1; + @while( true ) { + @if( count > 5 ) { + @return 42; + }; + count += 1; }; - count+=1; -}; -``` - - - - -## Идеи на будущее -### Символьное программирование - -> Символьное программирование, часто называемое декларативным программированием, представляет собой парадигму программирования, которая использует математическую логику, отношения и символы для представления знаний и помощи в решении проблем. Вместо того, чтобы сосредотачиваться на описании последовательности операций, необходимых для выполнения вычислений, как в императивном программировании, символическое программирование делает упор на выражении отношений и ограничений между структурами данных, уделяя особое внимание «что», а не «как». -> -> В контексте парадигм программирования символическое программирование часто противопоставляется процедурному или императивному программированию, где программы определяют пошаговые процедуры для достижения своих целей. В то время как императивное программирование фокусируется на описании потока управления с использованием таких конструкций, как циклы и условные выражения, для управления выполнением, символическое программирование сосредоточено на выражении фактов о проблеме и позволяет выполнению естественным образом выводить последующие последствия из предоставленной информации. -> -> Одним из основных преимуществ символьного программирования является его способность обеспечивать более высокий уровень абстракции, что упрощает анализ кода и снижает вероятность ошибок. Непосредственно выражая отношения и ограничения, символическое программирование позволяет разработчикам сосредоточиться на моделировании и спецификации проблем, позволяя базовой системе управлять реализацией и выполнением алгоритмов. -> -> Существует несколько языков программирования и сред, использующих парадигму символьного программирования, например Prolog, Lisp и Haskell. Например, Пролог — это язык логического программирования, который позволяет разработчикам выражать взаимосвязи и факты о проблемных областях, в то время как выполнение автоматически обосновывает и извлекает новые факты на основе исходной информации. В том же духе Лисп, функциональный язык программирования, использует символьные вычисления для манипулирования структурами данных и выполнения сложных операций над ними, используя краткий и математически обоснованный синтаксис. Haskell, еще один функциональный язык программирования, использует строгую типизацию и ленивые вычисления, чтобы обеспечить символическое рассуждение и облегчить эффективное создание программ. -> -> Символьное программирование может быть полезным в широком спектре проблемных областей, включая искусственный интеллект, экспертные системы, программирование логики ограничений и символьную математику, среди других. Более высокий уровень абстракции, обеспечиваемый декларативными языками программирования, облегчает разработку сложных систем, сводя к минимуму вероятность ошибки и улучшая удобство обслуживания. В частности, использование символьного программирования в искусственном интеллекте позволяет разработчикам создавать системы представления знаний и механизмы рассуждения, которые можно применять для обработки естественного языка, машинного обучения и автоматического доказательства теорем. - - -Различие между символьным программированием и препроцессором -- Задача препроцессора - раскрыть(расширить) макрос, тогда как при символьном программировании нужно сокращать (сворачивать) выражения -- Препроцессор обрабатывает последовательности лексем (плоские данные), тогда как символьное программирование оперирует выражениями (деревом лексем) -- Макрос у препроцессора идентифицируется первым термином, и если макрос не может быть раскрыт, то возникает ошибка. В символьном программировани требуется точное соответствие всего выражения и только в этом случае производится сокращение выражения. - -Предпосылки для реализации символьного программирования -Компилятор - интерепретатор с REPL и обработка AST как во время компиляции, так и во время выполнения. -Необходимо добавить конструкции для определения правил символьного программрования (чистые функции?) -Необходимо добавить конструкцию для вычисления выражений в символьном программировании. - - -Wolfram -https://habr.com/articles/772984/ -``` -diffRules = { - Sin[x] -> Cos[x], - Cos[x] -> -Sin[x], - x^2 -> 2*x, - x -> 1, - Log[x] -> 1/x -}; -``` - -``` -diffRules := ( - Sin(x) @-> Cos(x), - Cos(x) @-> -Sin(x), - x^2 @-> 2*x, - x @-> 1, - Log(x) @-> 1\x, -); - -expr @-> Sin(x) - x^2 + Log(x); - -# И применим к нему правила дифференцирования - -#expr /. diffRules -#(* 1/x - 2 x + Cos[x] *) - -sym := SymEval(expr, diffRules); -res := Eval(sym, x=0.123); - -``` - - - - -``` -expr = a^2 + 3 * b^3 - c^4 + 2 * x^2 - x + 4*c + 3 - -И я хочу это выражение линеаризовать, т.е. отбросить все степени выше первой. Я могу сделать это напрямую, как в примерах выше: - -expr /. { - a^2 -> 0, - b^3 -> 0, - c^4 -> 0, - x^2 -> 0 -} -(* 3 + 4 c - x *) - -Но это слишком неудобно. Что если я не знаю ни точную степень, ни имя переменной? Как просто указать, что нужно заменить все места, где встречается возведение в степень на ноль? Это можно сделать при помощи шаблонов вот так: - -expr /. Power[_, _] -> 0 -(* 3 + 4 c - x *) - -Либо вот так: - -expr /. _ ^ _ -> 0 -(* 3 + 4 c - x *) - -``` - - - -``` -:diffRules() := { - {@ Sin(x) @} ::- {@ Cos(x) @}; - Cos(x) @-> -Sin(x), - x^2 @-> 2*x, - x @-> 1, - Log(x) @-> 1\x, -}; - -expr @-> Sin(x) - x^2 + Log(x); - -# И применим к нему правила дифференцирования - -#expr /. diffRules -#(* 1/x - 2 x + Cos[x] *) - -sym := SymEval(expr, diffRules); -res := Eval(sym, x=0.123); - -``` - +``` \ No newline at end of file diff --git a/site/content/en/docs/types/native.md b/site/content/en/docs/types/native.md index 63feee7b..c81f1d95 100644 --- a/site/content/en/docs/types/native.md +++ b/site/content/en/docs/types/native.md @@ -1,33 +1,44 @@ --- -title: Нативные типы +title: Native Data Types # linkTitle: Docs # menu: {main: {weight: 20}} weight: 70 tags: [типы данных, системые типы, коллекции] --- +Native (machine) data can be variables or functions, and the names of native objects start with the percent symbol "**%**". -## Нативные типы данных -Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента "**%**". -В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат. +In the case of variables, these are binary data located in a single continuous area of machine memory at a specific address and have a strictly defined format. -### :Pointer — указатель на системную область памяти или нативную функцию +To use existing libraries, you need to import the native object, thereby creating an object NewLang, +but with an implementation in another language, for example, in C/C++. +The syntax for importing native objects is the same as for [creating](/docs/ops/create/) regular language objects, +only the name of the native object needs to be specified as the right operand in the creation operator. +When importing a native object, it is necessary to always specify the variable types, +as well as the types of arguments and return values for functions. -Так как любой программе приходится взаимодействовать с внешним миром, т -о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, -и для этих целей служит тип *:Pointer*. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. -Но можно вывести его значение, например для отладки. +If the data types of the created object and the native object match (i.e., no type conversion is required), +then the native object name can be specified with an ellipsis, +which means that the data types will replicate those specified at the left operand. -### :Plain — указатель на представление данных в бинарном виде +```python +:FILE ::= :Plain; -Для взаимодействия с внешними библиотеками требуется еще и обмен данными. -И для этих целей служит тип данных *:Plain* — который также является указателем, но на двоичное представление данных в области памяти. -Конечно, если их можно представить в виде одного фрагмента. +fopen(filename:StrChar, modes:StrChar):FILE ::= %fopen...; +fclose(f:FILE):Int32 ::= %fclose...; +fflush(f:FILE):Int32 ::= %fflush...; +fprintf(f:FILE, format:FmtChar, ...):Int32 ::= %fprintf...; -### Перечисление, структура и объединение +fremove(filename:String):Int32 ::= %remove...; +frename(old:String, new:String):Int32 ::= %rename...; +``` -*:Enum*, *:Struct* и *:Union* — это такие же [словари](http://localhost:1313/docs/types/dicts/#перечисление-структура-и-объединение), только на их элементы накладываются определённые ограничения. Каждый элемент должен иметь уникальное имя, а его тип данных должен быть простым, т.е. числом или строкой фиксированного размера. Эти типы данных так же относятся к группе *:Plain* и могут быть представлены в двоичном виде в одной области машинной памяти. +{{% pageinfo %}} + +The following description is under development. + +{{% /pageinfo %}} diff --git a/site/content/en/playground/_index.md b/site/content/en/playground/_index.md index 54b44f5e..1889423a 100644 --- a/site/content/en/playground/_index.md +++ b/site/content/en/playground/_index.md @@ -8,9 +8,6 @@ menu: main weight: 25 --- -Примеры программ на NewLang - - <style> .rownr {width: 5%; overflow-y: hidden; background-color: rgb(105,105,105); color: white; text-align: right; vertical-align:top; resize: none;} @@ -20,6 +17,10 @@ weight: 25 .pgbox {margin-top: 4rem;} </style> +<p> +<br> +</p> + <div class="pgbox"> <select class="c10" style="width: 95%;" onchange="SelectExample(this);" id="example_list"> <option selected="selected" value="" id="example_start">Select an exmaple...</option> @@ -69,18 +70,6 @@ weight: 25 <script> -if(window.location.search){ - const params = new Proxy(new URLSearchParams(window.location.search), { - get: (searchParams, prop) => searchParams.get(prop), - }); - // Get the value of "src" in eg "https://example.com/?src=source" - if(params.src){ - document.getElementById('playground').value = unescape(params.src); - } - //alert(escape('#!../output/nlc \n\nprint(\'Hello, world!\\n\');\n')); - // %23%21../output/nlc%20%0A%0Aprint%28%27Hello%2C%20world%21%5Cn%27%29%3B%0A -} - locations =[ "", "{{< source "hello.src" >}}", "{{< source "rational.src" >}}", @@ -89,14 +78,17 @@ locations =[ "", "{{< source "tensor.src" >}}", ]; -function SelectExample(sel){ - - srcLocation = locations[sel.selectedIndex]; - if (srcLocation != undefined && srcLocation != "") { - obj = document.getElementById('playground'); - obj.value = locations[sel.selectedIndex]; - input_changed(obj); - } +function SelectExample(sel){ + obj = document.getElementById('playground'); + if(Number.isInteger(sel) && locations[sel]){ + obj.value = locations[sel]; + } else { + srcLocation = locations[sel.selectedIndex]; + if (srcLocation != undefined && srcLocation != "") { + obj.value = locations[sel.selectedIndex]; + } + } + input_changed(obj); } @@ -251,7 +243,7 @@ function run_playground(){ clearInterval(downloadTimer); document.getElementById('progress').style.display = "none"; document.getElementById('playground_out').classList.add("error"); - alert("Request failed!"); + alert("Request failed!\n\nCheck the connection protocol!\n\nThe site should open using the regular HTTP protocol without using SSL! Because browsers typically block unsecured connections on HTTPS pages."); }; xhr.ontimeout = (e) => { @@ -260,4 +252,20 @@ function run_playground(){ alert("Run query timeout!"); }; } + + +if(window.location.search){ + const params = new Proxy(new URLSearchParams(window.location.search), { + get: (searchParams, prop) => searchParams.get(prop), + }); + // Get the value of "src" in eg "https://example.com/?src=source" + if(params.id){ + SelectExample(parseInt(params.id)); + } else if(params.src){ + document.getElementById('playground').value = unescape(params.src); + } + //alert(escape('#!../output/nlc \n\nprint(\'Hello, world!\\n\');\n')); + // %23%21../output/nlc%20%0A%0Aprint%28%27Hello%2C%20world%21%5Cn%27%29%3B%0A +} + </script> \ No newline at end of file diff --git a/site/content/ru/blog/release-0.4.md b/site/content/ru/blog/release-0.4.md index f83b713c..96808303 100644 --- a/site/content/ru/blog/release-0.4.md +++ b/site/content/ru/blog/release-0.4.md @@ -1,23 +1,23 @@ --- slug: release-v0.4 -title: Релиз языка программрования NewLang 0.4 +title: Релиз языка программирования NewLang 0.4 date: 2023-06-06 #draft: true --- - -![КДПВ](/ru/blog/langs.jpeg) - - -{{% pageinfo %}} - -Внимание!!! - -"nj pfujnДанная статья содержит описание синтаксиса NewLnag предыдущей версии. - -Актуальную версию синтаксиса языка можно посмотреть [тут](/ru/docs/). - -{{% /pageinfo %}} - - -ssssssssssssssssssssssssssssssssssssssssssssss \ No newline at end of file +## Новые возможности и изменения в синтаксисе NewLang +- Переработано определение типов объектов с помощью [префикса имен (сигила)](https://newlang.net/docs/syntax/naming/) +- Прерывание потока выполнения и возврат теперь может выполняться для [именованных блоков кода](https://newlang.net/docs/ops/throw/). +- Упрощен синтаксис импорта [нативных переменных и функций (С/С++)](https://newlang.net/docs/types/native/) +- Стабилизирован синтаксис для [заполнение начальными данными](https://newlang.net/docs/ops/create/#comprehensions) значений тензоров, словарей и аргументов при вызове функций. +- Появились встроенные макросы для написания кода с использованием ключевых слов в стиле [DSL](https://newlang.net/docs/syntax/dsl/) + +## Новые возможности компилятора (nlc) +- Полностью переделан макропроцессор. +- Переработана архитектура компилятора с разделением на парсер, макропроцессор, синтаксический анализатор, интерпретатор и генератор кода. + +## Разное +- [Сайт](http://newlang.net) с документацией переведен на [Hugo](https://gohugo.io/) и сделан двуязычным. +- Вместо бинарных сборок на сайт добавлен раздел [Playground and example code](https://newlang.net/playground/) для небольших экспериментов. +- Выполнен переход на clang-16 (переход на clang-17 и старше планируется после полной реализации корутин и поддержки расширенных форматов чисел с плавающей запятой). +- Количество контрибуторов проекта стало больше одного! \ No newline at end of file diff --git a/site/content/ru/docs/_index.md b/site/content/ru/docs/_index.md index 832058df..1f853828 100755 --- a/site/content/ru/docs/_index.md +++ b/site/content/ru/docs/_index.md @@ -9,15 +9,3 @@ weight: 20 Описание акутально для текущей версии 4.0 - -clang-17 не поддерживает: -| Feature | Proposal | Available | -|-------------------|-------------------|---------------------------------------| -| Coroutines | P0912R5 |*Partial* Fully supported on all targets except Windows, which still has some stability and ABI issues. -| Extended floating-point types and standard names | P1467R9 | No -| Concepts | P0848R3 | Clang 16 (Partial) -| Modules | | No | - - -### Начиная с C++ should adopt the same characters for C++26. -- Add **@**, **$**, and ` to the basic character set P2558R2 Yes \ No newline at end of file diff --git a/site/content/ru/docs/arch/_index.md b/site/content/ru/docs/arch/_index.md index 1ab901a9..b6981e93 100644 --- a/site/content/ru/docs/arch/_index.md +++ b/site/content/ru/docs/arch/_index.md @@ -6,6 +6,23 @@ description: > simple_list: false --- + +## На память + +clang-17 не поддерживает: +| Feature | Proposal | Available | +|-------------------|-------------------|---------------------------------------| +| Coroutines | P0912R5 |*Partial* Fully supported on all targets except Windows, which still has some stability and ABI issues. +| Extended floating-point types and standard names | P1467R9 | No +| Concepts | P0848R3 | Clang 16 (Partial) +| Modules | | No | + + +### Начиная с C++ should adopt the same characters for C++26. +- Add **@**, **$**, and ` to the basic character set P2558R2 Yes + + + ## Система классов реализации RunTime - единственный класс для приложения (процесса) - интерфейс для взаимодействия с операционной системой diff --git a/site/content/ru/docs/syntax/dsl.md b/site/content/ru/docs/syntax/dsl.md index 1618d0de..1272916b 100644 --- a/site/content/ru/docs/syntax/dsl.md +++ b/site/content/ru/docs/syntax/dsl.md @@ -6,222 +6,63 @@ weight: 200 --- -## DSL - ### Особенности ассоциативной памяти Синтаксис языка *NewLang* основан на строгих правилах без использования ключевых слов, и как бы он не выглядел логичным, ассоциация по ключевым словам вспоминается гораздо легче, например **if**, чем комбинация *минус минус правая угловая скобка* **-->**. Из-за этого имеет смысл использовать не "чистый" базовый синтаксис, а более привычный диалект с использованием ключевых слов. -### Синтаксис на ключевых словах -В файле dsl.nlp находится набор макросов, которые расширяют базовый синтаксис *NewLang*, основанный на правилах, -набором предопределенных ключевых слов как в классических языках программирования. -А при необходимости, их можно адаптировать или дополнить под собственную предметную область. - +*NewLang* уже содержит набор макросов, которые расширяют базовый синтаксис *NewLang*, основанный на правилах, +набором предопределенных ключевых слов как в классических языках программирования, +которые можно адаптировать или дополнить под собственную предметную область. -## Константы -### Логические -- **true** - 1 -- **yes** - 1 -- **false** - 0 -- **no** - 0 +### Константы +- *@true* - 1 +- *@yes* - 1 +- *@false* - 0 +- *@no* - 0 -### Системные имена -- **this** - Текущий объект (**$0**) -- **parent** - Родительский объект (**$$**) -- **last** - Результат выполнения последнего оператора (**$^**) +- *@this* или *@self* - Текущий объект +- *@super* - Родительский объект +- *@latter* или *@last*- Результат выполенения последнего оператора Result of the last operation -!!!!!!!!- **args** - Все аргументы функции (**$\***) +### Логические операторы -!!!!!!!!- **sys** - Системный контекст запущенной программы (**@@**) -!!!!!!!!- **current** - Текущий модуль (**@$**) -!!!!!!!!- **cmd** - Все аргументы выполняющегося приложения из командной строки (**@\***) +- *@and* - Логическое **И** +- *@or* - Логическое **ИЛИ** +- *@xor* - Логическое **Исключающее ИЛИ** +- *@not(value)* - Логическое отрицание -!!!!!!!!!!1### Типовые функции и проверки -!!!!!!!!!!- **run('filename')** - Выполнить указанный файл (**@@('filename')**) -!!!!!!!!!!- **ifmain** - Проверка, если текущий модуль основной (**[@$.$0] -->** { ... }) -!!!!!!!!!!- **ifload** - Проверка, если текущий модуль загружается впервые (**[@$.__load__] -->** { ... }) ### Операторы -- **match(cond)** - Оператор [оценки выражения](https://newlang.net/ops.html#оценка-выражения) -- **if(...)** - Первый условный оператор (**[\$*]-->** { ... }) -- **elif(...)** - Второй и все последующие (**,[\$*]-->** { ... }) -- **else** - Оператор *иначе* (**,[_]-->** { ... }) - -- **while(cond)** - Оператор цикла с предусловием (**[@$cond] <->** { ... } ) -- **dowhile(cond)** - Оператор цикла с постусловием ({ ... } **<->[@$cond]**) - -- **iter(obj, ... )** - Создание итератора ( **@$obj** ? (@$*) ) -- **next(obj, ... )** - Следующий элемент итератора ( **@$obj** ! (\$*) ) -- **curr(obj, ... )** - Текущий элемент итератора ( **@$obj** !? (\$*) ) -- **first(obj)** - Перейти на первый элемент итератора ( **@$obj** !! ) -- **all(obj)** - Получить сразу все элементы итератора ( **@$obj** ??) - - -### Прерывания -- **return** - Положительное прерывание (**++**) -- **return(...)**- Положительное прерывание с возвратом значения (**++** @$value **++**) - -- **error** - Отрицательное прерывание (**-\-**) -- **error(...)** - Отрицательное прерывание с возвратом значения (**-\-** @$value **-\-**) - -- **break+** и **break-** - Выход из цикла: -``` - while(...) {+ - ++ :Break ++ - +} - while(...) {- - -- :Break -- - -} -``` -- **continue+** и **continue-** - В начало цикла: -``` - while(...) {+ - ++ :Continue ++ - +} - while(...) {- - -- :Continue -- - -} -``` - - - - - -obj { - .field = 1; - .prop(); -}; - -#Python -# 1) without using with statement -file = open('file_path', 'w') -file.write('hello world !') -file.close() - - - -# 2) without using with statement -file = open('file_path', 'w') -try: - file.write('hello world') -finally: - file.close() - -open('file_path', 'w') { - .write('hello world !'); - .close(); -} - - -Python3 - -# using with statement -with open('file_path', 'w') as file: - file.write('hello world !') - - -# a simple file writer object - -class MessageWriter(object): - def __init__(self, file_name): - self.file_name = file_name - - def __enter__(self): - self.file = open(self.file_name, 'w') - return self.file - - def __exit__(self, *args): - self.file.close() - -# using with statement with MessageWriter - -with MessageWriter('my_file.txt') as xfile: - xfile.write('hello world') - - - - - -# a simple file writer object -:MessageWriter { - def __init__(self, file_name): - self.file_name = file_name - - def __enter__(self): - self.file = open(self.file_name, 'w') - return self.file - - def __exit__(self, *args): - self.file.close() -} - -# using with statement with MessageWriter - -MessageWriter('my_file.txt') { - .write('hello world'); -}; - - - - - - - -from contextlib import contextmanager - - -class MessageWriter(object): - def __init__(self, filename): - self.file_name = filename - - @contextmanager - def open_file(self): - try: - file = open(self.file_name, 'w') - yield file - finally: - file.close() - - -# usage -message_writer = MessageWriter('hello.txt') -with message_writer.open_file() as my_file: - my_file.write('hello world') - - - - -:MessageWriter(object) { - def __init__(self, filename): - self.file_name = filename - - @contextmanager - def open_file(self): - try: - file = open(self.file_name, 'w') - yield file - finally: - file.close() - -} - -# usage -message_writer = MessageWriter('hello.txt') -with message_writer.open_file() as my_file: - my_file.write('hello world') - +- *@if(...)* - Первый условный оператор +- *@elif(...)* - Второй и все последующие условные операторы +- *@else* - Оператор *иначе* +- *@while(...)* - Оператор цикла с предусловием +- *@dowhile(...)* - Оператор цикла с постусловием +- *@loop* - Оператор безконечного цикла +- *@break $label* - Оператор выхода из именованного именованного блока кода +- *@continue $label* - Оператор прехода на начало именованного блока кода +- *@return( result )* - Оператор возврата значения и выхода из функции +- *@throw( error )* - Оператор создания исключения и возврата ошибки +- *@match( ... )* - Оператор оценки выражения +- *@case( ... )* - Оператор сравнения с образцом +- *@default* - Оператор выбора по улочанию -# Приложения +- *@iter(obj, ... )* - Создание итератора +- *@next(obj, ... )* - Получить следующий элемент итератора +- *@curr(obj, ... )* - Получить текущий элемент итератора +- *@first(obj)* - Перейти на первый элемент итератора +- *@all(obj)* - Получить сразу все элементы итератора ## Предопределенные макросы -При работе парсера *NewLang* автоматически формируются несколько зарезервированных макросов, часть из которых соответствуют макросам препроцессора у С/С++. +При работе парсера *NewLang* автоматически формируются несколько зарезервированных макросов, +часть из которых соответствуют макросам препроцессора у С/С++. Данные предопределенные макросы можно использовать как обычные константы. - \_\_FILE\_\_ или \_\_FILE_NAME\_\_ - имя и полный путь текущего файла diff --git a/site/content/ru/docs/syntax/macros.md b/site/content/ru/docs/syntax/macros.md index 74ef6c5c..1951c258 100644 --- a/site/content/ru/docs/syntax/macros.md +++ b/site/content/ru/docs/syntax/macros.md @@ -5,6 +5,7 @@ title: Макросы weight: 50 --- +Макросы используются и для превращеня исходного кода *NewLang* в более привычный синтаксис на основе [ключевых слов](https://newlang.net/syntax_dsl.html), так как такой тест гораздо легче воспринимается при последующем чтении исходного кода. Макросы в **NewLang**, это один или несколько последовательных терминов, которые заменяются на другой термин или на целую синтаксическую конструкцию (последовательность лексем). @@ -60,13 +61,13 @@ weight: 50 следует определять макрос без аргументов и в этом случае контроль параметров будет выполнятся компилятором. ```bash - @@macro@@ := term; # Макрос без аргументов + @@ macro @@ := term; # Макрос без аргументов macro(args); # ОК -> term(args); macro; # ОК -> term; # Но - @@call()@@ := term(); + @@ call() @@ := term(); call(); # ОК -> term(); call; # Ошибка (@call определен с аргументами) @@ -86,371 +87,58 @@ weight: 50 `@@macro($arg)@@ := @@ func_ @## @$arg( @#" arg ) @;`, тогда вызов `macro(name);` будет преобразован в `func_name ("name");` - -{{% pageinfo %}} - -#### Ограничения макропроцессора в текущей версии - -На текущий момент макросы реализованы в минимальном объеме для самых простых сценариев использования: - -- DSL для keyword based syntax (if, else, return, match, while и т.д.) - (1 термин с произвольными аргументами и без) - требуется сейчас !!! - -*Парсер при обработке макросов может анализировать информацию о типах данных, если она указана.* -*Но на текущий момент типы данных в макросах никак не обрабатываются и это одна из обязательных фич, которая будет реализована в будущем.* - -- Определения (func, class) - (несколько терминов с аргументами и без аргументов) - Реализация ООП и импорт С++ классов -- Модификации при определениях (override) - (несколько терминов и шаблоны с аргументами и без аргументов) - Реализация ООП и импорт С++ классов - -{{% /pageinfo %}} - - -# МАКРОСЫ БЕЗ АРГУМЕНТОВ ИЛИ ВСЕ АРГУМЕНТЫ СРАЗУ !!!!! -# анализа аргументов или их типов не производится !!! - - - - -Lambda -@@ lambda $name(...) @@ ::= @@ @$name( @$... ) ::= ( _( @$... ) ::= @__PRAGMA_FINALIZE__( @\), {, {+, {-, {* ) @@ - - -### Примеры использования макросов - -```bash +Примеры использования макросов: +```python # Обычные макросы (тело макроса корректное выражение) - @@macro@@ := replace(); - @@macro2(arg)@@ := { call(@$arg); call()}; + @@ macro @@ := replace(); + @@ macro2(arg) @@ := { call(@$arg); call()}; # Тело макросов из последовательности лексем - @@if(...)@@ := @@ [ \$if(*) ]--> @@; # Выражение может быть не полным - @@elif(...)@@ := @@ ,[ \$elif(*) ]--> @@; - @@else@@ := @@ ,[_]--> @@; + @@ if(...) @@ := @@ [ @$... ]--> @@; # Выражение может быть не полным + @@ elif(...) @@ := @@ ,[ @$... ]--> @@; + @@ else @@ := @@ ,[...]--> @@; # Запись условного оператора с использованием # определенных выше макросов - if( condition ){ + @if( condition ){ ... - } elif( condition2 ) { + } @elif( condition2 ) { ... - } else { + } @else { ... }; ``` - - - - - - - - - -Зачем нужна трансформация синтаксиса? -Нативная поддержка других языков нужна чтобы не переписывать легаси код на этих языках. - -Чтобы можно было использовать существующие исходники как собственные требуется настройка работы -препроцессора и лексера под конкретный язык программирования (описание DSL). -Для **С/С++** потребуется выделять лексером комментарии из-за пересечения синтаксиса (которые сейчас игнорируются). -Для **Python** требуется выделять лексером отступы (которые сейчас тоже игнорируются), причем потребуется реализация не только синтаксиса, -но и зависимых пакетов с последующая трансляцией этого кода в С++, что в настоящий момент делать не целесообразно (cython ???). - -Но так как возможность трансформации кода с других языков программирования принципиальная возможна, -стоит над этим думать только после полноценного релиза NewLang и его перехода в прод. - - - -Для реализации DSL требуется передача команд в парсер для управления его работой (по аналогии с командой #pragma) -Но так как обработка таких команд должна происходить в лексере до передачи данных в парсер (анализатор), -то команды для макропроцессора должны быть в максимально простом виде и состоять из элементов, -которые лексер может самостоятельно идентифицировать, т.е. термины, строки и цифры (без выражений и именованных аргументов). - -После обработки такой команды она анализируется макропроцессором и удаляется из потока лексем, т.е. в парсер (анализатор) не передается. -Но в случае ошибки с синтаксисе, данные команды нужно уметь однозначно идентифировать и самый простой способ, -комбинация признака макроса и системного имени, т.е. что-то вроде -``` - @__PRAGMA_DIAG__(push) - @__PRAGMA_DIAG__(ignored, "-Wundef") - @__PRAGMA_DIAG__(warning, "-Wformat") - @__PRAGMA_DIAG__(error "-Wuninitialized") - @__PRAGMA_DIAG__(pop) - - #pragma message "Compiling " __FILE__ "..." - @__PRAGMA_MESSAGE__("Compiling ", __FILE__, "...") - - #pragma error "Error " __FILE__ "..." - @__PRAGMA_ERROR__("Error ", __FILE__, "...") - - -#define DO_PRAGMA(x) _Pragma (#x) -#define TODO(x) DO_PRAGMA(message ("TODO - " #x)) - -@@TODO( ... )@@ := @__PRAGMA_MESSAGE__("TODO - ", @*) - -@TODO(Remember to fix this) # note: TODO - Remember to fix this - -\\.__lexer__ignore_space__ = 1; -\\.__lexer__ignore_indent__ = 1; -\\.__lexer__ignore_comment__ = 1; -\\.__lexer__ignore_crlf__ = 1; - - -``` - - -Таким образом можно трансформировать условный оператор на питоне в синтаксис NewLang следующим макросом: -``` - -#pragma clang attribute push -#pragma clang diagnostic ignored "-Wundef" -#pragma clang diagnostic ignored "-Wunused-variable" - - -#elif __GNUC__ - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wuninitialized" - -#pragma GCC diagnostic ignored "-Wall" -#pragma GCC diagnostic ignored "-Wextra" - - @pragma warning(pop) - - @@ pragma warning(...) @@ := __PRAGMA_TERM_DIAG_WARNING__(); -@__PRAGMA_DIAG__(warning, pop); - -Обработка терминов в макропроцессоре в максимально простом виде. -Агрументы только термины, строки и цифры без вложенных выражений и именованных аргументов, -т.е. только элементы, которые может самостоятельно идентифицировать лексер. - -@warning("--") - @@ if ... : @@ := @@ [ @$* ]-> __TERM_BLOCK_INDENT__("{", force_semicolon=1) @@ - - if __name__ == "__main__": - run1() - run2() - - [ __name__ == "__main__" ]-> { - run1(); - run2(); +Например цикл до 5: +```python + count := 1; + [ 1 ] <-> { + [ count > 5 ] --> { + -- 42 --; + }; + count+=1; }; - - - ``` - - - - - - - -Ключ --parser-syntax-only только текстовый парсинг исходного кода без загрузки модулей, раскрытия макросов и проверки имен. - -Ключ --parser-no-macros - без раскрытия макросов -Ключ --parser-no-module - без загрузки модулей (и мокросов, если они в них определяются) -Ключ --parser-no-check-prototype - без проверки имен при обращении - -prototype -@__PRAGMA_PROTOTYPE__(define) -@__PRAGMA_PROTOTYPE__(implement) - -$$ - -\\$ - корень системы (система) - -\$ - текущий модуль - -# Макросы для конвертора проверки в Python -# if __name__ == "__main__": - -@@ __name__ @@ ::= @@ \$. @__PRAGMA_NO_MACRO__() __name__ @@ -@@ if $... @\: @@ ::= @@ [ @$... ] --> @@ - -@if( \$.__name__ == "__main__" ) { - - -} - -\\каталог\модуль() - статический импорт модуля -\\("каталог\модуль")() - динамический импорт модуля - - -printf := :Pointer('printf(format:FmtChar, ...):Int32'); -printf := %printf(format:FmtChar, ...):Int32; - - -# Регистрация прототипа нативной функции -@prototype -%puts(format:StrChar):Int32; - -# Импорт нативной функции с предварительной проверкой её наличия во время компиляции (статическая линковка) -puts2(format:StrChar):Int32 := %puts(format:StrChar):Int32; -# Импорт нативной функции по её прототипу во время выполнения (динамическая линковка) -puts3(format:StrChar):Int32 := :Pointer('puts(format:StrChar):Int32'); - -%puts('Тест вывода строки'); # Линковка с нативной функцией во время компиляции и непосредственный вызов с оптимизацией передачи параметров -puts2('Тест 2 вывода строки'); # Линковка с нативной функцией во время компиляции -puts3('Тест 3 вывода строки'); # Линковка с нативной функцией во время выполнения при первом вызове puts3 - - - -- Парсинг исходного текста без раскрытия макросов и загрузки модулей -- Парсинг исходного текста с раскрытием макросов (требуется загрузка модулей для зависимых и переопределяемых макросов) -- Загружатся модули могут как в виде исходников (которые требуется парсить и компилировть/выполнять) -или в виде бинарников (в них должны быть список макросов, типов и имена объектов) -- После парсинга получается список **имен** макросов, типов и объектов (TermPtr) -- После выполнения модуля - список **имен** заполняется реальными объектами (ObjPtr). - - -# Компиляция файла -- Парсинг исходника для построения AST (без анализа имен, связей, загрузки модулей и пр. только исходые тексты с раскрытием макросов -- - - -# Систематизация реализации макросов - -последовательность лексем MACRO_SEQ мужду @@ @@ сохраняется в m_block, так как фрагменты блоков не могут быть идентификаторами - -Разбор макросов происходит в лексере. Определением макроса всегда является целая строка, -которая заканчивается точкой с запятой, а идентификатором макроса всегда выступает последовательность лексем: -```bash - @@ id @@ := macro; - @@ id @@ := @@ @@; - @@ id @@ := @@@ @@@; -``` -Хранилищем текущих максросов является объект класса MacroBuffer. -Последовательность лексем идентификатора (id) макроса должна сохраняется в отдельном поле термина и однозначно его идентифицирует. -Первый термин в идентификаторе хранится как ключ hashmap, а дальше происходит поиск полным перебором. -Этапы работы с макросами - -- Входные термины из лексера получаются вызовом GetNextToken, внутри которой и происходит раскрытие макросов. -Внутренний буфер заполняется до окончания строки (выражения), т.е. до символа ';' или <END>, после чего производится -поиск макросов в объекте MacroBuffer для текущей последовательности лексем в буфере. - -- Если макрос найден, то соответствющая ему последоваетльность заменяется на тело макроса и происходит переход -на повторный анализ входного буфера. - -- Если макрос не найден, то данные передаются в парсер для дальнейшего синтаксическго анализа. - -- Для этого во входном потоке лексем (parser.y) во время оператората создания/присвоения вызывается функция проверки на макрос. -MacroBuffer::CheckMacroAndConvertDel($$), и после этого выходному значению присваивается результат выполнения driver.MacroEval($$), -и в дальнейшем этот макрос никак не обработывается. - -- Создание макросов, проверка на дубликаты и логические ошибки в определении происходит путем обращения к методам объекта MacroBuffer. - - - - - - - /* - * Макросы хрянтся как фрагменты AST в виде объектов типа Term, - * так как создаются после обработки парсером по правилам стандратной грамматики. - * - * Но анализ входных данных на предмет раскрытия макросов проиходит из потока (последовательности) лексем, - * т.е. **ДО** обработки парсером, так как при раскрытии макросов может меняться грамматика выражений. - * - * Функция \ref CompareMacro сравнивает входной буфер (последовательность лексем) - * на предмет возможного соответствия одному конкретному макросу. - * Сравниваются только ключевые словам без учета аргументов в скобках, - * но само наличие аргументов проверяется ?????????????????? - * - * Проблема: - * К функции можно обратится с целью её вызова (указав после имени скобки), - * так и по имени без скобок (например для получения ссылки на объект). - * Так и к переменной можно обратиться только по имени, - * так и указав скобки после имени как к функции (при копировании объекта). - * - * Сделать один макрос под оба сценария (со скобками и без скобок) не получится, так как непонятно, - * что делать с аргументами при раскрытии тела макроса, когда они не указаны. - * - * Но может быть следует переименовывать только одно имя без учета скобок, - * например, оставив такую возможность только для одиночных макросов. - * - * \name -> name или name (...), hash: name - * но \name(...) -> name(...), а name - ошибка !!!! hash: name - * - * Или все же следует различать макросы со скобками и без скобок как два разных объекта??? - * \name := name2; и \name(...) := name2(...); будут разными объектами - * - * Или добавить макросы-алиасы без аргументов только для переименования отдельных терминов? - * \alias :- name2; но как их отличать от обычных макросов в операции удаления? - * Или вообще не нужно отличать и оставить только один варинат (либо макрос, либо алиас) - * Тода вопрос со скобками закрывается сам собой, алиасы всегда без скобок, - * макросы со скбками или без скобок, но должно быть полное соответствие. - * - * @ name name2 @ -> name name2, но name name2(...) - ошибка!!! (hash: name,name2) - * @ name name2(...) @ -> name name2(...), но name name2 - ошибка !!!! (hash: name,name2) - * @ name name2[...](...) @ -> name name2[...](...), но name name2 - ошибка !!!! ( hash: name,name2 ) - * @ name $tmpl[...](...) name3@ -> name $tmpl[...](...) name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 ) - * - * Но! - * @ name name2 @ ::- -> name name2 - ок, но name name2(...) - ок - * @ name $tmpl name3@ ::- -> name $tmpl[...](...) name3 - ок, name $tmpl(...) name3[...] - ок - * - * - * - * Для последовательности лексем требуется полное соответствие с учетом скобок ??? - * и может ли быть несколько скобок одного типа (несколько крыглях, или несколько квардратных???? - * <Может быть несколько скобок одного типа, например, при указании типа у аргументов или типа возвращаемого значения.> - * - * @ name name2 @ -> name name2, но name name2(...) - ошибка!!! (hash: name,name2) - * @ name name2(...) @ -> name name2(...), но name name2 - ошибка !!!! (hash: name,name2) - * @ name name2[...](...) @ -> name name2[...](...), но name name2 - ошибка !!!! ( hash: name,name2 ) - * @ name $tmpl[...](...) name3@ -> name $tmpl[...](...) name3, но name $tmpl name3 - ошибка !!!! ( hash: name,$,name3 ) - * - * Проблема скобок возникает из-за сценария замены одного термина на другой, - * который есть в препроцессоре С/С++, но отсутствует при реализации с использованием шаблонов. - * - * - */ - - - - - - -Макросы используются и для превращеня исходного кода *NewLang* в более привычный синтаксис на основе [ключевых слов](https://newlang.net/syntax_dsl.html), так как такой тест гораздо легче воспринимается при последующем чтении исходного кода. - - -[Например:](https://newlang.net/syntax_dsl.html). -``` - @@if(...)@@ ::= @@ [ \$* ]--> @@; - @@while(...)@@ ::= @@ [\$*] <-> @@; - @@return $arg@@::= @@ -- \$arg -- @@; - @@true@@ ::= 1; -``` - -Тогда цикл до 5: -``` -count:=1; -[ 1 ] <-> { - [count>5] --> { - -- 42 --; - }; - count+=1; -}; -``` - -будет выглядеть более привычно -``` -count:=1; -while( true ) { - if(count>5) { - return 42; +Будет выглядеть более привычно: +```python + count := 1; + @while( true ) { + @if( count > 5 ) { + @return 42; + }; + count += 1; }; - count+=1; -}; ``` +{{% pageinfo %}} - -## Идеи на будущее +### Далее идеи на будущее ### Символьное программирование +{{% /pageinfo %}} + > Символьное программирование, часто называемое декларативным программированием, представляет собой парадигму программирования, которая использует математическую логику, отношения и символы для представления знаний и помощи в решении проблем. Вместо того, чтобы сосредотачиваться на описании последовательности операций, необходимых для выполнения вычислений, как в императивном программировании, символическое программирование делает упор на выражении отношений и ограничений между структурами данных, уделяя особое внимание «что», а не «как». > > В контексте парадигм программирования символическое программирование часто противопоставляется процедурному или императивному программированию, где программы определяют пошаговые процедуры для достижения своих целей. В то время как императивное программирование фокусируется на описании потока управления с использованием таких конструкций, как циклы и условные выражения, для управления выполнением, символическое программирование сосредоточено на выражении фактов о проблеме и позволяет выполнению естественным образом выводить последующие последствия из предоставленной информации. diff --git a/site/content/ru/docs/types/native.md b/site/content/ru/docs/types/native.md index fa5a19a0..7cc98530 100644 --- a/site/content/ru/docs/types/native.md +++ b/site/content/ru/docs/types/native.md @@ -9,14 +9,44 @@ tags: [типы данных, системые типы, коллекции] ## Нативные типы данных Нативными (машинные) данными могут быть как переменные, так и функции, а имя нативных объектов начинается на символ процента "**%**". -В случае пемеенных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определнный формат. -### :Pointer — указатель на системную область памяти или нативную функцию +В случае переменных, это двоичные данные, которые располагаются в одной неразрывной области машинной памяти по определенному адресу и имеют строго определенный формат. + +Чтобы использовать уже существующие библиотеки, нужно импортировать нативный объект, +тем самым создав объкт NewLang, но с реализацией на другом языке, например на С/С++. + +Синтаксис импорта нативных объектов такой же, как и для [создания](/ru/docs/ops/create/) обычных объектов языка, +только в качестве правого операнда в операторе создания требуется указать имя нативнного объекта. + +При импорте нативного объекта необходимо всегда указывать типы переменных, а также типы аргументов и возвращаемых значений для функций. + +Если типы данных у создаваемого и нативного объекта совпадают (т.е. не требуется преобразование типов), +то нативное имя объекта можно указать с многоточием, которое означает, что типы данных будут повторять заданные у левого операнда. + +```python +:FILE ::= :Plain; + +fopen(filename:StrChar, modes:StrChar):FILE ::= %fopen...; +fclose(f:FILE):Int32 ::= %fclose...; +fflush(f:FILE):Int32 ::= %fflush...; +fprintf(f:FILE, format:FmtChar, ...):Int32 ::= %fprintf...; +fremove(filename:String):Int32 ::= %remove...; +frename(old:String, new:String):Int32 ::= %rename...; +``` -Так как любой программе приходится взаимодействовать с внешним миром, т -о по неволе приходится закладывать возможность использования других библиотек и системы типов данных, + +{{% pageinfo %}} + +Последующее описание находится в процессе разработки. + +{{% /pageinfo %}} + +### :Pointer — указатель на системную область памяти или нативную функцию + +Так как любой программе приходится взаимодействовать с внешним миром, +то по неволе приходится закладывать возможность использования других библиотек и системы типов данных, и для этих целей служит тип *:Pointer*. Он создается при импорте функций из внешних библиотек и вручную его создать нельзя. Но можно вывести его значение, например для отладки. diff --git a/site/content/ru/playground/_index.md b/site/content/ru/playground/_index.md index 54b44f5e..1889423a 100755 --- a/site/content/ru/playground/_index.md +++ b/site/content/ru/playground/_index.md @@ -8,9 +8,6 @@ menu: main weight: 25 --- -Примеры программ на NewLang - - <style> .rownr {width: 5%; overflow-y: hidden; background-color: rgb(105,105,105); color: white; text-align: right; vertical-align:top; resize: none;} @@ -20,6 +17,10 @@ weight: 25 .pgbox {margin-top: 4rem;} </style> +<p> +<br> +</p> + <div class="pgbox"> <select class="c10" style="width: 95%;" onchange="SelectExample(this);" id="example_list"> <option selected="selected" value="" id="example_start">Select an exmaple...</option> @@ -69,18 +70,6 @@ weight: 25 <script> -if(window.location.search){ - const params = new Proxy(new URLSearchParams(window.location.search), { - get: (searchParams, prop) => searchParams.get(prop), - }); - // Get the value of "src" in eg "https://example.com/?src=source" - if(params.src){ - document.getElementById('playground').value = unescape(params.src); - } - //alert(escape('#!../output/nlc \n\nprint(\'Hello, world!\\n\');\n')); - // %23%21../output/nlc%20%0A%0Aprint%28%27Hello%2C%20world%21%5Cn%27%29%3B%0A -} - locations =[ "", "{{< source "hello.src" >}}", "{{< source "rational.src" >}}", @@ -89,14 +78,17 @@ locations =[ "", "{{< source "tensor.src" >}}", ]; -function SelectExample(sel){ - - srcLocation = locations[sel.selectedIndex]; - if (srcLocation != undefined && srcLocation != "") { - obj = document.getElementById('playground'); - obj.value = locations[sel.selectedIndex]; - input_changed(obj); - } +function SelectExample(sel){ + obj = document.getElementById('playground'); + if(Number.isInteger(sel) && locations[sel]){ + obj.value = locations[sel]; + } else { + srcLocation = locations[sel.selectedIndex]; + if (srcLocation != undefined && srcLocation != "") { + obj.value = locations[sel.selectedIndex]; + } + } + input_changed(obj); } @@ -251,7 +243,7 @@ function run_playground(){ clearInterval(downloadTimer); document.getElementById('progress').style.display = "none"; document.getElementById('playground_out').classList.add("error"); - alert("Request failed!"); + alert("Request failed!\n\nCheck the connection protocol!\n\nThe site should open using the regular HTTP protocol without using SSL! Because browsers typically block unsecured connections on HTTPS pages."); }; xhr.ontimeout = (e) => { @@ -260,4 +252,20 @@ function run_playground(){ alert("Run query timeout!"); }; } + + +if(window.location.search){ + const params = new Proxy(new URLSearchParams(window.location.search), { + get: (searchParams, prop) => searchParams.get(prop), + }); + // Get the value of "src" in eg "https://example.com/?src=source" + if(params.id){ + SelectExample(parseInt(params.id)); + } else if(params.src){ + document.getElementById('playground').value = unescape(params.src); + } + //alert(escape('#!../output/nlc \n\nprint(\'Hello, world!\\n\');\n')); + // %23%21../output/nlc%20%0A%0Aprint%28%27Hello%2C%20world%21%5Cn%27%29%3B%0A +} + </script> \ No newline at end of file diff --git a/src/analysis.cpp b/src/analysis.cpp index 5a3f2a9d..424a96d7 100644 --- a/src/analysis.cpp +++ b/src/analysis.cpp @@ -380,6 +380,11 @@ bool AstAnalysis::CheckNative_(TermPtr &proto, TermPtr &native) { return false; } + if (!m_rt.m_import_native) { + NL_MESSAGE(LOG_LEVEL_INFO, native, "Used flag '--nlc-no-import-native' to disabled import any native objects!"); + return false; + } + if (proto->isCall() != native->isCall()) { // Нативная функция с частичным прототипом TermPtr from; @@ -750,7 +755,7 @@ bool AstAnalysis::CreateOp_(TermPtr &op, ScopeStack & stack) { } -// ScopePush block(stack, proto, &proto->m_int_vars, true); + // ScopePush block(stack, proto, &proto->m_int_vars, true); TermPtr none = Term::CreateName("$0"); none->m_int_name = NormalizeName(none->m_text); @@ -1462,13 +1467,18 @@ bool AstAnalysis::RecursiveAnalyzer(TermPtr term, ScopeStack & stack) { return true; } + case TermID::MODULE: + if (!m_rt.m_import_module) { + NL_MESSAGE(LOG_LEVEL_INFO, term, "Used flag '--nlc-no-import-module' to disabled import any modules!"); + return false; + } + case TermID::NAME: case TermID::TYPE: case TermID::ARGS: case TermID::ARGUMENT: case TermID::LOCAL: case TermID::STATIC: - case TermID::MODULE: case TermID::NAMESPACE: { found = LookupName(term, stack); @@ -1555,6 +1565,14 @@ bool AstAnalysis::RecursiveAnalyzer(TermPtr term, ScopeStack & stack) { case TermID::ITERATOR: return CheckError(Iterator_(term, stack)); + + case TermID::EMBED: + if (!m_rt.m_embed_source) { + NL_MESSAGE(LOG_LEVEL_INFO, term, "Use flag '--nlc-embed-source' to enable embedded source code!"); + return false; + } + return false; // Not implemented + default: NL_MESSAGE(LOG_LEVEL_INFO, term, "AstRecursiveAnalyzer for type '%s' not implemented!", toString(term->getTermID())); } diff --git a/src/nbproject/configurations.xml b/src/nbproject/configurations.xml index 166cf89f..fe06a7fa 100644 --- a/src/nbproject/configurations.xml +++ b/src/nbproject/configurations.xml @@ -4,37 +4,10 @@ <logicalFolder name="content" displayName="content" projectFiles="true"> <logicalFolder name="en" displayName="en" projectFiles="true"> <logicalFolder name="blog" displayName="blog" projectFiles="true"> - <logicalFolder name="complex-prog" - displayName="complex-prog" - projectFiles="true"> - <itemPath>../site/content/en/blog/complex-prog/bag.jpeg</itemPath> - <itemPath>../site/content/en/blog/complex-prog/complex-prog.jpeg</itemPath> - <itemPath>../site/content/en/blog/complex-prog/drupal.jpeg</itemPath> - <itemPath>../site/content/en/blog/complex-prog/graph1.jpeg</itemPath> - <itemPath>../site/content/en/blog/complex-prog/graph2.png</itemPath> - <itemPath>../site/content/en/blog/complex-prog/graph3.jpeg</itemPath> - <itemPath>../site/content/en/blog/complex-prog/index.md</itemPath> - </logicalFolder> - <logicalFolder name="lang-final" displayName="lang-final" projectFiles="true"> - <itemPath>../site/content/en/blog/lang-final/index.md</itemPath> - <itemPath>../site/content/en/blog/lang-final/lang-final.jpeg</itemPath> - </logicalFolder> <itemPath>../site/content/en/blog/_index.md</itemPath> <itemPath>../site/content/en/blog/dsl-with-macros.en.md</itemPath> - <itemPath>../site/content/en/blog/dsl-with-macros.md</itemPath> <itemPath>../site/content/en/blog/dsl.jpeg</itemPath> - <itemPath>../site/content/en/blog/inter-prog.md</itemPath> - <itemPath>../site/content/en/blog/langs.jpeg</itemPath> - <itemPath>../site/content/en/blog/logic-prog.md</itemPath> - <itemPath>../site/content/en/blog/matrix.jpeg</itemPath> - <itemPath>../site/content/en/blog/newlang.md</itemPath> - <itemPath>../site/content/en/blog/parser-nuances.md</itemPath> - <itemPath>../site/content/en/blog/prog-styles-same-time.md</itemPath> - <itemPath>../site/content/en/blog/release-0.1.md</itemPath> - <itemPath>../site/content/en/blog/release-0.2.md</itemPath> - <itemPath>../site/content/en/blog/release-0.3.md</itemPath> <itemPath>../site/content/en/blog/release-0.4.md</itemPath> - <itemPath>../site/content/en/blog/unusual-prog.md</itemPath> </logicalFolder> <logicalFolder name="docs" displayName="docs" projectFiles="true"> <logicalFolder name="arch" displayName="arch" projectFiles="true"> @@ -447,117 +420,18 @@ </item> <item path="../site/content/en/blog/_index.md" ex="false" tool="3" flavor2="0"> </item> - <item path="../site/content/en/blog/complex-prog/bag.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/complex-prog.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/drupal.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/graph1.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/graph2.png" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/graph3.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/index.md" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../site/content/en/blog/dsl-with-macros.en.md" ex="false" tool="3" flavor2="0"> </item> - <item path="../site/content/en/blog/dsl-with-macros.md" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../site/content/en/blog/dsl.jpeg" ex="false" tool="3" flavor2="0"> </item> - <item path="../site/content/en/blog/inter-prog.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/lang-final/index.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/lang-final/lang-final.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/langs.jpeg" ex="false" tool="3" flavor2="0"> - </item> - <item path="../site/content/en/blog/logic-prog.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/matrix.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/newlang.md" ex="false" tool="3" flavor2="0"> - </item> - <item path="../site/content/en/blog/parser-nuances.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/prog-styles-same-time.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/release-0.1.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/release-0.2.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/release-0.3.md" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../site/content/en/blog/release-0.4.md" ex="false" tool="3" flavor2="0"> </item> - <item path="../site/content/en/blog/unusual-prog.md" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../site/content/en/docs/_index.md" ex="false" tool="3" flavor2="0"> </item> <item path="../site/content/en/docs/arch/_index.md" @@ -1550,117 +1424,18 @@ </item> <item path="../site/content/en/blog/_index.md" ex="false" tool="3" flavor2="0"> </item> - <item path="../site/content/en/blog/complex-prog/bag.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/complex-prog.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/drupal.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/graph1.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/graph2.png" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/graph3.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/index.md" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../site/content/en/blog/dsl-with-macros.en.md" ex="false" tool="3" flavor2="0"> </item> - <item path="../site/content/en/blog/dsl-with-macros.md" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../site/content/en/blog/dsl.jpeg" ex="false" tool="3" flavor2="0"> </item> - <item path="../site/content/en/blog/inter-prog.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/lang-final/index.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/lang-final/lang-final.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/langs.jpeg" ex="false" tool="3" flavor2="0"> - </item> - <item path="../site/content/en/blog/logic-prog.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/matrix.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/newlang.md" ex="false" tool="3" flavor2="0"> - </item> - <item path="../site/content/en/blog/parser-nuances.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/prog-styles-same-time.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/release-0.1.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/release-0.2.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/release-0.3.md" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../site/content/en/blog/release-0.4.md" ex="false" tool="3" flavor2="0"> </item> - <item path="../site/content/en/blog/unusual-prog.md" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../site/content/en/docs/_index.md" ex="false" tool="3" flavor2="0"> </item> <item path="../site/content/en/docs/arch/_index.md" @@ -2627,117 +2402,18 @@ </item> <item path="../site/content/en/blog/_index.md" ex="false" tool="3" flavor2="0"> </item> - <item path="../site/content/en/blog/complex-prog/bag.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/complex-prog.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/drupal.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/graph1.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/graph2.png" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/graph3.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/index.md" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../site/content/en/blog/dsl-with-macros.en.md" ex="false" tool="3" flavor2="0"> </item> - <item path="../site/content/en/blog/dsl-with-macros.md" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../site/content/en/blog/dsl.jpeg" ex="false" tool="3" flavor2="0"> </item> - <item path="../site/content/en/blog/inter-prog.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/lang-final/index.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/lang-final/lang-final.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/langs.jpeg" ex="false" tool="3" flavor2="0"> - </item> - <item path="../site/content/en/blog/logic-prog.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/matrix.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/newlang.md" ex="false" tool="3" flavor2="0"> - </item> - <item path="../site/content/en/blog/parser-nuances.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/prog-styles-same-time.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/release-0.1.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/release-0.2.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/release-0.3.md" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../site/content/en/blog/release-0.4.md" ex="false" tool="3" flavor2="0"> </item> - <item path="../site/content/en/blog/unusual-prog.md" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../site/content/en/docs/_index.md" ex="false" tool="3" flavor2="0"> </item> <item path="../site/content/en/docs/arch/_index.md" @@ -3608,117 +3284,18 @@ </item> <item path="../site/content/en/blog/_index.md" ex="false" tool="3" flavor2="0"> </item> - <item path="../site/content/en/blog/complex-prog/bag.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/complex-prog.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/drupal.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/graph1.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/graph2.png" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/graph3.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/index.md" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../site/content/en/blog/dsl-with-macros.en.md" ex="false" tool="3" flavor2="0"> </item> - <item path="../site/content/en/blog/dsl-with-macros.md" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../site/content/en/blog/dsl.jpeg" ex="false" tool="3" flavor2="0"> </item> - <item path="../site/content/en/blog/inter-prog.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/lang-final/index.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/lang-final/lang-final.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/langs.jpeg" ex="false" tool="3" flavor2="0"> - </item> - <item path="../site/content/en/blog/logic-prog.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/matrix.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/newlang.md" ex="false" tool="3" flavor2="0"> - </item> - <item path="../site/content/en/blog/parser-nuances.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/prog-styles-same-time.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/release-0.1.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/release-0.2.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/release-0.3.md" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../site/content/en/blog/release-0.4.md" ex="false" tool="3" flavor2="0"> </item> - <item path="../site/content/en/blog/unusual-prog.md" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../site/content/en/docs/_index.md" ex="false" tool="3" flavor2="0"> </item> <item path="../site/content/en/docs/arch/_index.md" @@ -4708,117 +4285,18 @@ </item> <item path="../site/content/en/blog/_index.md" ex="false" tool="3" flavor2="0"> </item> - <item path="../site/content/en/blog/complex-prog/bag.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/complex-prog.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/drupal.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/graph1.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/graph2.png" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/graph3.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/complex-prog/index.md" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../site/content/en/blog/dsl-with-macros.en.md" ex="false" tool="3" flavor2="0"> </item> - <item path="../site/content/en/blog/dsl-with-macros.md" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../site/content/en/blog/dsl.jpeg" ex="false" tool="3" flavor2="0"> </item> - <item path="../site/content/en/blog/inter-prog.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/lang-final/index.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/lang-final/lang-final.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/langs.jpeg" ex="false" tool="3" flavor2="0"> - </item> - <item path="../site/content/en/blog/logic-prog.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/matrix.jpeg" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/newlang.md" ex="false" tool="3" flavor2="0"> - </item> - <item path="../site/content/en/blog/parser-nuances.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/prog-styles-same-time.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/release-0.1.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/release-0.2.md" - ex="false" - tool="3" - flavor2="0"> - </item> - <item path="../site/content/en/blog/release-0.3.md" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../site/content/en/blog/release-0.4.md" ex="false" tool="3" flavor2="0"> </item> - <item path="../site/content/en/blog/unusual-prog.md" - ex="false" - tool="3" - flavor2="0"> - </item> <item path="../site/content/en/docs/_index.md" ex="false" tool="3" flavor2="0"> </item> <item path="../site/content/en/docs/arch/_index.md" diff --git a/src/runtime.cpp b/src/runtime.cpp index 4dfba615..9af3002a 100644 --- a/src/runtime.cpp +++ b/src/runtime.cpp @@ -1409,7 +1409,7 @@ m_diag(std::make_shared<Diag>()) { m_load_dsl = true; m_embed_source = false; m_import_module = true; - m_import_natime = true; + m_import_native = true; m_eval_enable = true; m_load_runtime = true; // m_error_limit = 10; diff --git a/src/runtime.h b/src/runtime.h index babda9dc..0ed4046d 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -21,11 +21,11 @@ namespace newlang { - + #ifdef __GNUC__ -extern "C" int nlc_prinft_sub_(char const *format, ...) __attribute__ ((format(printf, 1, 2))); + extern "C" int nlc_prinft_sub_(char const *format, ...) __attribute__ ((format(printf, 1, 2))); #else -EXTERN_C int nlc_prinft_sub_(char const *format, ...); + EXTERN_C int nlc_prinft_sub_(char const *format, ...); #endif template <typename T> @@ -211,7 +211,7 @@ EXTERN_C int nlc_prinft_sub_(char const *format, ...); ObjPtr CreateFunction(TermPtr proto, TermPtr block); ObjPtr CreateFunction(TermPtr proto, void *addr); - + static std::string Escape(const std::string_view str); /* * class A { @@ -363,7 +363,7 @@ EXTERN_C int nlc_prinft_sub_(char const *format, ...); bool m_load_dsl; bool m_embed_source; bool m_import_module; - bool m_import_natime; + bool m_import_native; bool m_eval_enable; bool m_load_runtime; int m_typedef_limit; @@ -436,13 +436,14 @@ EXTERN_C int nlc_prinft_sub_(char const *format, ...); // m_main_args = EvalStatic(MakeAst(call, true), false); } else if (args[i].compare("--nlc-embed-source") == 0) { + LOG_RUNTIME("Flag '--nlc-embed-source' not implemented!"); m_embed_source = true; } else if (args[i].compare("--nlc-no-embed-source") == 0) { m_embed_source = false; } else if (args[i].compare("--nlc-no-import-module") == 0) { m_import_module = false; } else if (args[i].compare("--nlc-no-import-native") == 0) { - m_import_natime = false; + m_import_native = false; } else if (args[i].compare("--nlc-no-eval-enable") == 0) { m_eval_enable = false; } else if (args[i].compare("--nlc-no-assert") == 0) {