В Аде, Как мне рекурсивно отобразить и память управлять типом внутри себя

Я боролся с этой маленькой проблемой некоторое время. Я пытаюсь создать свою собственную реализацию внутренней структуры JSON. Проблема в том, что с Ada я должен использовать тип доступа, чтобы сделать его рекурсивным, а у типов доступа есть риск утечки, если я не контролирую его жестко. Для того, чтобы это контролировалось, я держал всю реальную деятельность в секрете Get (Source:...) а также Set (Target:...; Value:...) функции / процедуры для типа Node, которые будут пытаться проверять и обрабатывать любые существующие элементы Vector (json-array) или Map (json-object). Чтобы еще больше убедиться, что я использую стабильные функции Ada 2012 и ловлю содержимое по мере их выхода из области видимости, я попытался использовать тип Protected_Controlled и "управлять" библиотеками Ada, но обнаружил, что библиотеки контейнеров не могут обрабатывать защищенные типы Так что я использовал просто контролируемый. Finalize (...) Процедура предназначена для любых типов Vector или Map и рекурсивно освобождает Node_Value.Reference.

У меня вопрос: правильно ли я применяю Ada 2012, или как мне создать управляемую памятью рекурсию типа, который может быть вектором / картой или строкой / числом?

private

    ...

   type Node_Access is access Node;
   type Node_Value is new Ada.Finalization.Controlled with record
      Reference : Node_Access;
   end record;
   overriding procedure Initialize (Item : in out Node_Value);
   overriding procedure Adjust (Item : in out Node_Value);
   overriding procedure Finalize (Item : in out Node_Value);

    ...

   package Of_Array is new Ada.Containers.Indefinite_Vectors (Natural, Node_Value);
   package Of_Object is new Ada.Containers.Indefinite_Ordered_Maps (Wide_String, Node_Value);

   type Node is record
      ...
      Vector    : aliased Of_Array.Vector;
      Object    : aliased Of_Object.Map;
   end record
     with Size => 96;

   procedure Free is new Ada.Unchecked_Deallocation (Node, Node_Access);

2 ответа

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

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

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

with Ada.Containers.Indefinite_Vectors;
package Sexes is
   type Sex is private;
   -- Operations on Sex
private -- Sexes
   package Sex_List is new Ada.Containers.Indefinite_Vectors
      (Index_Type => Positive, Element_Type => Sex); -- Illegal

   type Sex (Is_Atom : Boolean := False) is record
      case Is_Atom is
      when False =>
         Value : Atom;
      when True =>
         List : Sex_List.Vector;
      end case;
   end record;
end Sexes;

но Ада не позволяет этого. Мы можем использовать расширение типа, чтобы обойти это:

private -- Sexes
   type Root is tagged null record;

   package Sex_List is new Ada.Containers.Indefinite_Vectors
      (Index_Type => Positive, Element_Type => Root'Class);

   type Sex (Is_Atom : Boolean := False) is new Root with record
      case Is_Atom is
      when False =>
         Value : Atom;
      when True =>
         List : Sex_List.Vector;
      end case;
   end record;
end Sexes;

что законно Единственный улов заключается в том, что вам нужно преобразовать все, что взято из Списка, в Пол (или в вашем случае в Узел).

НТН; извините за поздний ответ.

Другие вопросы по тегам