// 2025-2026 Богданович Давид Когут Прихожденко (кдб.дійсність.укр)

взяти означення мавка/пристрій;

простір мавка {
  простір пристрій {
    внутрішня дія машина_виділити_сиру_памʼять(
      М: адреса<Машина>,
      розмір: природне
    ) -> адреса<п8> {
      вернути пристрій_мавки_виділити_сиру_памʼять(розмір);
    }

    внутрішня дія машина_перевиділити_сиру_памʼять(
      М: адреса<Машина>,
      значення: адреса<п8>,
      новий_розмір: природне
    ) -> адреса<п8> {
      вернути пристрій_мавки_перевиділити_сиру_памʼять(значення, новий_розмір);
    }

    внутрішня дія машина_звільнити_сиру_памʼять(
      М: адреса<Машина>,
      значення: адреса<п8>
    ) {
      пристрій_мавки_звільнити_сиру_памʼять(значення);
    }

    внутрішня дія машина_запанікувати(
      М: адреса<Машина>,
      повідомлення: кд
    ) {
      надрукувати_кд(М, повідомлення);

      пристрій_мавки_вийти(1);
    }

    внутрішня дія машина_вивести_кд(
      М: адреса<Машина>,
      значення: кд
    ) {
      пристрій_мавки_вивести_кд(значення.розмір, значення.дані);
    }

    внутрішня дія машина_надрукувати(
      М: адреса<Машина>,
      значення: кд
    ) {
      пристрій_мавки_надрукувати_кд(значення.розмір, значення.дані);
    }

    внутрішня дія машина_перетворити_п64_в_кд(
      М: адреса<Машина>,
      значення: п64,
      вихід_текстового_значення: адреса<кд>
    ) -> логічне {
      змінна значення_кд: кд;

      якщо пристрій_мавки_перетворити_п64_в_кд(значення, значення_кд.розмір::адреса, значення_кд.дані::адреса) {
        вихід_текстового_значення.розмір = значення_кд.розмір;
        вихід_текстового_значення.дані = значення_кд.дані;

        вернути так;
      }

      вернути ні;
    }

    внутрішня дія машина_перетворити_ц64_в_кд(
      М: адреса<Машина>,
      значення: ц64,
      вихід_текстового_значення: адреса<кд>
    ) -> логічне {
      змінна значення_кд: кд;

      якщо пристрій_мавки_перетворити_ц64_в_кд(значення, значення_кд.розмір::адреса, значення_кд.дані::адреса) {
        вихід_текстового_значення.розмір = значення_кд.розмір;
        вихід_текстового_значення.дані = значення_кд.дані;

        вернути так;
      }

      вернути ні;
    }

    внутрішня дія машина_перетворити_р64_в_кд(
      М: адреса<Машина>,
      значення: р64,
      вихід_текстового_значення: адреса<кд>
    ) -> логічне {
      змінна значення_кд: кд;
      змінна розмір_експоненти: ціле = 0;

      якщо пристрій_мавки_перетворити_р64_в_кд(значення, значення_кд.розмір::адреса, значення_кд.дані::адреса, розмір_експоненти::адреса) {
        якщо розмір_експоненти == 0 {
          вихід_текстового_значення.розмір = значення_кд.розмір;
          вихід_текстового_значення.дані = значення_кд.дані;

          вернути так;
        }

        змінна накопичувач_тексту = зробити_накопичувач_тексту(М, значення_кд.розмір + 10);
        покласти_в_накопичувач_тексту(М, накопичувач_тексту::адреса, значення_кд);

        змінна значення_експоненти_кд: кд;

        якщо пристрій_мавки_перетворити_ц64_в_кд(розмір_експоненти, значення_експоненти_кд.розмір::адреса, значення_експоненти_кд.дані::адреса) {
          покласти_в_накопичувач_тексту(М, накопичувач_тексту::адреса, "е");

          якщо розмір_експоненти > 0 {
            покласти_в_накопичувач_тексту(М, накопичувач_тексту::адреса, "+");
          }

          покласти_в_накопичувач_тексту(М, накопичувач_тексту::адреса, значення_експоненти_кд);

          звільнити(М, значення_експоненти_кд.дані);
          звільнити(М, значення_кд.дані);

          вихід_текстового_значення.розмір = накопичувач_тексту.розмір;
          вихід_текстового_значення.дані = накопичувач_тексту.дані;

          вернути так;
        }

        звільнити(М, накопичувач_тексту.дані);
        звільнити(М, значення_кд.дані);

        вернути так;
      }

      вернути ні;
    }

    внутрішня дія машина_піднести_до_степеня_п64(
      М: адреса<Машина>,
      значення: п64,
      степінь: п64
    ) -> п64 {
      вернути пристрій_мавки_піднести_до_степеня_п64(значення, степінь);
    }

    внутрішня дія машина_піднести_до_степеня_ц64(
      М: адреса<Машина>,
      значення: ц64,
      степінь: ц64
    ) -> ц64 {
      вернути пристрій_мавки_піднести_до_степеня_ц64(значення, степінь);
    }

    внутрішня дія машина_піднести_до_степеня_р64(
      М: адреса<Машина>,
      значення: р64,
      степінь: р64
    ) -> р64 {
      вернути пристрій_мавки_піднести_до_степеня_р64(значення, степінь);
    }

    внутрішня дія машина_взяти_модуль(
      М: адреса<Машина>,
      шлях_до_теки_модулів: адреса<ПредметДаних>,
      відносно: логічне,
      довжина_шляху: природне,
      шлях: адреса<адреса<ПредметТексту>>,
      місцезнаходження: Місцезнаходження
    ) -> ЗначенняАбоСтанПадіння {
      змінна успіх: логічне = ні;
      змінна кдпм = М.користувацькі_дані_пристрою.значення як адреса<КористувацькіДаніПристроюМавки>;
      змінна шлях_до_кореневої_теки_модулів = кдпм.шлях_до_теки_модулів.предмет як адреса<ПредметДаних>;
      змінна шлях_до_теки_паків = кдпм.шлях_до_теки_паків.предмет як адреса<ПредметДаних>;
      змінна предмет_шляху: адреса<ПредметДаних> = пусто;
      змінна розмір_елементів_збиття: природне = довжина_шляху + 1;
      змінна елементи_збиття = виділити<ЕлементШляхуПристроюМавки>(М, розмір_елементів_збиття);
      змінна позиція_елементів_збиття: природне = 0;
      змінна п: природне = 0;
      змінна значення_ю8: ю8 = ю8 { 0, пусто };
      змінна позиція_помилки: природне = 0;
      змінна розмір_збитого_шляху: природне = 0;
      змінна дані_збитого_шляху: адреса<п8> = пусто;
      змінна треба_звільнити_перший_елемент: логічне = ні;

      якщо відносно {
        елементи_збиття[позиція_елементів_збиття] = ЕлементШляхуПристроюМавки {
          шлях_до_теки_модулів.розмір,
          шлях_до_теки_модулів.дані
        };

        треба_звільнити_перший_елемент = ні;

        позиція_елементів_збиття += 1;
      } інакше {
        успіх = пристрій_мавки_перевірити_чи_шлях_починається_на(
          шлях_до_теки_модулів.розмір,
          шлях_до_теки_модулів.дані,
          шлях_до_теки_паків.розмір,
          шлях_до_теки_паків.дані
        );

        якщо успіх {
          успіх = пристрій_мавки_отримати_шлях_до_паку_з_шляху_теки_модулів(
            шлях_до_теки_модулів.розмір,
            шлях_до_теки_модулів.дані,
            шлях_до_теки_паків.розмір,
            шлях_до_теки_паків.дані,
            елементи_збиття[позиція_елементів_збиття].розмір::адреса,
            елементи_збиття[позиція_елементів_збиття].дані::адреса
          );

          якщо не успіх {
            звільнити(М, елементи_збиття);
            звільнити(М, шлях);

            вернути МІСЦЕПАДІННЯ(М, створити_текст(М, "Не вдалося отримати шлях до паку з шляху модуля."), місцезнаходження);
          }
        } інакше {
          елементи_збиття[позиція_елементів_збиття] = ЕлементШляхуПристроюМавки {
            шлях_до_кореневої_теки_модулів.розмір,
            шлях_до_кореневої_теки_модулів.дані
          };
        }

        позиція_елементів_збиття += 1;
      }

      поки п < довжина_шляху {
        успіх = пристрій_мавки_перекодувати_кд_в_ю8(
          шлях[п].значення.розмір,
          шлях[п].значення.дані,
          значення_ю8.розмір::адреса,
          значення_ю8.дані::адреса,
          позиція_помилки::адреса
        );

        якщо не успіх {
          якщо треба_звільнити_перший_елемент {
            п = 0;
          } інакше {
            п = 1;
          }
          поки п < позиція_елементів_збиття {
            звільнити(М, елементи_збиття[п].дані);

            п += 1;
          }
          звільнити(М, елементи_збиття);
          звільнити(М, шлях);

          вернути МІСЦЕПАДІННЯ(М, створити_текст(М, "Не вдалося перекодувати елемент шляху модуля в ю8."), місцезнаходження);
        }

        елементи_збиття[позиція_елементів_збиття] = ЕлементШляхуПристроюМавки {
          значення_ю8.розмір,
          значення_ю8.дані
        };

        позиція_елементів_збиття += 1;

        п += 1;
      }

      успіх = пристрій_мавки_збити_шлях_до_модуля(
        розмір_елементів_збиття,
        елементи_збиття,
        розмір_збитого_шляху::адреса,
        дані_збитого_шляху::адреса
      );

      якщо не успіх {
        якщо треба_звільнити_перший_елемент {
          п = 0;
        } інакше {
          п = 1;
        }
        поки п < розмір_елементів_збиття {
          звільнити(М, елементи_збиття[п].дані);

          п += 1;
        }
        звільнити(М, елементи_збиття);
        звільнити(М, шлях);

        вернути МІСЦЕПАДІННЯ(М, створити_текст(М, "Не вдалося збити шлях до модуля."), місцезнаходження);
      }

      предмет_шляху = створити_дані(
        М,
        розмір_збитого_шляху,
        дані_збитого_шляху
      );

      якщо треба_звільнити_перший_елемент {
        п = 0;
      } інакше {
        п = 1;
      }
      поки п < розмір_елементів_збиття {
        звільнити(М, елементи_збиття[п].дані);

        п += 1;
      }
      звільнити(М, елементи_збиття);

      змінна результат = взяти_файл(
        М,
        предмет_шляху,
        шлях[довжина_шляху - 1],
        місцезнаходження
      );

      звільнити(М, шлях);

      вернути результат;
    }

    внутрішня дія машина_взяти_пак(
      М: адреса<Машина>,
      довжина_шляху: природне,
      шлях: адреса<адреса<ПредметТексту>>,
      місцезнаходження: Місцезнаходження
    ) -> ЗначенняАбоСтанПадіння {
      змінна успіх: логічне = ні;
      змінна кдпм = М.користувацькі_дані_пристрою.значення як адреса<КористувацькіДаніПристроюМавки>;
      змінна шлях_до_теки_паків = кдпм.шлях_до_теки_паків.предмет як адреса<ПредметДаних>;
      змінна предмет_шляху: адреса<ПредметДаних> = пусто;
      змінна розмір_елементів_збиття: природне = довжина_шляху + 1;
      якщо довжина_шляху == 1 {
        розмір_елементів_збиття += 1;
      }
      змінна елементи_збиття = виділити<ЕлементШляхуПристроюМавки>(М, розмір_елементів_збиття);
      змінна позиція_елементів_збиття: природне = 0;
      змінна п: природне = 0;
      змінна значення_ю8: ю8 = ю8 { 0, пусто };
      змінна позиція_помилки: природне = 0;
      змінна розмір_збитого_шляху: природне = 0;
      змінна дані_збитого_шляху: адреса<п8> = пусто;

      елементи_збиття[позиція_елементів_збиття] = ЕлементШляхуПристроюМавки {
        шлях_до_теки_паків.розмір,
        шлях_до_теки_паків.дані
      };

      позиція_елементів_збиття += 1;

      якщо довжина_шляху == 1 {
        успіх = пристрій_мавки_перекодувати_кд_в_ю8(
          шлях[п].значення.розмір,
          шлях[п].значення.дані,
          значення_ю8.розмір::адреса,
          значення_ю8.дані::адреса,
          позиція_помилки::адреса
        );

        якщо не успіх {
          п = 1;
          поки п < позиція_елементів_збиття {
            звільнити(М, елементи_збиття[п].дані);

            п += 1;
          }
          звільнити(М, елементи_збиття);
          звільнити(М, шлях);

          вернути МІСЦЕПАДІННЯ(М, створити_текст(М, "Не вдалося перекодувати елемент шляху модуля в ю8."), місцезнаходження);
        }

        елементи_збиття[позиція_елементів_збиття] = ЕлементШляхуПристроюМавки {
          значення_ю8.розмір,
          значення_ю8.дані
        };

        позиція_елементів_збиття += 1;
      }

      поки п < довжина_шляху {
        успіх = пристрій_мавки_перекодувати_кд_в_ю8(
          шлях[п].значення.розмір,
          шлях[п].значення.дані,
          значення_ю8.розмір::адреса,
          значення_ю8.дані::адреса,
          позиція_помилки::адреса
        );

        якщо не успіх {
          п = 1;
          поки п < позиція_елементів_збиття {
            звільнити(М, елементи_збиття[п].дані);

            п += 1;
          }
          звільнити(М, елементи_збиття);
          звільнити(М, шлях);

          вернути МІСЦЕПАДІННЯ(М, створити_текст(М, "Не вдалося перекодувати елемент шляху модуля в ю8."), місцезнаходження);
        }

        елементи_збиття[позиція_елементів_збиття] = ЕлементШляхуПристроюМавки {
          значення_ю8.розмір,
          значення_ю8.дані
        };

        позиція_елементів_збиття += 1;

        п += 1;
      }

      успіх = пристрій_мавки_збити_шлях_до_модуля(
        розмір_елементів_збиття,
        елементи_збиття,
        розмір_збитого_шляху::адреса,
        дані_збитого_шляху::адреса
      );

      якщо не успіх {
        п = 1;
        поки п < розмір_елементів_збиття {
          звільнити(М, елементи_збиття[п].дані);

          п += 1;
        }
        звільнити(М, елементи_збиття);
        звільнити(М, шлях);

        вернути МІСЦЕПАДІННЯ(М, створити_текст(М, "Не вдалося збити шлях до модуля."), місцезнаходження);
      }

      предмет_шляху = створити_дані(
        М,
        розмір_збитого_шляху,
        дані_збитого_шляху
      );

      п = 1;
      поки п < розмір_елементів_збиття {
        звільнити(М, елементи_збиття[п].дані);

        п += 1;
      }
      звільнити(М, елементи_збиття);

      змінна результат = взяти_файл(
        М,
        предмет_шляху,
        шлях[довжина_шляху - 1],
        місцезнаходження
      );

      звільнити(М, шлях);

      вернути результат;
    }

    внутрішня дія дія_перед_знищенням_користувацьких_даних_пристрою_мавки(
      М: адреса<Машина>,
      користувацькі_дані: адреса<КористувацькіДані>
    ) {
      змінна кдпм = користувацькі_дані.значення як адреса<КористувацькіДаніПристроюМавки>;

      // потім: відпустити шляхи і звільнити кдпм
    }

    дія створити_машину() -> адреса<Машина> {
      змінна М = пристрій_мавки_виділити_сиру_памʼять(Машина.розмір) як адреса<Машина>;

      налаштувати_машину(М, Налаштування {
        виділити_сиру_памʼять = машина_виділити_сиру_памʼять,
        перевиділити_сиру_памʼять = машина_перевиділити_сиру_памʼять,
        звільнити_сиру_памʼять = машина_звільнити_сиру_памʼять,
        запанікувати = машина_запанікувати,
        вивести_кд = машина_вивести_кд,
        перетворити_п64_в_кд = машина_перетворити_п64_в_кд,
        перетворити_ц64_в_кд = машина_перетворити_ц64_в_кд,
        перетворити_р64_в_кд = машина_перетворити_р64_в_кд,
        піднести_до_степеня_п64 = машина_піднести_до_степеня_п64,
        піднести_до_степеня_ц64 = машина_піднести_до_степеня_ц64,
        піднести_до_степеня_р64 = машина_піднести_до_степеня_р64,
        взяти_модуль = машина_взяти_модуль,
        взяти_пак = машина_взяти_пак,
        взяти_біб = пусто,
      });

      змінна кдпм = виділити<КористувацькіДаніПристроюМавки>(М, 1);
      кдпм.шлях_до_теки_модулів = пусто;
      кдпм.шлях_до_теки_паків = пусто;

      М.користувацькі_дані_пристрою = створити_користувацькі_дані(
        М,
        кдпм,
        дія_перед_знищенням_користувацьких_даних_пристрою_мавки
      );

      вернути М;
    }

    дія розібрати_шлях_початкового_модуля(
      М: адреса<Машина>,
      шлях: адреса<ПредметДаних>,
      вихід_абсолютного_шляху: адреса<адреса<ПредметДаних>>,
      вихід_теки_модулів: адреса<адреса<ПредметДаних>>,
      вихід_теки_паків: адреса<адреса<ПредметДаних>>,
      вихід_назви_модуля: адреса<адреса<ПредметТексту>>
    ) -> логічне {
      змінна розмір_абсолютого_шляху: природне;
      змінна дані_абсолютного_шляху: адреса<п8>;
      змінна розмір_теки_модулів: природне;
      змінна дані_теки_модулів: адреса<п8>;
      змінна розмір_теки_паків: природне;
      змінна дані_теки_паків: адреса<п8>;
      змінна розмір_назви_модуля: природне;
      змінна дані_назви_модуля: адреса<п8>;

      якщо не пристрій_мавки_перевірити_чи_шлях_існує_і_є_файлом(
        шлях.розмір,
        шлях.дані
      ) {
        вернути ні;
      }

      якщо не пристрій_мавки_отримати_абсолютний_шлях(
        шлях.розмір,
        шлях.дані,
        розмір_абсолютого_шляху::адреса,
        дані_абсолютного_шляху::адреса
      ) {
        вернути ні;
      }

      якщо не пристрій_мавки_отримати_теку_шляху(
        розмір_абсолютого_шляху,
        дані_абсолютного_шляху,
        розмір_теки_модулів::адреса,
        дані_теки_модулів::адреса,
        1
      ) {
        пристрій_мавки_звільнити_сиру_памʼять(дані_абсолютного_шляху);
        вернути ні;
      }

      якщо не пристрій_мавки_отримати_теку_до_паків(
        розмір_теки_модулів,
        дані_теки_модулів,
        розмір_теки_паків::адреса,
        дані_теки_паків::адреса
      ) {
        пристрій_мавки_звільнити_сиру_памʼять(дані_абсолютного_шляху);
        пристрій_мавки_звільнити_сиру_памʼять(дані_теки_модулів);
        вернути ні;
      }

      якщо не пристрій_мавки_отримати_назву_модуля_з_шляху(
        розмір_абсолютого_шляху,
        дані_абсолютного_шляху,
        розмір_назви_модуля::адреса,
        дані_назви_модуля::адреса
      ) {
        пристрій_мавки_звільнити_сиру_памʼять(дані_абсолютного_шляху);
        пристрій_мавки_звільнити_сиру_памʼять(дані_теки_модулів);
        пристрій_мавки_звільнити_сиру_памʼять(дані_теки_паків);
        вернути ні;
      }

      вихід_абсолютного_шляху::вміст = створити_дані(
        М,
        розмір_абсолютого_шляху,
        дані_абсолютного_шляху
      );

      вихід_теки_модулів::вміст = створити_дані(
        М,
        розмір_теки_модулів,
        дані_теки_модулів
      );

      вихід_теки_паків::вміст = створити_дані(
        М,
        розмір_теки_паків,
        дані_теки_паків
      );

      вихід_назви_модуля::вміст = створити_текст(
        М,
        кд { розмір_назви_модуля, дані_назви_модуля }
      );

      вернути так;
    }

    дія записати_шлях_до_теки_модулів_та_паків(
      М: адреса<Машина>,
      шлях_до_теки_модулів: адреса<ПредметДаних>,
      шлях_до_теки_паків: адреса<ПредметДаних>
    ) {
      змінна кдпм = М.користувацькі_дані_пристрою.значення як адреса<КористувацькіДаніПристроюМавки>;
      якщо кдпм.шлях_до_теки_модулів != пусто {
        ЗАПАНІКУВАТИ(М, "Шлях до теки модулів вже встановлено.");
      }
      якщо кдпм.шлях_до_теки_паків != пусто {
        ЗАПАНІКУВАТИ(М, "Шлях до теки паків вже встановлено.");
      }
      кдпм.шлях_до_теки_модулів = притримати_глобально(М, шлях_до_теки_модулів як адреса<Предмет>);
      кдпм.шлях_до_теки_паків = притримати_глобально(М, шлях_до_теки_паків як адреса<Предмет>);
    }
  }
}