Browse Source

SVI Добавление кода парсера и интерпретатора

SVI 2 months ago
parent
commit
8ac6be9437

+ 33 - 12
Taskfile.yml

@@ -10,14 +10,14 @@ tasks:
     cmds:
       - echo "{{.GREETING}}"
     silent: true
-  dev:
+  devi:
     desc: "Запуск для отладки интерпретатора"
     cmds:
       - clear
       - go fmt ./...
-      - go run -race ./cmd/proi/main.go
+      - go run -race ./cmd/plti/main.go
     env:
-      MAIN_PROLET: ./plt/main.plt
+      MAIN_PROLET: ./plt/main.pli
   mod:
     desc: "Установка/обновление всех зависимостей модулей"
     cmds:
@@ -34,14 +34,6 @@ tasks:
      OMP_NUM_THREADS: 16
      OMP_PROC_BIND: true
      OMP_PLACES: cores
-  read:
-    desc: "Чтение файла (pdftotext read.pdf > read.txt)"
-    cmds:
-      - RHVoice-client -s Anna+CLB < read.txt | aplay
-  wav:
-    desc: "Создание wav файла"
-    cmds:
-      - cat read.txt | RHVoice-client -s Anna+CLB > read.wav
   pros:
     desc: "Запуск сервера prolet на brython"
     cmds:
@@ -49,4 +41,33 @@ tasks:
       - cp -aT ./pub ./bin/pub
       - go fmt ./...
       - go build -race -o ./bin/pros ./cmd/pros/main.go
-      - cd ./bin && ./pros
+      - cd ./bin && ./pros
+  fmt:
+    desc: "Форматирование кода"
+    cmds:
+      - clear
+      - go fmt ./...
+  lazy:
+    desc: "Запуск lazygit (с обновлением)"
+    cmds:
+      - go install github.com/jesseduffield/lazygit@latest
+      - lazygit
+  lint:
+    desc: "Запуск всех линтеров"
+    cmds:
+      - clear
+      - go fmt ./...
+      - go vet ./...
+      - go install honnef.co/go/tools/cmd/staticcheck@latest
+      - staticcheck ./...
+      - go install github.com/MakeNowJust/enumcase/cmd/enumcase@latest
+      - enumcase ./...
+      # - go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
+      - go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2
+      - golangci-lint run ./...
+      - go install github.com/fzipp/gocyclo/cmd/gocyclo@latest
+      - gocyclo -over 11 .
+      - go install github.com/securego/gosec/cmd/gosec@latest
+      - gosec ./...
+      # - pipx install semgrep
+      # - semgrep scan --config .semgrep.yml

+ 10 - 0
cmd/pltc/main.go

@@ -0,0 +1,10 @@
+// package main -- пускач для компилятора
+package main
+
+import (
+	"log"
+)
+
+func main() {
+	log.Println("Hello, World!")
+}

+ 19 - 0
cmd/plti/main.go

@@ -0,0 +1,19 @@
+// package main -- пускач для интерпретатора
+package main
+
+import (
+	"log"
+	"plt/lev2/vm"
+)
+
+func main() {
+	log.Println("main()")
+	vm := read()
+	vm.Run()
+}
+
+// Читает IL-файл, парсит, возвращает
+func read() *vm.Vm {
+	vm := vm.NewVm()
+	return vm
+}

+ 12 - 0
cmd/plti/main.pli

@@ -0,0 +1,12 @@
+# Код на промежуточном языке для prolet
+
+Отладка(Программа запущена)
+
+Отладка(А тут
+
+вывод
+
+в несколько
+
+строк. Потому что
+можем)

+ 2 - 0
dev.env

@@ -0,0 +1,2 @@
+# Главный файл с инструкциями
+export MAIN_PROLET=./plt/main.pli

+ 130 - 104
docs/docs/01_70.md

@@ -10,10 +10,10 @@
 
 ### Диалектический принцип
 
-- Ядро языка — неподвижно (в пределах версии), но совместимо (в пределах всех версий)
-- Расширение — подвижно,
-- Но движущееся порождается из неподвижного, отрицает его,
-- И в своём развитии — отрицает отрицание,
+* Ядро языка — неподвижно (в пределах версии), но совместимо (в пределах всех версий)
+* Расширение — подвижно,
+* Но движущееся порождается из неподвижного, отрицает его,
+* И в своём развитии — отрицает отрицание,
 
 поднимая язык на новый уровень.
 
@@ -25,15 +25,15 @@
 
 ### Ядро (Базис)
 
-- Устойчивая основа: атомы, управление, память, вызовы;
-- Последовательная разработка ядра на основе реальных потребностей;
-- Объективный подход ко всем аспектам языка.
+* Устойчивая основа: атомы, управление, память, вызовы;
+* Последовательная разработка ядра на основе реальных потребностей;
+* Объективный подход ко всем аспектам языка.
 
 ### Расширение (Творчество)
 
-- Развитие: новые парадигмы, **DSL**, оптимизации, замена частей ядра,
-- Частные расширения контекстов но основе текущих потребностей,
-- Субъективная инициатива.
+* Развитие: новые парадигмы, **DSL**, оптимизации, замена частей ядра,
+* Частные расширения контекстов но основе текущих потребностей,
+* Субъективная инициатива.
 
 Это — единство и борьба форм, где форма выражает содержание диалектики.
 
@@ -54,7 +54,6 @@
   )
 )
 
-
 атом(
   имя(Пользователь)
   протон(
@@ -69,7 +68,6 @@
   )
 )
 
-
 прц(
   имя(Пуск)
   нач(
@@ -88,10 +86,10 @@
 
 Особенности ядра:
 
-- Неизменно в рамках версии 1.x;
-- Компилируется во внутреннее представление напрямую;
-- Не может быть переопределено, но может быть перекрыто частным определением;
-- Создаётся централизованно на основе теории и практики.
+* Неизменно в рамках версии 1.x;
+* Компилируется во внутреннее представление напрямую;
+* Не может быть переопределено, но может быть перекрыто частным определением;
+* Создаётся централизованно на основе теории и практики.
 
 > 💡 Это — материальная база, как производительные силы в экономике — нельзя менять каждый день, но можно развивать в следующей версии, с развитием производственных отношений.
 
@@ -109,22 +107,28 @@
     ядро()
   )
   автор(user@ya.ru)
-  док: "Конструктор запроса SELECT"
-  парам:
-    - тело данные
-    - тело спека
-  нач:
-    - ЗагрузитьДанные {данные}
-    - ОбновитьСпек {спека}
+  док("Конструктор запроса SELECT")
+  парам(
+    тело(данные)
+    тело(спека)
+  )
+  нач(
+    ЗагрузитьДанные(встав(данные))
+    ОбновитьСпек(встав(спека))
+  )
+)
+
+макро(
+  имя(выбор)
+  парам(
+    тело(таблица)
+    тело(возраст)
+  )
+  нач(
+    встав("SELECT * FROM {пользователь} WHERE возраст > ?" {возраст}")
+  )
 )
 
-макро:
-  имя: выбор
-  парам:
-    - тело таблица
-    - тело возраст
-  нач:
-    - SQL "SELECT * FROM {пользователь} WHERE возраст > ?" {возраст}
 ```
 
 Как это работает: `параллельно` — не ключевое слово, а расширение, определённое в пользовательской библиотеке, на том же уровне. Эффект `ядро` запрещает переопределять или изменять макрос.
@@ -137,72 +141,81 @@
 
 ### Формы ядра
 
-- Форма: `%контекст: ...`
-- Изменяемость: Запрещена в версии (эффект `ядро`)
-- Компиляция: На этапе 1
-- Авторство: разработчики ядра
-- Ответственность: Гарантирована
-- Жизненный цикл: Долгий (версии 1.0, 2.0)
+* Форма: `%контекст(...)`
+* Изменяемость: Запрещена в версии (эффект `ядро`)
+* Компиляция: На этапе 1
+* Авторство: разработчики ядра
+* Ответственность: Гарантирована
+* Жизненный цикл: Долгий (версии 1.0, 2.0)
 
 ### Формы пользователя
 
-- Форма: `макро: ...`
-- Изменяемость: Разрешена, по согласованию
-- Компиляция: На этапе 2 (после ядра, но до разбора исходного текста)
-- Авторство: Сообщество, отдельные разработчики
-- Ответственность: На авторе расширения
-- Жизненный цикл: Краткий (пробный, экспериментальный)
+* Форма: `макро(...)`
+* Изменяемость: Разрешена, по согласованию
+* Компиляция: На этапе 2 (после ядра, но до разбора исходного текста)
+* Авторство: Сообщество, отдельные разработчики
+* Ответственность: На авторе расширения
+* Жизненный цикл: Краткий (пробный, экспериментальный)
 
 Это — диалектическое разделение труда в языке:
 
-- Ядро — закон,
-- Расширение — инициатива,
-- Их единство — развитие.
+* Ядро — закон,
+* Расширение — инициатива,
+* Их единство — развитие.
 
 ## Переход от старого к новому: процесс отрицания
 
 Пример: появление нового цикла в потоках (старое ядро):
 
-```yml
-прц:
-  имя: Пуск
-  нач:
-    - ЦиклПо списокЗадач СоздатьПоток рез
+```python
+прц(
+  имя(Пуск)
+  нач(
+    ЦиклПо(списокЗадач
+      СоздатьПоток()
+      рез
+    )
+  )
+)
 ```
 
 После проверки практикой — включение в ядро новой версии (расширение):
 Новое (расширение):
 
-```yml
-прц:
-  имя: Пуск
-  нач:
-    - параллельно Выполнить списокЗадач, Печать "Параллельная печать в терминал!"
+```python
+прц(
+  имя(Пуск)
+  нач(
+    параллельно(
+      Выполнить(списокЗадач)
+      Печать()"Параллельная печать в терминал!")
+  )
+)
 ```
 
 Это — отрицание отрицания:
 
-- Старое `ЦиклПо ... СоздатьПоток` — отрицается,
-- Новый макрос `параллельно ...` — отрицает старое,
+* Старое `ЦиклПо(... СоздатьПоток)` — отрицается,
+* Новый макрос `параллельно ...` — отрицает старое,
 
-Но затем `параллельно ...` само отрицается — становится частью ядра, и появляется новое расширение для асинхронных потоков.
+Но затем `параллельно(...)` само отрицается — становится частью ядра, и появляется новое расширение для асинхронных потоков.
 
 ## Психологическая и педагогическая выгода
 
 Для новичка:
 
-- Видит только `%контекст: ...` — простота, порядок, безопасность.
-- Расширения скрыты или отключены.
+* Видит только `%контекст(...)` — простота, порядок, безопасность.
+* Расширения скрыты или отключены.
 
 Для специалиста:
 
-- Может писать `макро: ...`, на пользовательском уровне, но осознаёт, что это — эксперимент, что он выходит за рамки устоявшегося, что за это несёт ответственность. При компиляции получает уведомление (если не подавлено атрибутом).
+* Может писать `макро(...)`, на пользовательском уровне, но осознаёт, что это — эксперимент, что он выходит за рамки устоявшегося, что за это несёт ответственность. При компиляции получает уведомление (если не подавлено атрибутом).
 
 Расширения разработчиками ядра могут быть:
 
-- Одобрены,
-- Отклонены,
-- Включены в следующую версию ядра.
+* Одобрены,
+* Отклонены,
+* Включены в следующую версию ядра.
 
 Это — демократический централизм в действии.
 
@@ -210,23 +223,23 @@
 
 Этап 1: Парсинг ядра
 
-- Обрабатывает только системные библиотеки, строит **AST**.
-- выполняет предварительную компиляцию ядра (однократно).
+* Обрабатывает только системные библиотеки, строит **AST**.
+* выполняет предварительную компиляцию ядра (однократно).
 
 Этап 2: Макро-раскрытие расширений на уровне пользователя
 
-- Находит `макро: ...`, подставляет определение из зарегистрированных расширений;
-- Проверяет квалификацию, тесты, отсутствие эффекта `ядро`.
+* Находит `макро(...)`, подставляет определение из зарегистрированных расширений;
+* Проверяет квалификацию, тесты, отсутствие эффекта `ядро`.
 
 Этап 3: Трансляция в ядро
 
-- Все пользовательские макросы интегрируются в ядро;
-- Проставляется эффект `ядро`.
+* Все пользовательские макросы интегрируются в ядро;
+* Проставляется эффект `ядро`.
 
 Этап 4: Компиляция
 
-- только изменившийся код.
-- сборка готовых модулей.
+* только изменившийся код.
+* сборка готовых модулей.
 
 > 💡 Таким образом, вся сложность остаётся контролируемой, сборка занимает незначительное время, а инновации не разрушают стабильность.
 
@@ -234,47 +247,60 @@
 
 ```yml
 # === ЯДРО ===
-фн:
-  имя: ОбработатьПакет
-  эффект:
-    - ядро
-  парам:
-    - СписокДок пакет
-  нач:
-    - ПроверитьЦелостность пакет
-    - если рез
-    - _ тогда Расшифровать пакет
-    - _ иначе Остановить "битый пакет"
+фн(
+  имя(ОбработатьПакет)
+  эффект(
+    ядро()
+  )
+  парам(
+    СписокДок(пакет)
+  )
+  нач(
+    ПроверитьЦелостность(пакет)
+    если(рез
+      тогда (
+        Расшифровать(пакет)
+        ..
+      )
+    Остановить("битый пакет")
+  )
+)
+
 
 # === РАСШИРЕНИЕ ===
-атом:
-  имя: ВебСервер
-  протон:
-    - ВебОбработчик маршрут
-    - СетьПорт порт
-
-прц:
-  имя: Пуск
-  нач:
-    - Печатать "Запуск сервера..."
+атом(
+  имя(ВебСервер)
+  протон(
+    ВебОбработчик(маршрут)
+    СетьПорт(порт)
+  )
+)
+
+
+прц(
+  имя(Пуск)
+  нач(
+    Печатать("Запуск сервера...")
+  )
+)
 ```
 
 Здесь:
 
-- `фн: ...` — ядро, стабильно,
-- `ВебСервер` — использование результатов творчества, может измениться,
-- `Печатать ...` — может быть переопределён под нужды среды, вместо реализации ядра
+* `фн(...)` — ядро, стабильно,
+* `ВебСервер` — использование результатов творчества, может измениться,
+* `Печатать(...)` — может быть переопределён под нужды среды, вместо реализации ядра
 
 ### Правила
 
-- Сущности ядра могут использовать сущности этапа разработки через спецификации;
-- Сущности ядра на этапе разработки изменять нельзя;
-- Сущности этапа разработки могут использовать сущности ядра.
+* Сущности ядра могут использовать сущности этапа разработки через спецификации;
+* Сущности ядра на этапе разработки изменять нельзя;
+* Сущности этапа разработки могут использовать сущности ядра.
 
 ## 🎯 Заключение: язык как диалектическая система
 
-- Форма ядра `%контекст: ...` — отражает устоявшееся, необходимое, объективное.
-- Форма расширения — `макро: ...)` — отражает возникающее, творческое, субъективное.
+* Форма ядра `%контекст(...)` — отражает устоявшееся, необходимое, объективное.
+* Форма расширения — `макро(...)` — отражает возникающее, творческое, субъективное.
 
 > ✅ Их борьба и единство — двигатель развития.
 
@@ -284,6 +310,6 @@
 
 > ✅ Это — не просто язык программирования, это — модель справедливого информационного общества:
 
-- стабильный базис,
-- свободное изменение по необходимости,
-- и путь от частного к общему через практику.
+* стабильный базис,
+* свободное изменение по необходимости,
+* и путь от частного к общему через практику.

+ 185 - 126
docs/docs/01_80.md

@@ -76,30 +76,40 @@
 
 Входы и выходы всегда требуется при обмене с внешним миром. Если приём данных из внешнего источника из экосистемы `prolet` -- тогда такой поток байтовых данных будет сопровождаться метками типа. В этой ситуации контроль на входе не нужен.
 
-```yml
+```python
 # Внутри — следует использовать байтовый поток, тип на выходе -- СписБайт
-прц:
-  имя: ВебЗапрос
-  эффект:
-    - вход
-    - ревью
-  вых:
-    - СрезБайт
-  нач:
-    - Веб запросить "/data"
+прц(
+  имя(ВебЗапрос)
+  эффект(
+    вход()
+    ревью()
+  )
+  вых(
+    СрезБайт(htp)
+  )
+  нач(
+    Веб(запросить "/data")
     # тип: фиксированный срез байтов
-    - <...>
+    <...>
+  )
+)
+
 
 # Обратный переход — только через проверку
-прц:
-  имя: Пуск
-  нач:
-   - ВебЗапрос
-   - уст ответ
-   - СрезБайт еслиОк ответ
-   - если рез
-   - _  тогда Пользователь изБайт ответ
-   - _  иначе ПечатьОшибка "неверный формат"
+прц(
+  имя(Пуск)
+  нач(
+    ВебЗапрос()
+    уст(ответ)
+    СрезБайт(еслиОк ответ)
+    если(рез
+      тогда(
+        Пользователь(изБайт ответ)
+        ..()
+      )
+    ПечатьОшибка("неверный формат")
+  )
+)
 ```
 
 Особенности входа:
@@ -130,20 +140,25 @@
 
 Он не может участвовать в вычислениях напрямую. Чтобы использовать — нужно привести к статическому обобщению.
 
-```yml
+```python
 # по умолчанию статичность на выходе фикс
 #   эффект с внешним миром -- вход
-прц:
-  имя: Пуск
-  нач:
-    - Api получитьИз
-    - уст x
-    - ВебЗапрос
-    - СписБайт еслиОк х
-    - если рез
-    - _ тогда Целое изБайт x,
-    - _     ОбработатьЧисло
-    - _ иначе ПечатьОшибка "ожидалось число"
+прц(
+  имя(Пуск)
+  нач(
+    Api(получитьИз)
+    уст(x)
+    ВебЗапрос()
+    СписБайт(еслиОк х)
+    если(рез
+      тогда(
+        Целое(изБайт x)
+        ОбработатьЧисло()
+        ..()
+      )
+    )
+    ПечатьОшибка("ожидалось число")
+  )
 )
 ```
 
@@ -164,19 +179,24 @@
 
 Проверка типа:
 
-- `если рез` Булево, безопасно
+- `если(рез ...)` Булево, безопасно
 - Безопасное извлечение типа
 
-```yml
-прц:
-  имя: Пуск
-  вых:
-    - РезПользователь
-  нач:
-    - если рез
-    - _ тогда Пользователь изБайт рез,
-    - _      Обработать
-    - .. рез
+```python
+прц(
+  имя(Пуск)
+  вых(
+    РезПользователь(рез)
+  )
+  нач(
+    если(рез
+      тогда(
+        Пользователь(изБайт рез)
+        Обработать()
+        ..(рез)
+      )
+    )
+  )
 )
 ```
 
@@ -186,18 +206,24 @@
 
 Схемная валидация для сложных форматов:
 
-```yml
-прц:
-  имя: Пуск
-  нач:
-    - ВебЗапрос
-    - уст ответ
-    - СписБайт еслиОк
-    - если рез
-    - _ тогда Пользователь изБайт ответ,
-    - _       уст х
-    - _ иначе Пользователь ошибка "Пуск:" рез .ошибка
-    - .. рез
+```python
+прц(
+  имя(Пуск)
+  нач(
+    ВебЗапрос()
+    уст(ответ)
+    СписБайт(еслиОк)
+    если(рез
+      тогда(
+        Пользователь(изБайт ответ)
+        уст(х)
+        ..(рез)
+      )
+    )
+    Пользователь(ошибка "Пуск: {рез(ошибка)}")
+    ..(рез)
+  )
+)
 ```
 
 Переход из динамики в статику — не автоматический, а требующий сознательного усилия, как переход от чувственного восприятия к рациональному пониманию.
@@ -214,43 +240,60 @@
 
 Когда динамический интерфейс стабилизируется, его можно возвысить до статического закона:
 
-```yml
+```python
 # Сначала — динамически,
 #  "ЗапросАпи" определён как эффект вход, и данные как фикс
-прц:
-  имя: ЗапросАпи
-  эффект:
-    - вход
-  вых:
-    - СписБайт
-  нач:
-    - <...>
+прц(
+  имя(ЗапросАпи)
+  эффект(
+    вход()
+  )
+  вых(
+    СписБайт(рез)
+  )
+  нач(
+    <...>
     # Прямое преобразование
     # Через месяц практики — выносим в структуру
-    - ФорматV1 изБайт
-    - <...>
+    ФорматV1(изБайт)
+    <...>
+  )
+)
+
 
 # Использование через приведение, результат определён как фикс
-прц:
-  имя: вБайты +эксп
-  парам:
-    - ФормаV1 форма
-  вых:
-    - СписБайт
-  нач:
-    - НакладнаяНазвание вБайт форма .поле1
-    - уст байтПоле1
-    - СписокЦелое вБайт форма .поле2
-    - СписБайт доб байтПоле1 рез
-    - .. рез
-
-атом:
-  имя: ФорматV1 +эксп
-  протон:
-    - НакладнаяНазвание поле1
-    - СписокЦелое поле2
-  нейтрон:
-    - вБайты +эксп
+прц(
+  имя(вБайты +эксп)
+  парам(
+    ФормаV1(форма)
+  )
+  вых(
+    СписБайт(рез)
+  )
+  нач(
+    НакладнаяНазвание(вБайт форма(поле1))
+    уст(байтПоле1)
+    СписокЦелое(вБайт форма(поле2))
+    СписБайт(доб байтПоле1 рез)
+    ..(рез)
+  )
+)
+
+
+атом(
+  имя(ФорматV1 +эксп)
+  протон(
+    имя(НакладнаяНазвание +изм)
+    тип(Стр)
+  )
+  протон(
+    имя(Сумма)
+    тип(СписокЦелое)
+  )
+  нейтрон(
+    имя(вБайты +эксп)
+  )
+)
 ```
 
 Это — отрицание отрицания: динамика отрицает статику, но на основе практического действия — порождает заново безопасную статику.
@@ -275,19 +318,24 @@
 
 Но если выход — в неструктурированный формат (например, `raw TCP`), то нужен обратный шлюз — эффект `выход`:
 
-```yml
-прц:
-  имя: Отправить
-  эффект:
+```python
+прц(
+  имя(Отправить)
+  эффект(
     # указание на вход вне экосистемы prolet
-    - выход +внеш
-  парам:
-    - Пользователь х
-  рез:
-    - СписБайт рез
-  нач:
-   - Пользователь вБайтыВнеш x
-   - .. рез
+    - выход(+внеш)
+  )
+  парам(
+    Пользователь(х)
+  )
+  рез(
+    СписБайт(рез)
+  )
+  нач(
+    Пользователь(вБайтыВнеш x)
+    ..(рез)
+  )
+)
 ```
 
 Это — единство и борьба: вход и выход — разные по природе, потому что мир в динамике асимметричен.
@@ -302,8 +350,8 @@
 
 Требуется явное приведение:
 
-- `Пользователь изБайтВнеш ответ` → с проверкой на возможную ошибку;
-- Или — `Пользователь изБайт ответ`, когда такая проверка не требуется.
+- `Пользователь(изБайтВнеш ответ)` → с проверкой на возможную ошибку;
+- Или — `Пользователь(изБайт ответ)`, когда такая проверка не требуется.
 
 Фиксируется событие:
 
@@ -330,35 +378,46 @@
 
 ## Пример: полный цикл перехода
 
-```yml
+```python
 # Внешний API — неизвестная структура
-прц:
-  имя: Пуск
-  эффект:
-    - вход +внеш
-  нач:
-    - Веб запросить "https://api.partner/data"
-    - уст ответ
+прц(
+  имя(Пуск)
+  эффект(
+    вход(+внеш)
+  )
+  нач(
+    Веб(запросить "https://api.partner/data")
+    уст(ответ)
+  )
+)
+
 
 # Проверка и переход к статике
-макро:
-  имя: ВебЗапрос
-  эффект:
-    - вход +внеш
-  нач:
-    - вставить """
-    + Веб запросить "https://api.partner/data" """
-    - Среда получ ЕслиОтладка
-    - если рез
-    - _ тогда вставить """
-    + уст ответ
-    + СписБайт еслиОк рез
-    + если рез
-    + _ тогда АнализДанных изБайт отчёт,
-    + _      уст отчёт
-    + _ иначе АнализДанных ошНов "ВебЗапрос: " отчёт .ошибка """
-    - _ иначе вставить """
-    + АнализДанных изБайтПринуд отчёт """
+макро(
+  имя(ВебЗапрос)
+  эффект(
+    вход(+внеш)
+  )
+  нач(
+    вставить(Веб запросить "https://api.partner/data")
+    Среда(получ ЕслиОтладка)
+    если(рез
+      тогда(
+        вставить("""
+          уст(ответ)
+          СписБайт(еслиОк рез)
+          если(рез
+            тогда(
+              АнализДанных(изБайт отчёт)
+              уст(отчёт)
+            )
+          АнализДанных(ошНов "ВебЗапрос: {отчёт(ошибка)}""")
+        )
+        ..()
+      )
+    вставить(АнализДанных(изБайтПринуд отчёт))
+  )
+)
 ```
 
 От хаоса внешнего мира → к порядку внутренней системы через безопасные однонаправленные шлюзы.

+ 17 - 0
docs/docs/10_10.md

@@ -0,0 +1,17 @@
+# Форматы файлов
+
+## *.plc
+
+Файл с исходным кодом программы.
+
+## *.pli
+
+Файл с кодом программы в формате **IL**
+
+## *.plb
+
+Файл с кодом программы в формате **BIN** (оптимизированный байт-код)
+
+## *.pl-lin.exe, *.pl-win.exe, *.pl-bsd.exe
+
+Исполянемый файл программы ля соответствующей **ОС**.

+ 2 - 0
docs/pro_readme.md

@@ -43,6 +43,8 @@
 * Атомы языка
 * ВМ
 * Система типов
+* pro.10_10 [Форматы файлов](./docs/10_10.md)
+
 
 ## Лицензия
 

+ 3 - 0
go.mod

@@ -0,0 +1,3 @@
+module plt
+
+go 1.27.0

+ 7 - 0
lev0/spec/ivm_prc.go

@@ -0,0 +1,7 @@
+package spec
+
+// IVmPrc -- процесс интерпретатора
+// type IVmPrc interface {
+// 	// Run -- запускает процесс интерпретатора
+// 	Run()
+// }

+ 2 - 0
lev0/spec/spec.go

@@ -0,0 +1,2 @@
+// package spec -- список спецификаций экосистемы
+package spec

+ 83 - 0
lev2/vm/pos/pos.go

@@ -0,0 +1,83 @@
+// package pos -- позиция в коде
+package pos
+
+import (
+	"fmt"
+	"log"
+)
+
+// IPos -- низменяемая позиция курсора
+type IPos interface {
+	String() string
+}
+
+// IPosMut -- низменяемая позиция курсора
+type IPosMut interface {
+	IPos
+	// GetX -- получить X
+	GetX() int
+	// IncX -- инкремент X
+	IncX()
+	// SetX -- установить X
+	SetX(x int)
+	// GetY -- получить Y
+	GetY() int
+	// IncY -- увеличить Y
+	IncY()
+	// NextLine -- перейти на новую строку
+	NextLine()
+}
+
+// Позиция в коде
+type pos struct {
+	x int // Строка
+	y int // Столбец
+}
+
+// NewPos -- возвращает новую позицию в коде
+func NewPos(x, y int) *pos {
+	return &pos{x, y}
+}
+
+var (
+	PosCur = NewPos(1, 1) // Позиция курсора в изоляте
+)
+
+// GetX -- получить X
+func (sf *pos) GetX() int {
+	return sf.x
+}
+
+// IncX -- инкремент X
+func (sf *pos) IncX() {
+	sf.x++
+}
+
+// SetX -- установить X
+func (sf *pos) SetX(x int) {
+	if x < 1 {
+		log.Panicf("pos,SetX(): x(%v)<1", x)
+	}
+	sf.x = x
+}
+
+// GetY -- получить Y
+func (sf *pos) GetY() int {
+	return sf.y
+}
+
+// IncY -- увеличить Y на 1
+func (sf *pos) IncY() {
+	sf.y++
+}
+
+// NextLine -- переход на следующую строку
+func (sf *pos) NextLine() {
+	sf.y++
+	sf.x = 1
+}
+
+// String -- возвращает строковое представление координаты в коде
+func (sf *pos) String() string {
+	return fmt.Sprintf("%d:%d", sf.y, sf.x)
+}

+ 20 - 0
lev2/vm/prc_base/prc_base.go

@@ -0,0 +1,20 @@
+// package prc_base -- базовый процесс для всех процессов
+package prc_base
+
+import "strings"
+
+// PrcBase -- базовый процесс для всех процессов
+type PrcBase struct {
+}
+
+// StripOut -- удаляет из строки все паразитные символы
+func (sf *PrcBase) StripOut(out string) string {
+	out = strings.TrimSuffix(out, "\t")
+	out = strings.TrimSuffix(out, " ")
+	out = strings.TrimPrefix(out, "\t")
+	out = strings.TrimPrefix(out, " ")
+	out = strings.ReplaceAll(out, "\t", " ")
+	out = strings.ReplaceAll(out, "\n", " ")
+	out = strings.ReplaceAll(out, "  ", " ")
+	return out
+}

+ 49 - 0
lev2/vm/prc_comment/prc_comment.go

@@ -0,0 +1,49 @@
+// package prc_comment -- процесс комментария
+package prc_comment
+
+import (
+	"fmt"
+	"log"
+	"plt/lev2/vm/pos"
+	"plt/lev2/vm/state_vm"
+	"strings"
+)
+
+// PrcComment -- процесс комментария
+type PrcComment struct {
+	strOut string
+}
+
+// NewPrcComment -- возвроащает новый процесс комментария
+func NewPrcComment() *PrcComment {
+	log.Println("NewPrcComment()")
+	sf := &PrcComment{}
+	sf.parse()
+	return sf
+}
+
+// Парсит инструкции в попытке извлечь комментарий
+func (sf *PrcComment) parse() {
+	vmState := state_vm.VM_State
+	posCur := pos.PosCur
+	posCur.IncX()
+	vmState.RuneInc()
+	beginPosY := posCur.GetY()
+	begPosX := posCur.GetX()
+	out := ""
+	for vmState.StrCur() != ")" {
+		if vmState.StrCur() == "\n" {
+			posCur.NextLine()
+		}
+		out += vmState.StrNext()
+		posCur.IncX()
+	}
+	vmState.RuneInc()
+	out = strings.ReplaceAll(out, "\n\n", "\n")
+	sf.strOut = fmt.Sprintf("%v:%v\t#(%v)", beginPosY, begPosX, out)
+}
+
+// Run -- запускает процесс (комментарий)
+func (sf *PrcComment) Run() {
+	fmt.Printf("%v\n", sf.strOut)
+}

+ 70 - 0
lev2/vm/prc_debug/prc_debug.go

@@ -0,0 +1,70 @@
+// package prc_debug -- процесс отладки
+package prc_debug
+
+import (
+	"fmt"
+	"log"
+	"strings"
+
+	"plt/lev2/vm/pos"
+	"plt/lev2/vm/state_vm"
+)
+
+// PrcDebug -- процесс для отладки
+type PrcDebug struct {
+	strOut string
+}
+
+// NewPrcDebug -- возвращает новый процесс для отладки
+func NewPrcDebug() *PrcDebug {
+	log.Println("NewPrcDebug()")
+	sf := &PrcDebug{}
+	sf.parse()
+	return sf
+}
+
+// Парсит инструкции ,вырезает действие
+func (sf *PrcDebug) parse() {
+	vmState := state_vm.VM_State
+	posCur := pos.PosCur
+	begPosX := 0
+	begPosY := pos.PosCur.GetY()
+	{ // Начать поиск выводимого значения
+		for vmState.StrCur() != "(" {
+			vmState.RuneInc()
+			if vmState.StrCur() == "\n" {
+				posCur.NextLine()
+			}
+			posCur.IncX()
+		}
+		// Сдвинуть позицию
+		vmState.RuneInc()
+		posCur.IncX()
+		begPosX = posCur.GetX()
+	}
+	{ // Выбрать значение отладки
+		out := ""
+		for vmState.StrCur() != ")" {
+			strCur := vmState.StrCur()
+			if strCur == "\n" {
+				posCur.NextLine()
+			}
+			out += vmState.StrNext()
+			posCur.IncX()
+			if vmState.IsEnd() {
+				break
+			}
+		}
+		vmState.RuneInc() // Сдвиг после скобки
+		out = strings.ReplaceAll(out, "\n\n", "\n")
+		// if out[len(out)-1] != '\n' {
+		// 	out += "\n"
+		// }
+		sf.strOut = fmt.Sprintf("%v:%v\td(%v)\n", begPosY, begPosX, out)
+	}
+}
+
+// Run -- запускает процесс (отладка)
+func (sf *PrcDebug) Run() {
+	fmt.Printf("%v", sf.strOut)
+}

+ 196 - 0
lev2/vm/prc_int/prc_int.go

@@ -0,0 +1,196 @@
+// package prc_int -- процесс над целочисленным кварком
+package prc_int
+
+import (
+	"fmt"
+	"log"
+	"strconv"
+	"strings"
+
+	"plt/lev2/vm/pos"
+	"plt/lev2/vm/prc_base"
+	"plt/lev2/vm/state_res"
+	"plt/lev2/vm/state_vm"
+)
+
+// PrcInt -- процесс над целочисленным значением
+type PrcInt struct {
+	prc_base.PrcBase
+	strOut string
+	Run    func() // Run -- запускает процесс (над целым числом)
+}
+
+var (
+	// DictRun -- словарь переменных времени исполнения
+	DictRun = map[string]int{}
+	// DictCompile -- словарь имён времени компиляции
+	DictCompile = map[string]bool{}
+	vmState     = state_vm.VM_State
+	posCur      = pos.PosCur
+)
+
+// NewPrcInt -- возвращает новый процесс над целочисленным значением
+func NewPrcInt() *PrcInt {
+	log.Println("NewPrcInt()")
+	sf := &PrcInt{}
+	sf.parse()
+	return sf
+}
+
+// Парсит инструкции, вырезает действие
+func (sf *PrcInt) parse() {
+	begPosX := 0
+	begPosY := 0
+	{ // Начать поиск выводимого значения
+		for vmState.StrCur() != "(" {
+			vmState.RuneInc()
+			if vmState.StrCur() == "\n" {
+				posCur.NextLine()
+			}
+			posCur.IncX()
+			begPosY = posCur.GetY()
+		}
+		// Сдвинуть позицию
+		vmState.RuneInc()
+		posCur.IncX()
+		begPosX = posCur.GetX()
+	}
+	out := ""
+	{ // Выбрать значение отладки
+		for vmState.StrCur() != ")" {
+			strCur := vmState.StrCur()
+			if strCur == "\n" {
+				posCur.NextLine()
+			}
+			out += vmState.StrNext()
+			posCur.IncX()
+			if vmState.IsEnd() {
+				break
+			}
+		}
+		vmState.RuneInc() // Сдвиг после скобки
+		out = strings.ReplaceAll(out, "\n\n", "\n")
+		sf.strOut = fmt.Sprintf("%v:%v\t%v", begPosY, begPosX, out)
+	}
+	{ // Теперь надо выяснить операцю
+		out = sf.StripOut(out)
+		lstOut := strings.Split(out, " ")
+		lenLst := len(lstOut)
+		switch lenLst {
+		case 3:
+			cmd := lstOut[0]
+			switch cmd {
+			case "New": // готовит инструкцию создания новой целочисленной переменной
+				sf.compileNew(begPosY, begPosX, lstOut)
+			case "+": // Сложение
+				sf.compileAdd(begPosY, begPosX, lstOut)
+			default:
+				panic("PrcInt(): unknown command for case=3")
+			}
+		case 2:
+			cmd := lstOut[0]
+			switch cmd {
+			case "++":
+				sf.compileInc(begPosY, begPosX, lstOut)
+			case "--":
+				sf.compileDec(begPosY, begPosX, lstOut)
+			default:
+				panic("PrcInt(): unknown command for case=2")
+			}
+		}
+	}
+}
+
+// Декремент значения
+func (sf *PrcInt) compileDec(x, y int, lstOut []string) {
+	name := lstOut[1]
+	sf.Run = func() {
+		val := DictRun[name]
+		val--
+		DictRun[name] = val
+		fmt.Printf("%v:%v\ti(-- %v)\t#(val=%v)\n", x, y, name, val)
+	}
+}
+
+// Инкремент значения
+func (sf *PrcInt) compileInc(x, y int, lstOut []string) {
+	name := lstOut[1]
+	sf.Run = func() {
+		val := DictRun[name]
+		val++
+		DictRun[name] = val
+		fmt.Printf("%v:%v\ti(++ %v)\t#(val=%v)\n", x, y, name, val)
+	}
+}
+
+// Складывает два числа
+func (sf *PrcInt) compileAdd(x, y int, lstOut []string) {
+	var err error
+	name1 := lstOut[1]
+	var val1, val2 int
+	isOkName1 := DictCompile[name1]
+	if !isOkName1 {
+		val1, err = strconv.Atoi(name1)
+		if err != nil {
+			err := fmt.Errorf("PrcInt.compileAdd(): in extract op1(%v), err=\n\t%w",
+				name1, err)
+			panic(err)
+		}
+	}
+
+	name2 := lstOut[2]
+	isOkName2 := DictCompile[name2]
+	if !isOkName2 {
+		val2, err = strconv.Atoi(name2)
+		if err != nil {
+			err := fmt.Errorf("PrcInt.cmdAdd(): in extract new val(%v), err=\n\t%w",
+				name2, err)
+			panic(err)
+		}
+	}
+	switch {
+	case isOkName1 && isOkName2:
+		sf.Run = func() {
+			res := val1 + val2
+			vmState.ResRun().Set(state_res.ResTypeInt, res)
+			fmt.Printf("%v:%v\ti(+ %v %v)\t#(val=%v)\n", x, y, name1, name2, res)
+		}
+	case isOkName1 && !isOkName2:
+		sf.Run = func() {
+			val1 := DictRun[name1]
+			res := val1 + val2
+			vmState.ResRun().Set(state_res.ResTypeInt, res)
+			fmt.Printf("%v:%v\ti(+ %v %v)\t#(val=%v)\n", x, y, name1, val2, res)
+		}
+	case !isOkName1 && isOkName2:
+		sf.Run = func() {
+			val2 := DictRun[name2]
+			res := val1 + val2
+			vmState.ResRun().Set(state_res.ResTypeInt, res)
+			fmt.Printf("%v:%v\ti(+ %v %v)\t#(val=%v)\n", x, y, val1, name2, res)
+		}
+	case !isOkName1 && !isOkName2:
+		sf.Run = func() {
+			res := val1 + val2
+			vmState.ResRun().Set(state_res.ResTypeInt, res)
+			fmt.Printf("%v:%v\ti(+ %v %v)\t#(val=%v)\n", x, y, val1, val2, res)
+		}
+	}
+}
+
+// Создаёт новую целочисленную переменную
+func (sf *PrcInt) compileNew(x, y int, lstOut []string) {
+	name := lstOut[1]
+	strVal := lstOut[2]
+	val, err := strconv.Atoi(strVal)
+	if err != nil {
+		err := fmt.Errorf("PrcInt.compileNew(): in extract new val(%v), err=\n\t%w",
+			strVal, err)
+		panic(err)
+	}
+	DictCompile[name] = true
+	sf.Run = func() {
+		DictRun[name] = val
+		fmt.Printf("%v:%v\ti(New %v %v)\n", x, y, name, val)
+	}
+}

+ 119 - 0
lev2/vm/prc_res/prc_res.go

@@ -0,0 +1,119 @@
+// package prc_res -- обработка результата
+package prc_res
+
+import (
+	"fmt"
+	"log"
+	"strconv"
+	"strings"
+
+	"plt/lev2/vm/pos"
+	"plt/lev2/vm/prc_base"
+	"plt/lev2/vm/prc_int"
+	"plt/lev2/vm/state_res"
+	"plt/lev2/vm/state_vm"
+)
+
+// PrcRes -- обработка результата
+type PrcRes struct {
+	prc_base.PrcBase
+	Run func() // Функция процесса инструкций ВМ
+}
+
+var (
+	vmState = state_vm.VM_State
+	posCur  = pos.PosCur
+)
+
+// NewPrcRes -- возвращает новый обработчик результата
+func NewPrcRes() *PrcRes {
+	log.Println("NewPrcRes()")
+	sf := &PrcRes{}
+	sf.parse()
+	return sf
+}
+
+// Парсит строку исходного кода
+func (sf *PrcRes) parse() {
+	begPosX := 0
+	begPosY := 0
+	{ // Начать поиск присвоения
+		for vmState.StrCur() != "(" {
+			vmState.RuneInc()
+			if vmState.StrCur() == "\n" {
+				posCur.NextLine()
+			}
+			posCur.IncX()
+			begPosY = posCur.GetY()
+		}
+		// Сдвинуть позицию
+		vmState.RuneInc()
+		posCur.IncX()
+		begPosX = posCur.GetX()
+	}
+	out := ""
+	{ // Выбрать значение отладки
+		for vmState.StrCur() != ")" {
+			strCur := vmState.StrCur()
+			if strCur == "\n" {
+				posCur.NextLine()
+			}
+			out += vmState.StrNext()
+			posCur.IncX()
+			if vmState.IsEnd() {
+				break
+			}
+		}
+		vmState.RuneInc() // Сдвиг после скобки
+		out = strings.ReplaceAll(out, "\n\n", "")
+	}
+	{ // Теперь надо выяснить операцию
+		out = sf.StripOut(out)
+		resTypeCompile := vmState.ResCompile().Type()
+		switch resTypeCompile {
+		case state_res.ResTypeInt:
+			sf.compileInt(begPosY, begPosX, out)
+		default:
+			err := fmt.Errorf("PrcRes.parse():Неизвестный тип результата, type=%q", resTypeCompile)
+			panic(err)
+		}
+	}
+}
+
+// Готовит инструкцию присвоения целочисленного значения
+func (sf *PrcRes) compileInt(x, y int, op1 string) {
+	// Проверить на наличие имени
+	_, isOk := prc_int.DictCompile[op1]
+	{ // Если это значение
+		if !isOk { // Проверяем на число
+			val, err := strconv.Atoi(op1)
+			if err != nil {
+				err := fmt.Errorf("PrcRes.compileInt(): op=%s, err=\n\t%w", op1, err)
+				panic(err)
+			}
+			sf.Run = func() {
+				resType := vmState.ResRun().Type()
+				if resType != state_res.ResTypeInt {
+					err := fmt.Errorf("PrcRes.compileInt(): for val(%v), resType=%v, not int", val, resType)
+					panic(err)
+				}
+				vmState.ResRun().Set(state_res.ResTypeInt, val)
+				fmt.Printf("%v:%v\tr(%v)\t#(val=%v)\n", x, y, val, val)
+			}
+			return
+		}
+	}
+	{ // Если это имя
+		sf.Run = func() {
+			resType := vmState.ResRun().Type()
+			if resType != state_res.ResTypeInt {
+				err := fmt.Errorf("PrcRes.compileInt(): for name(%v),  resType=%v, not int", op1, resType)
+				panic(err)
+			}
+			val := prc_int.DictRun[op1]
+			val = vmState.ResRun().Get().(int)
+			prc_int.DictRun[op1] = val
+			fmt.Printf("%v:%v\tr(%v)\t#(val=%v)\n", x, y, op1, val)
+		}
+	}
+}

+ 46 - 0
lev2/vm/state_res/state_res.go

@@ -0,0 +1,46 @@
+// package state_res -- состояние результата
+package state_res
+
+// AResType -- тип результата
+type AResType string
+
+const (
+	ResTypeInt = AResType("int")
+)
+
+var (
+	// DictType -- список допустимыз типов
+	DictType = map[AResType]bool{
+		ResTypeInt: true,
+	}
+)
+
+// StateRes -- состояние результата
+type StateRes struct {
+	resType AResType // Тип результата
+	res     any      // Результат последней операции по int
+}
+
+// NewStateRes -- возвращает новый объект результата
+func NewStateRes() *StateRes {
+	return &StateRes{
+		resType: ResTypeInt,
+		res:     0,
+	}
+}
+
+// Type -- возвращает тип результата
+func (sf *StateRes) Type() AResType {
+	return sf.resType
+}
+
+// Set -- установка результата
+func (sf *StateRes) Set(resType AResType, res any) {
+	sf.resType = ResTypeInt
+	sf.res = res
+}
+
+// Get -- возвращает результат
+func (sf *StateRes) Get() any {
+	return sf.res
+}

+ 79 - 0
lev2/vm/state_vm/state_vm.go

@@ -0,0 +1,79 @@
+// package state_vm -- статус ВМ
+package state_vm
+
+import (
+	"plt/lev2/vm/state_res"
+	"strings"
+)
+
+// StateVm -- статус ВМ
+type StateVm struct {
+	codeStr  string              // Инструкци ив строке
+	codeRune []rune              // Инструкции в рунах
+	indRune  int                 // Указатель на текущую руну в промежуточном языке
+	resComp  *state_res.StateRes // Результат при компиляции
+	resRun   *state_res.StateRes // Результат при исполнении
+
+}
+
+var (
+	VM_State = &StateVm{
+		resComp: state_res.NewStateRes(),
+		resRun:  state_res.NewStateRes(),
+	}
+)
+
+// ResCompile -- результат при компиляции
+func (sf *StateVm) ResCompile() *state_res.StateRes {
+	return sf.resComp
+}
+
+// ResRun -- результат при исполнении
+func (sf *StateVm) ResRun() *state_res.StateRes {
+	return sf.resRun
+}
+
+// CodeStrSet -- одноразовое внедрение кода
+func (sf *StateVm) CodeStrSet(codeStr string) {
+	sf.codeStr = codeStr
+	sf.codeRune = []rune(sf.codeStr)
+}
+
+// RuneInc -- инкремент индекса текущей руны
+func (sf *StateVm) RuneInc() {
+	sf.indRune++
+}
+
+// IndRune -- текущий индекс
+func (sf *StateVm) IndRune() int {
+	return sf.indRune
+}
+
+// StrCur - литера по текущемй индексу
+func (sf *StateVm) StrCur() string {
+	return string(sf.codeRune[sf.indRune])
+}
+
+// StrNext -- возвращает следующую литеру
+func (sf *StateVm) StrNext() string {
+	defer func() {
+		sf.indRune++
+	}()
+	runeNext := sf.codeRune[sf.indRune]
+	return string(runeNext)
+}
+
+// RuneLen -- количество рун
+func (sf *StateVm) RuneLen() int {
+	return len(sf.codeRune)
+}
+
+// IsEnd -- проверка на конец рун
+func (sf *StateVm) IsEnd() bool {
+	return sf.indRune >= len(sf.codeRune)-1
+}
+
+// LstLast -- возвращает последню часть инструкций
+func (sf *StateVm) LstLast(lit string) []string {
+	return strings.Split(string(sf.codeRune[sf.indRune:]), lit)
+}

+ 87 - 0
lev2/vm/vm.go

@@ -0,0 +1,87 @@
+// package vm -- интерпретатор промежуточного языка
+package vm
+
+import (
+	"fmt"
+	"log"
+	"os"
+
+	// "plt/lev0/spec"
+	"plt/lev2/vm/pos"
+	"plt/lev2/vm/prc_comment"
+	"plt/lev2/vm/prc_debug"
+	"plt/lev2/vm/prc_int"
+	"plt/lev2/vm/prc_res"
+	"plt/lev2/vm/state_vm"
+)
+
+// Vm -- интерпретатор промежуточного языка
+type Vm struct {
+	lstPrc []func() // Функция процесса инструкций ВМ
+}
+
+// NewVm -- возвращает новый интерпретатор промежуточного языка
+func NewVm() *Vm {
+	log.Println("NewVm()")
+	path := os.Getenv("MAIN_PROLET")
+	if path == "" {
+		path = "./main.pli"
+	}
+	log.Printf("NewVm(): path=%q", path)
+	// path := "main.pli"
+	// path := "main.pl
+	binCode, err := os.ReadFile(path)
+	if err != nil {
+		log.Panicf("NewVM(): in read path, path=%q, err=\n\t%v", path, err)
+	}
+	sf := &Vm{
+		lstPrc: []func(){},
+	}
+	vmState := state_vm.VM_State // Статус ВМ
+	vmState.CodeStrSet(string(binCode))
+	sf.parse() // парсинг кода, заполнение структуры s
+	return sf
+}
+
+// Парсит код на промежуточном языке
+func (sf *Vm) parse() {
+	vmState := state_vm.VM_State // Статус ВМ
+	log.Printf("Vm.parse(): len=%v,\n", vmState.RuneLen())
+	posCur := pos.PosCur // Текущая позиция в коде
+	fmt.Println("")
+	for vmState.RuneLen() > vmState.IndRune() {
+		r := vmState.StrCur()
+		// fmt.Printf("%v", string(r))
+		switch r {
+		case "#": // Поиск коммента
+			vmState.RuneInc()
+			prcComment := prc_comment.NewPrcComment()
+			sf.lstPrc = append(sf.lstPrc, prcComment.Run)
+		case "d": // Поиск отладки
+			prcDebug := prc_debug.NewPrcDebug()
+			sf.lstPrc = append(sf.lstPrc, prcDebug.Run)
+		case "i": // Поиск операции с целым числым
+			prcInt := prc_int.NewPrcInt()
+			sf.lstPrc = append(sf.lstPrc, prcInt.Run)
+		case "r": // Установка результата
+			prcRes := prc_res.NewPrcRes()
+			sf.lstPrc = append(sf.lstPrc, prcRes.Run)
+		case "\n": // Поиск перевода строки
+			posCur.NextLine()
+			vmState.RuneInc()
+		default: // Дефолтное действие
+			fmt.Print(string(r))
+			vmState.RuneInc()
+		}
+	}
+	fmt.Printf("\n%v PARSE END\n", posCur)
+}
+
+// Run -- запускает интерпретатор промежуточного языка
+func (sf *Vm) Run() {
+	log.Println("Vm.Run()")
+	for _, fnRun := range sf.lstPrc {
+		fnRun()
+	}
+	fmt.Println("")
+}

+ 0 - 0
plt/main.plt → plt/main.plc


+ 33 - 0
plt/main.pli

@@ -0,0 +1,33 @@
+#(Код на промежуточном языке для prolet
+	отступы с табуляцией будут выводиться как
+	есть. Весь текст в скобках -- это один
+	комментарий. Пустые строки
+
+	игнорируются)
+
+d(Программа запущена)
+
+d(А тут
+
+	вывод
+
+	в несколько
+
+	строк. Потому что
+	мы это можем
+)
+
+i(New
+	ябл 23)
+
+i(++ ябл)
+i(++ ябл)
+i(-- ябл)
+#(Далее операции без присвоения)
+i(+ ябл 10)
+i(+ 20 ябл)
+i(+ 45 10)
+#(Установить результат как значение яблока,
+	если не имя, то устанавливается результат)
+r(ябл)
+r(-10)