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

взяти визначення КД;
взяти визначення мавка;

простір мавка {
  дія здійснити(
    М: *Машина,
    здійснювач: Значення,
    значення: Значення,
    задіяні: Задіяні,
    місцезнаходження: Місцезнаходження
  ) -> ЗначенняАбоСтанПадіння {
    якщо значення.вид == ЗНедійсне {
      вернути МІСЦЕПАДІННЯ(М, створити_текст(М, "Неможливо здійснити \"недійсне\"."), місцезнаходження);
    }

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

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

    змінна предмет = значення.дані як *Предмет;

    якщо предмет.клас == М.клас_Дія {
      вернути предмет_дії_здійснити(
        М,
        здійснювач,
        предмет як *ПредметДії,
        задіяні,
        місцезнаходження
      );
    }

    якщо предмет.клас == М.клас_Клас {
      вернути клас_здійснити(
        М,
        предмет як *ПредметКласу,
        задіяні,
        місцезнаходження
      );
    }

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

  // позначка: прохід по типах предметів
  дія отримати_властивість(
    М: *Машина,
    значення: Значення,
    назва: *ПредметТексту,
    місцезнаходження: Місцезнаходження
  ) -> ЗначенняАбоСтанПадіння {
    якщо значення.вид == ЗНедійсне {
      змінна накопичувач_тексту = зробити_накопичувач_тексту(М, 50);
      покласти_в_накопичувач_тексту(М, накопичувач_тексту::адреса, "Неможливо отримати властивість \"");
      покласти_в_накопичувач_тексту(М, накопичувач_тексту::адреса, назва.значення);
      покласти_в_накопичувач_тексту(М, накопичувач_тексту::адреса, "\" недійсного.");
      вернути МІСЦЕПАДІННЯ(М, створити_текст_без_копіювання(М, накопичувач_тексту.розмір, накопичувач_тексту.дані), місцезнаходження);
    }

    якщо значення.вид == ЗДійсне {
      вернути НЕДІЙСНЕ;
    }

    якщо значення.вид == ЗЧисло {
      вернути НЕДІЙСНЕ;
    }

    змінна предмет = значення.дані як *Предмет;

    якщо предмет.клас.вбудований {
      якщо предмет.клас == М.клас_Клас {
        вернути клас_отримати_властивість(
          М,
          предмет як *ПредметКласу,
          назва,
          місцезнаходження
        );
      }

      якщо предмет.клас == М.клас_Дані {
        вернути предмет_даних_отримати_властивість(
          М,
          предмет як *ПредметДаних,
          назва,
          місцезнаходження
        );
      }

      якщо предмет.клас == М.клас_ПроміжокЧисел {
        вернути предмет_проміжка_чисел_отримати_властивість(
          М,
          предмет як *ПредметПроміжкаЧисел,
          назва,
          місцезнаходження
        );
      }

      якщо предмет.клас == М.клас_Дія {
        вернути предмет_дії_отримати_властивість(
          М,
          предмет як *ПредметДії,
          назва,
          місцезнаходження
        );
      }

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

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

      якщо предмет.клас == М.клас_Ознака {
        вернути предмет_ознаки_отримати_властивість(
          М,
          предмет як *ПредметОзнаки,
          назва,
          місцезнаходження
        );
      }

      якщо предмет.клас == М.клас_ПеребірДаних {
        вернути предмет_перебору_даних_отримати_властивість(
          М,
          предмет як *ПредметПереборуДаних,
          назва,
          місцезнаходження
        );
      }

      якщо предмет.клас == М.клас_ПеребірПроміжкаЧисел {
        вернути предмет_перебору_проміжка_чисел_отримати_властивість(
          М,
          предмет як *ПредметПереборуПроміжкаЧисел,
          назва,
          місцезнаходження
        );
      }

      якщо предмет.клас == М.клас_ПеребірПослідовності {
        вернути предмет_перебору_послідовності_отримати_властивість(
          М,
          предмет як *ПредметПереборуПослідовності,
          назва,
          місцезнаходження
        );
      }

      якщо предмет.клас == М.клас_ПеребірСловника {
        вернути предмет_перебору_словника_отримати_властивість(
          М,
          предмет як *ПредметПереборуСловника,
          назва,
          місцезнаходження
        );
      }

      якщо предмет.клас == М.клас_ПеребірСписку {
        вернути предмет_перебору_списку_отримати_властивість(
          М,
          предмет як *ПредметПереборуСписку,
          назва,
          місцезнаходження
        );
      }

      якщо предмет.клас == М.клас_ПеребірТексту {
        вернути предмет_перебору_тексту_отримати_властивість(
          М,
          предмет як *ПредметПереборуТексту,
          назва,
          місцезнаходження
        );
      }

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

      якщо предмет.клас == М.клас_Словник {
        вернути предмет_словника_отримати_властивість(
          М,
          предмет як *ПредметСловника,
          назва,
          місцезнаходження
        );
      }

      якщо предмет.клас == М.клас_Список {
        вернути предмет_списку_отримати_властивість(
          М,
          предмет як *ПредметСписку,
          назва,
          місцезнаходження
        );
      }

      якщо предмет.клас == М.клас_Текст {
        вернути предмет_тексту_отримати_властивість(
          М,
          предмет як *ПредметТексту,
          назва,
          місцезнаходження
        );
      }

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

    вернути складений_предмет_отримати_властивість(
      М,
      значення.дані як *Предмет як *СкладенийПредмет,
      назва,
      місцезнаходження
    );
  }

  // позначка: прохід по типах предметів
  дія змінити_властивість(
    М: *Машина,
    значення: Значення,
    назва: *ПредметТексту,
    значення_властивості: Значення,
    місцезнаходження: Місцезнаходження
  ) -> СтанПадіння {
    якщо значення.вид == ЗНедійсне {
      МІСЦЕПАДІННЯ(М, створити_текст(М, "Неможливо змінити властивість недійсного."), місцезнаходження);
      вернути;
    }

    якщо значення.вид == ЗДійсне {
      МІСЦЕПАДІННЯ(М, створити_текст(М, "Неможливо змінити властивість дійсного."), місцезнаходження);
      вернути;
    }

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

    змінна предмет = значення.дані як *Предмет;

    якщо предмет.клас.вбудований {
      якщо предмет.клас == М.клас_Клас {
        клас_змінити_властивість(
          М,
          предмет як *ПредметКласу,
          назва,
          значення_властивості,
          місцезнаходження
        );
        вернути;
      }

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

    складений_предмет_змінити_властивість(
      М,
      значення.дані як *Предмет як *СкладенийПредмет,
      назва,
      значення_властивості,
      місцезнаходження
    );
  }

  дія здійснити_властивість(
    М: *Машина,
    значення: Значення,
    назва: *ПредметТексту,
    задіяні: Задіяні,
    місцезнаходження: Місцезнаходження
  ) -> ЗначенняАбоСтанПадіння {
    змінна значення_властивості = отримати_властивість(
      М,
      значення,
      назва,
      місцезнаходження
    );

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

      вернути НЕДІЙСНЕ;
    }

    якщо значення_властивості.вид == ЗНедійсне {
      звільнити_задіяні(М, задіяні);

      змінна накопичувач_тексту = зробити_накопичувач_тексту(М, 50);
      покласти_в_накопичувач_тексту(М, накопичувач_тексту::адреса, "Неможливо здійснити недійсне (властивість \"");
      покласти_в_накопичувач_тексту(М, накопичувач_тексту::адреса, назва.значення);
      покласти_в_накопичувач_тексту(М, накопичувач_тексту::адреса, "\").");

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

    вернути здійснити(
      М,
      значення,
      значення_властивості,
      задіяні,
      місцезнаходження
    );
  }

  // позначка: прохід по типах предметів
  дія отримати_елемент(
    М: *Машина,
    значення: Значення,
    ключ: Значення,
    місцезнаходження: Місцезнаходження
  ) -> ЗначенняАбоСтанПадіння {
    якщо значення.вид == ЗПредмет {
      змінна предмет = значення.дані як *Предмет;

      якщо предмет.клас == М.клас_Дані {
        вернути предмет_даних_отримати_елемент(
          М,
          предмет як *ПредметДаних,
          ключ,
          місцезнаходження
        );
      }

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

      якщо предмет.клас == М.клас_Словник {
        вернути предмет_словника_отримати_елемент(
          М,
          предмет як *ПредметСловника,
          ключ,
          місцезнаходження
        );
      }

      якщо предмет.клас == М.клас_Список {
        вернути предмет_списку_отримати_елемент(
          М,
          предмет як *ПредметСписку,
          ключ,
          місцезнаходження
        );
      }

      якщо предмет.клас == М.клас_Текст {
        вернути предмет_тексту_отримати_елемент(
          М,
          предмет як *ПредметТексту,
          ключ,
          місцезнаходження
        );
      }
    }

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

  // позначка: прохід по типах предметів
  дія змінити_елемент(
    М: *Машина,
    значення: Значення,
    ключ: Значення,
    значення_елемента: Значення,
    місцезнаходження: Місцезнаходження
  ) -> СтанПадіння {
    якщо значення.вид == ЗНедійсне {
      МІСЦЕПАДІННЯ(М, створити_текст(М, "Неможливо змінити елемент недійсного."), місцезнаходження);
      вернути;
    }

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

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

    змінна предмет = значення.дані як *Предмет;

    якщо предмет.клас == М.клас_Дані {
      предмет_даних_змінити_елемент(
        М,
        предмет як *ПредметДаних,
        ключ,
        значення_елемента,
        місцезнаходження
      );
      вернути;
    }

    якщо предмет.клас == М.клас_Словник {
      предмет_словника_змінити_елемент(
        М,
        предмет як *ПредметСловника,
        ключ,
        значення_елемента,
        місцезнаходження
      );
      вернути;
    }

    якщо предмет.клас == М.клас_Список {
      предмет_списку_змінити_елемент(
        М,
        предмет як *ПредметСписку,
        ключ,
        значення_елемента,
        місцезнаходження
      );
      вернути;
    }
  }

  // позначка: прохід по типах предметів
  дія отримати_текст(
    М: *Машина,
    значення: Значення,
    місцезнаходження: Місцезнаходження
  ) -> *ПредметТексту {
    якщо значення.вид == ЗНедійсне {
      вернути М.константи_назв._недійсне;
    }

    якщо значення.вид == ЗДійсне {
      вернути М.константи_назв._дійсне;
    }

    якщо значення.вид == ЗЧисло {
      змінна значення_кд: кд;

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

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

    змінна предмет = значення.дані як *Предмет;

    якщо предмет.клас == М.клас_Текст {
      вернути предмет як *ПредметТексту;
    }

    змінна результат = здійснити_властивість(
      М,
      значення,
      М.константи_назв._чародія_текст,
      Задіяні { ВидЗадіяних2, 0, пусто, 0 },
      місцезнаходження
    );

    якщо М.стан_падіння {
      вернути пусто;
    }

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

    змінна предмет_результату = результат.дані як *Предмет;

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

    вернути предмет_результату як *ПредметТексту;
  }

  // позначка: прохід по типах предметів
  дія отримати_послідовність(
    М: *Машина,
    значення: Значення,
    місцезнаходження: Місцезнаходження
  ) -> *ПредметПослідовності {
    якщо значення.вид == ЗНедійсне {
      МІСЦЕПАДІННЯ(М, створити_текст(М, "Неможливо отримати послідовність з недійсного."), місцезнаходження);
      вернути пусто;
    }

    якщо значення.вид == ЗДійсне {
      МІСЦЕПАДІННЯ(М, створити_текст(М, "Неможливо отримати послідовність із значення \"дійсне\"."), місцезнаходження);
      вернути пусто;
    }

    якщо значення.вид == ЗЧисло {
      МІСЦЕПАДІННЯ(М, створити_текст(М, "Неможливо отримати послідовність з числа."), місцезнаходження);
      вернути пусто;
    }

    змінна предмет = значення.дані як *Предмет;

    якщо предмет.клас == М.клас_Послідовність {
      вернути предмет як *ПредметПослідовності;
    }

    змінна результат = здійснити_властивість(
      М,
      значення,
      М.константи_назв._чародія_послідовність,
      Задіяні { ВидЗадіяних2, 0, пусто, 0 },
      місцезнаходження
    );

    якщо М.стан_падіння {
      вернути пусто;
    }

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

    змінна предмет_результату = результат.дані як *Предмет;

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

    вернути предмет_результату як *ПредметПослідовності;
  }

  // позначка: прохід по типах предметів
  дія отримати_проміжок(
    М: *Машина,
    від: Значення,
    до: Значення,
    включно: логічне,
    місцезнаходження: Місцезнаходження
  ) -> ЗначенняАбоСтанПадіння {
    якщо від.вид == ЗЧисло {
      якщо до.вид == ЗЧисло {
        вернути ПРЕДМЕТ(створити_проміжок_чисел(
          М,
          від.дані як р64,
          до.дані як р64,
          включно
        ));
      }

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

    змінна задіяні = Задіяні { ВидЗадіяних2, 2, виділити<Значення>(М, 2), 0 };
    задіяні.дані[0] = до;
    якщо включно {
      задіяні.дані[1] = ДІЙСНЕ;
    } інакше {
      задіяні.дані[1] = НЕДІЙСНЕ;
    }

    вернути здійснити_властивість(
      М,
      від,
      М.константи_назв._чародія_межа,
      задіяні,
      місцезнаходження
    );
  }

  // позначка: прохід по типах предметів
  дія отримати_перебір(
    М: *Машина,
    значення: Значення,
    місцезнаходження: Місцезнаходження
  ) -> ЗначенняАбоСтанПадіння {
    якщо значення.вид == ЗПредмет {
      змінна предмет = значення.дані як *Предмет;

      якщо предмет.клас == М.клас_Дані {
        вернути ПРЕДМЕТ(створити_перебір_даних(
          М,
          предмет як *ПредметДаних
        ));
      }

      якщо предмет.клас == М.клас_ПроміжокЧисел {
        вернути ПРЕДМЕТ(створити_перебір_проміжка_чисел(
          М,
          предмет як *ПредметПроміжкаЧисел
        ));
      }

      якщо предмет.клас == М.клас_Послідовність {
        вернути ПРЕДМЕТ(створити_перебір_послідовності(
          М,
          предмет як *ПредметПослідовності
        ));
      }

      якщо предмет.клас == М.клас_Словник {
        вернути ПРЕДМЕТ(створити_перебір_словника(
          М,
          предмет як *ПредметСловника
        ));
      }

      якщо предмет.клас == М.клас_Список {
        вернути ПРЕДМЕТ(створити_перебір_списку(
          М,
          предмет як *ПредметСписку
        ));
      }

      якщо предмет.клас == М.клас_Текст {
        вернути ПРЕДМЕТ(створити_перебір_тексту(
          М,
          предмет як *ПредметТексту
        ));
      }
    }

    вернути здійснити_властивість(
      М,
      значення,
      М.константи_назв._чародія_перебір,
      Задіяні { ВидЗадіяних2, 0, пусто, 0 },
      місцезнаходження
    );
  }

  внутрішня дія є_невизначеність(значення: р64) -> логічне {
    вернути значення != значення;
  }

  дія порівняти_значення(
    М: *Машина,
    а: Значення,
    б: Значення
  ) -> логічне {
    якщо а.вид != б.вид {
      вернути ні;
    }

    якщо а.вид == ЗНедійсне {
      вернути так;
    }

    якщо а.вид == ЗДійсне {
      вернути так;
    }

    якщо а.вид == ЗЧисло {
      якщо є_невизначеність(а.дані як р64) і є_невизначеність(б.дані як р64) {
        вернути ні;
      }

      вернути (а.дані як р64) == (б.дані як р64);
    }

    якщо а.вид != ЗПредмет {
      ЗАПАНІКУВАТИ(М, "Невідомий вид значення у перевірці на рівність.");
    }

    змінна а_предмет = а.дані як *Предмет;
    змінна б_предмет = б.дані як *Предмет;

    якщо а_предмет == б_предмет {
      вернути так;
    }

    якщо а_предмет.клас == б_предмет.клас {
      якщо а_предмет.клас == М.клас_Текст {
        вернути порівняти_тексти(
          М,
          а_предмет як *ПредметТексту,
          б_предмет як *ПредметТексту
        );
      }

      якщо а_предмет.клас == М.клас_Послідовність {
        вернути порівняти_послідовності(
          М,
          а_предмет як *ПредметПослідовності,
          б_предмет як *ПредметПослідовності
        );
      }
    }

    вернути ні;
  }

  дія перевірити_чи_предмет_є(
    М: *Машина,
    а: *Предмет,
    б: *ПредметКласу
  ) -> логічне {
    вернути а.клас == б;
  }
}