ru.malik.elaborarer.avt.programme.pas

Переключить прокрутку окна
Загрузить этот исходный код

{
    Этот исходный код является частью проекта ПВТ-ОО.

    Copyright © 2021 Малик Разработчик

    Это свободная программа: вы можете перераспространять её и/или
    изменять её на условиях Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она может быть полезна,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <http://www.gnu.org/licenses/>.
}

unit ru.malik.elaborarer.avt.programme;

{$MODE DELPHI}

interface

uses
    pascalx.lang,
    pascalx.io,
    pascalx.io.vfs,
    pascalx.utils,
    osindepended.fileformats,
    osindepended.fileformats.text,
    osindepended.fileformats.text.plain;

{$ASMMODE INTEL,CALLING REGISTER,TYPEINFO ON}

{%region pulic }
const
    AVTC_VERSION = '0.4.1';

    (* Л – константа является результатом работы лексического анализатора ru.malik.elaborarer.avt.lexer *)
    (* Д – константа является результатом работы построителя дерева разбора ru.malik.elaborarer.avt.tree *)
                                                               (* | Л | Д | описание                                                                                             *)
const { ключевые слова, области видимости }
    AVT_PRIVATE           = int(0);                            (* | x |   | private                                                                                              *)
    AVT_SOURCE            = int(2);                            (* |   |   | область видимости source                                                                             *)
    AVT_PACKAGE           = int(4);                            (* | x |   | package                                                                                              *)
    AVT_PROTECTED         = int(5);                            (* | x |   | protected                                                                                            *)
    AVT_PUBLIC            = int(6);                            (* | x |   | public                                                                                               *)
    AVT_PUBLISHED         = int(7);                            (* | x |   | published                                                                                            *)
    AVT_ABSTRACT          = int(8);                            (* | x |   | abstract                                                                                             *)
    AVT_FINAL             = int(9);                            (* | x |   | final                                                                                                *)
    AVT_IMPORT            = int(10);                           (* | x |   | import                                                                                               *)
    AVT_UNION             = int(11);                           (* | x |   | union                                                                                                *)
    AVT_CLASS             = int(12);                           (* | x |   | class                                                                                                *)
    AVT_STRUCT            = int(13);                           (* | x |   | struct                                                                                               *)
    AVT_SERVICE           = int(14);                           (* | x |   | service                                                                                              *)
    AVT_INTERFACE         = int(15);                           (* | x |   | interface                                                                                            *)
    AVT_STATIC            = int(16);                           (* | x |   | static                                                                                               *)
    AVT_NATIVE            = int(17);                           (* | x |   | native                                                                                               *)
    AVT_INTERRUPT         = int(18);                           (* | x |   | interrupt                                                                                            *)
    AVT_SYNCHRONIZED      = int(19);                           (* | x | x | synchronized                                                                                         *)
    AVT_VOID              = int(20);                           (* | x |   | void                                                                                                 *)
    AVT_BOOLEAN           = int(21);                           (* | x |   | boolean                                                                                              *)
    AVT_CHAR              = int(22);                           (* | x |   | char                                                                                                 *)
    AVT_REAL              = int(23);                           (* | x |   | real                                                                                                 *)
    AVT_BYTE              = int(24);                           (* | x |   | byte (значение (24) делится на 8)                                                                    *)
    AVT_BYTE2             = int(25);                           (* | x |   | byte2                                                                                                *)
    AVT_BYTE4             = int(26);                           (* | x |   | byte4                                                                                                *)
    AVT_BYTE8             = int(27);                           (* | x |   | byte8                                                                                                *)
    AVT_SHORT             = int(28);                           (* | x |   | short                                                                                                *)
    AVT_SHORT2            = int(29);                           (* | x |   | short2                                                                                               *)
    AVT_SHORT4            = int(30);                           (* | x |   | short4                                                                                               *)
    AVT_SHORT8            = int(31);                           (* | x |   | short8                                                                                               *)
    AVT_INT               = int(32);                           (* | x |   | int                                                                                                  *)
    AVT_INT2              = int(33);                           (* | x |   | int2                                                                                                 *)
    AVT_INT4              = int(34);                           (* | x |   | int4                                                                                                 *)
    AVT_INT8              = int(35);                           (* | x |   | int8                                                                                                 *)
    AVT_LONG              = int(36);                           (* | x |   | long                                                                                                 *)
    AVT_LONG2             = int(37);                           (* | x |   | long2                                                                                                *)
    AVT_LONG4             = int(38);                           (* | x |   | long4                                                                                                *)
    AVT_LONG8             = int(39);                           (* | x |   | long8                                                                                                *)
    AVT_FLOAT             = int(40);                           (* | x |   | float                                                                                                *)
    AVT_FLOAT2            = int(41);                           (* | x |   | float2                                                                                               *)
    AVT_FLOAT4            = int(42);                           (* | x |   | float4                                                                                               *)
    AVT_FLOAT8            = int(43);                           (* | x |   | float8                                                                                               *)
    AVT_DOUBLE            = int(44);                           (* | x |   | double                                                                                               *)
    AVT_DOUBLE2           = int(45);                           (* | x |   | double2                                                                                              *)
    AVT_DOUBLE4           = int(46);                           (* | x |   | double4                                                                                              *)
    AVT_DOUBLE8           = int(47);                           (* | x |   | double8                                                                                              *)
    AVT_OPERATOR          = int(48);                           (* | x |   | operator                                                                                             *)
    AVT_THROWS            = int(49);                           (* | x |   | throws                                                                                               *)
    AVT_SUPER             = int(50);                           (* | x |   | super                                                                                                *)
    AVT_THIS              = int(51);                           (* | x |   | this                                                                                                 *)
    AVT_INSTANCEOF        = int(52);                           (* | x | x | instanceof                                                                                           *)
    AVT_WITH              = int(53);                           (* | x | x | with                                                                                                 *)
    AVT_IF                = int(54);                           (* | x | x | if                                                                                                   *)
    AVT_ELSE              = int(55);                           (* | x |   | else                                                                                                 *)
    AVT_SWITCH            = int(56);                           (* | x | x | switch                                                                                               *)
    AVT_CASE              = int(57);                           (* | x | x | case                                                                                                 *)
    AVT_DEFAULT           = int(58);                           (* | x | x | default                                                                                              *)
    AVT_LABEL             = int(59);                           (* |   | x | <label>:                                                                                             *)
    AVT_DO                = int(60);                           (* | x | x | do                                                                                                   *)
    AVT_FOR               = int(61);                           (* | x | x | for                                                                                                  *)
    AVT_WHILE             = int(62);                           (* | x | x | while                                                                                                *)
    AVT_BLOCK             = int(63);                           (* |   | x | { … }                                                                                                *)
    AVT_BREAK             = int(64);                           (* | x |   | break                                                                                                *)
    AVT_CONTINUE          = int(65);                           (* | x |   | continue                                                                                             *)
    AVT_RETURN            = int(66);                           (* | x | x | return                                                                                               *)
    AVT_THROW             = int(67);                           (* | x | x | throw                                                                                                *)
    AVT_TRY_BEGIN         = int(68);                           (* | x | x | try (начало блока)                                                                                   *)
    AVT_TRY_END           = int(69);                           (* |   | x | try (конец блока)                                                                                    *)
    AVT_CATCH             = int(70);                           (* | x | x | catch                                                                                                *)
    AVT_FINALLY           = int(71);                           (* | x | x | finally                                                                                              *)
    AVT_FINALLY_INVOKE    = int(72);                           (* |   | x | вызов тела блока finally                                                                             *)
    AVT_FINALLY_RETURN    = int(73);                           (* |   | x | возврат из блока finally                                                                             *)
    AVT_MONITOR_ENTER     = int(74);                           (* | x |   | получение владения блокирующим монитором                                                             *)
    AVT_MONITOR_LEAVE     = int(75);                           (* | x |   | потеря владения блокирующим монитором                                                                *)
    AVT_FALSE             = int(76);                           (* |   |   | false                                                                                                *)
    AVT_TRUE              = int(77);                           (* |   |   | true                                                                                                 *)
    AVT_NEW               = int(78);                           (* | x |   | new                                                                                                  *)
    AVT_NULL              = int(79);                           (* | x |   | null                                                                                                 *)
    AVT_CLINIT_TRY_LOCK   = int(94);                           (* |   | x | вход в метод static{…}                                                                               *)
    AVT_CLINIT_UNLOCK     = int(95);                           (* |   | x | выход из метода static{…}                                                                            *)
    AVT_ENTER             = int(126);                          (* |   | x | вход в метод                                                                                         *)
    AVT_LEAVE             = int(127);                          (* |   | x | возврат из метода                                                                                    *)
    AVT_END               = AVT_LEAVE;                         (* | x |   | конец исходного кода                                                                                 *)

const { символы }
    CHAR_PARENTH_OPENED   = int(80);                           (* | x |   | (                                                                                                    *)
    CHAR_PARENTH_CLOSED   = int(81);                           (* | x |   | )                                                                                                    *)
    CHAR_EQUALS           = int(82);                           (* | x |   | =                                                                                                    *)
    CHAR_QUESTION         = int(83);                           (* | x |   | ?                                                                                                    *)
    CHAR_PERIOD           = int(84);                           (* | x |   | .                                                                                                    *)
    CHAR_COMMA            = int(85);                           (* | x |   | ,                                                                                                    *)
    CHAR_COLON            = int(86);                           (* | x |   | :                                                                                                    *)
    CHAR_SEMICOLON        = int(87);                           (* | x |   | ;                                                                                                    *)
    CHAR_BRACKET_OPENED   = int(88);                           (* | x |   | [                                                                                                    *)
    CHAR_BRACKET_CLOSED   = int(89);                           (* | x |   | ]                                                                                                    *)
    CHAR_CURLY_OPENED     = int(90);                           (* | x |   | {                                                                                                    *)
    CHAR_CURLY_CLOSED     = int(91);                           (* | x |   | }                                                                                                    *)

const { литералы }
    LITR_DOCUMENTATION    = int(100);                          (* | x |   | документация                                                                                         *)
    LITR_NAME             = int(101);                          (* | x |   | название                                                                                             *)
    LITR_STRING           = int(102);                          (* | x |   | строковый литерал                                                                                    *)
    LITR_BOOLEAN          = int(103);                          (* | x |   | литерал типа boolean                                                                                 *)
    LITR_CHAR             = int(104);                          (* | x |   | литерал типа char                                                                                    *)
    LITR_REAL             = int(105);                          (* | x |   | литерал типа real                                                                                    *)
    LITR_BYTE             = int(106);                          (* | x |   | литерал типа byte                                                                                    *)
    LITR_SHORT            = int(107);                          (* | x |   | литерал типа short                                                                                   *)
    LITR_INT              = int(108);                          (* | x |   | литерал типа int                                                                                     *)
    LITR_LONG             = int(109);                          (* | x |   | литерал типа long                                                                                    *)
    LITR_FLOAT            = int(110);                          (* | x |   | литерал типа float                                                                                   *)
    LITR_DOUBLE           = int(111);                          (* | x |   | литерал типа double                                                                                  *)

const { операторы }
    LOAD_VARIABLE         = int(128);                          (* |   | x | загрузка на стак значения локальной переменной                                                       *)
    LOAD_STATIC           = int(129);                          (* |   | x | загрузка на стак значения глобальной переменной                                                      *)
    LOAD_CLASS            = int(130);                          (* |   | x | загрузка на стак ссылки на класс { НЕ ИСПОЛЬЗУЕТСЯ! ИСПОЛЬЗУЙ LOAD_CONST ВМЕСТО ЭТОЙ ИНСТРУКЦИИ. }   *)
    LOAD_CONST            = int(131);                          (* |   | x | загрузка на стак постоянного значения                                                                *)
    GET_FIELD             = int(132);                          (* |   | x | чтение поля объекта или структуры                                                                    *)
    GET_PROPERTY          = int(133);                          (* |   | x | чтение свойства                                                                                      *)
    GET_ARRAY_ELEMENT     = int(134);                          (* |   | x | чтение элемента массива (оператор [])                                                                *)
    GET_VECTOR_ELEMENT    = int(135);                          (* |   | x | чтение элемента вектора (оператор [])                                                                *)
    DECLARE_VARIABLE      = int(136);                          (* |   | x | объявление переменной (также рассматривается как присвоение значения переменной)                     *)
    DUP1                  = int(140);                          (* |   | x | дублирование элемента на вершине стака: … a b → … a b b                                              *)
    DUP2                  = int(141);                          (* |   | x | дублирование двух элементов на вершине стака: … a b c → … a b c b c                                  *)
    DUP1X1                = int(142);                          (* |   | x | дублирование элемента на вершине стака и размещение его одним элементом ниже: … a b → … b a b        *)
    DUP1X2                = int(143);                          (* |   | x | дублирование элемента на вершине стака и размещение его двумя элементами ниже: … a b c → … c a b c   *)
    POP1                  = int(144);                          (* |   | x | извлечение одного элемента стака: … a b → … a                                                        *)
    JUMP                  = int(147);                          (* |   | x | безусловный переход                                                                                  *)
    INVOKE_STATIC         = int(148);                          (* |   | x | вызов метода класса                                                                                  *)
    INVOKE_SPECIAL        = int(149);                          (* |   | x | вызов конструктора, приватного метода объекта или метода из супертипа (super.method(arguments))      *)
    INVOKE_VIRTUAL        = int(150);                          (* |   | x | вызов виртуального метода объекта                                                                    *)
    INVOKE_SERVICE        = int(151);                          (* |   | x | вызов метода сервиса или протокола                                                                   *)
    NEW_ARRAY_BY_LENGTH   = int(152);                          (* |   | x | new <type name>[<length>][][]…[]                                                                     *)
    NEW_MULTI_ARRAY       = int(153);                          (* |   | x | new <type name>[<length1>][<length2>]…[<lengthN>][][]…[]                                             *)
    NEW_ARRAY_BY_ELEMENTS = int(154);                          (* |   | x | new <type name>[][]…[] { … }                                                                         *)
    NEW_VECTOR            = int(155);                          (* |   | x | new <vector type> { … }                                                                              *)
    NEW_CLASS             = int(156);                          (* |   | x | new <class name>(…) { … }                                                                            *)
    NEW_STRUCT            = int(157);                          (* |   | x | new <struct name>(…) { … }                                                                           *)
    NEW_SERVICE           = int(158);                          (* |   | x | new <service name>(…) { … }                                                                          *)
    OPER_TYPE_CAST        = int(176);                          (* |   | x | (<type>) a                                                                                           *)
    OPER_INCREMENT        = int(178);                          (* | x | x | a++, ++a (применимо только к локальным переменным)                                                   *)
    OPER_DECREMENT        = int(179);                          (* | x | x | a--, --a (применимо только к локальным переменным)                                                   *)
    OPER_INC_POST         = int(180);                          (* |   | x | a++ (применимо только к локальным переменным)                                                        *)
    OPER_DEC_POST         = int(181);                          (* |   | x | a-- (применимо только к локальным переменным)                                                        *)
    OPER_INC_PRED         = int(182);                          (* |   | x | ++a (применимо только к локальным переменным)                                                        *)
    OPER_DEC_PRED         = int(183);                          (* |   | x | --a (применимо только к локальным переменным)                                                        *)
    OPER_BOOL_NOT         = int(184);                          (* | x | x | !a                                                                                                   *)
    OPER_BOOL_AND         = int(185);                          (* | x | x | a && b                                                                                               *)
    OPER_BOOL_OR          = int(186);                          (* | x | x | a || b                                                                                               *)
    OPER_BOOL_COND        = int(187);                          (* |   | x | a ? b : c                                                                                            *)
    OPER_BIT_NOT          = int(188);                          (* | x | x | ~a                                                                                                   *)
    OPER_BIT_AND          = int(189);                          (* | x | x | a & b                                                                                                *)
    OPER_BIT_OR           = int(190);                          (* | x | x | a | b                                                                                                *)
    OPER_BIT_XOR          = int(191);                          (* | x | x | a ^ b                                                                                                *)
    OPER_SCAL_PLUS        = int(192);                          (* |   | x | +a                                                                                                   *)
    OPER_SCAL_MINUS       = int(193);                          (* |   | x | -a                                                                                                   *)
    OPER_SCAL_MUL         = int(194);                          (* | x | x | a * b                                                                                                *)
    OPER_SCAL_DIV         = int(196);                          (* | x | x | a / b                                                                                                *)
    OPER_SCAL_DIVU        = int(197);                          (* | x | x | a // b                                                                                               *)
    OPER_SCAL_REM         = int(198);                          (* | x | x | a % b                                                                                                *)
    OPER_SCAL_REMU        = int(199);                          (* | x | x | a %% b                                                                                               *)
    OPER_SCAL_ADD         = int(200);                          (* | x | x | a + b                                                                                                *)
    OPER_SCAL_SUB         = int(201);                          (* | x | x | a - b                                                                                                *)
    OPER_SCAL_SAR         = int(204);                          (* | x | x | a >> b                                                                                               *)
    OPER_SCAL_SAL         = int(205);                          (* | x | x | a << b                                                                                               *)
    OPER_SCAL_SHR         = int(206);                          (* | x | x | a >>> b                                                                                              *)
    OPER_SCAL_G           = int(208);                          (* | x | x | a > b                                                                                                *)
    OPER_SCAL_GE          = int(209);                          (* | x | x | a >= b                                                                                               *)
    OPER_SCAL_L           = int(210);                          (* | x | x | a < b                                                                                                *)
    OPER_SCAL_LE          = int(211);                          (* | x | x | a <= b                                                                                               *)
    OPER_SCAL_E           = int(212);                          (* | x | x | a == b                                                                                               *)
    OPER_SCAL_NE          = int(213);                          (* | x | x | a != b                                                                                               *)
    OPER_VECT_UNPCKL      = int(220);                          (* | x | x | ####a                                                                                                *)
    OPER_VECT_UNPCKU      = int(221);                          (* | x | x | ^^^^a                                                                                                *)
    OPER_VECT_PACK        = int(222);                          (* | x | x | @@@@a                                                                                                *)
    OPER_VECT_PLUS        = int(224);                          (* |   | x | ++++a                                                                                                *)
    OPER_VECT_MINUS       = int(225);                          (* |   | x | ----a                                                                                                *)
    OPER_VECT_MUL         = int(226);                          (* | x | x | a **** b                                                                                             *)
    OPER_VECT_DIV         = int(228);                          (* | x | x | a //// b                                                                                             *)
    OPER_VECT_ADD         = int(232);                          (* | x | x | a ++++ b                                                                                             *)
    OPER_VECT_SUB         = int(233);                          (* | x | x | a ---- b                                                                                             *)
    OPER_VECT_SAR         = int(236);                          (* | x | x | a >>>> b                                                                                             *)
    OPER_VECT_SAL         = int(237);                          (* | x | x | a <<<< b                                                                                             *)
    OPER_VECT_SHR         = int(238);                          (* | x | x | a >>>>> b                                                                                            *)
    OPER_VECT_G           = int(240);                          (* | x | x | a |>>| b                                                                                             *)
    OPER_VECT_GE          = int(241);                          (* | x | x | a |>=| b                                                                                             *)
    OPER_VECT_L           = int(242);                          (* | x | x | a |<<| b                                                                                             *)
    OPER_VECT_LE          = int(243);                          (* | x | x | a |<=| b                                                                                             *)
    OPER_VECT_E           = int(244);                          (* | x | x | a |==| b                                                                                             *)
    OPER_VECT_NE          = int(245);                          (* | x | x | a |!=| b                                                                                             *)
    OPER_VECT_MULS        = int(248);                          (* | x | x | a |**| b                                                                                             *)
    OPER_VECT_ADDS        = int(249);                          (* | x | x | a |++| b                                                                                             *)
    OPER_VECT_SUBS        = int(250);                          (* | x | x | a |--| b                                                                                             *)
    OPER_VECT_MULU        = int(252);                          (* | x | x | a #**# b                                                                                             *)
    OPER_VECT_ADDU        = int(253);                          (* | x | x | a #++# b                                                                                             *)
    OPER_VECT_SUBU        = int(254);                          (* | x | x | a #--# b                                                                                             *)

const { операторы записи значения }
    STORE_VARIABLE        = int(256 + LOAD_VARIABLE);          (* |   | x | запись в локальную переменную                                                                        *)
    STORE_STATIC          = int(256 + LOAD_STATIC);            (* |   | x | запись в глобальную переменную                                                                       *)
    SET_FIELD             = int(256 + GET_FIELD);              (* |   | x | запись в поле объекта или структуры                                                                  *)
    SET_PROPERTY          = int(256 + GET_PROPERTY);           (* |   | x | запись в свойство                                                                                    *)
    SET_ARRAY_ELEMENT     = int(256 + GET_ARRAY_ELEMENT);      (* |   | x | запись в элемент массива (оператор []=)                                                              *)
    ASGN_BIT_AND          = int(256 + OPER_BIT_AND);           (* | x |   | a &= b                                                                                               *)
    ASGN_BIT_OR           = int(256 + OPER_BIT_OR);            (* | x |   | a |= b                                                                                               *)
    ASGN_BIT_XOR          = int(256 + OPER_BIT_XOR);           (* | x |   | a ^= b                                                                                               *)
    ASGN_SCAL_MUL         = int(256 + OPER_SCAL_MUL);          (* | x |   | a *= b                                                                                               *)
    ASGN_SCAL_DIV         = int(256 + OPER_SCAL_DIV);          (* | x |   | a /= b                                                                                               *)
    ASGN_SCAL_DIVU        = int(256 + OPER_SCAL_DIVU);         (* | x |   | a //= b                                                                                              *)
    ASGN_SCAL_REM         = int(256 + OPER_SCAL_REM);          (* | x |   | a %= b                                                                                               *)
    ASGN_SCAL_REMU        = int(256 + OPER_SCAL_REMU);         (* | x |   | a %%= b                                                                                              *)
    ASGN_SCAL_ADD         = int(256 + OPER_SCAL_ADD);          (* | x |   | a += b                                                                                               *)
    ASGN_SCAL_SUB         = int(256 + OPER_SCAL_SUB);          (* | x |   | a -= b                                                                                               *)
    ASGN_SCAL_SAR         = int(256 + OPER_SCAL_SAR);          (* | x |   | a >>= b                                                                                              *)
    ASGN_SCAL_SAL         = int(256 + OPER_SCAL_SAL);          (* | x |   | a <<= b                                                                                              *)
    ASGN_SCAL_SHR         = int(256 + OPER_SCAL_SHR);          (* | x |   | a >>>= b                                                                                             *)
    ASGN_VECT_MUL         = int(256 + OPER_VECT_MUL);          (* | x |   | a ****= b                                                                                            *)
    ASGN_VECT_DIV         = int(256 + OPER_VECT_DIV);          (* | x |   | a ////= b                                                                                            *)
    ASGN_VECT_ADD         = int(256 + OPER_VECT_ADD);          (* | x |   | a ++++= b                                                                                            *)
    ASGN_VECT_SUB         = int(256 + OPER_VECT_SUB);          (* | x |   | a ----= b                                                                                            *)
    ASGN_VECT_SAR         = int(256 + OPER_VECT_SAR);          (* | x |   | a >>>>= b                                                                                            *)
    ASGN_VECT_SAL         = int(256 + OPER_VECT_SAL);          (* | x |   | a <<<<= b                                                                                            *)
    ASGN_VECT_SHR         = int(256 + OPER_VECT_SHR);          (* | x |   | a >>>>>= b                                                                                           *)
    ASGN_VECT_G           = int(256 + OPER_VECT_G);            (* | x |   | a |>>|= b                                                                                            *)
    ASGN_VECT_GE          = int(256 + OPER_VECT_GE);           (* | x |   | a |>=|= b                                                                                            *)
    ASGN_VECT_L           = int(256 + OPER_VECT_L);            (* | x |   | a |<<|= b                                                                                            *)
    ASGN_VECT_LE          = int(256 + OPER_VECT_LE);           (* | x |   | a |<=|= b                                                                                            *)
    ASGN_VECT_E           = int(256 + OPER_VECT_E);            (* | x |   | a |==|= b                                                                                            *)
    ASGN_VECT_NE          = int(256 + OPER_VECT_NE);           (* | x |   | a |!=|= b                                                                                            *)
    ASGN_VECT_MULS        = int(256 + OPER_VECT_MULS);         (* | x |   | a |**|= b                                                                                            *)
    ASGN_VECT_ADDS        = int(256 + OPER_VECT_ADDS);         (* | x |   | a |++|= b                                                                                            *)
    ASGN_VECT_SUBS        = int(256 + OPER_VECT_SUBS);         (* | x |   | a |--|= b                                                                                            *)
    ASGN_VECT_MULU        = int(256 + OPER_VECT_MULU);         (* | x |   | a #**#= b                                                                                            *)
    ASGN_VECT_ADDU        = int(256 + OPER_VECT_ADDU);         (* | x |   | a #++#= b                                                                                            *)
    ASGN_VECT_SUBU        = int(256 + OPER_VECT_SUBU);         (* | x |   | a #--#= b                                                                                            *)

const { лексемы документации }
    DOC_TEXT              = int(0);                            (* слово или произвольный текст (не является одним из остальных лексем документации)                              *)
    DOC_NAME              = int(1);                            (* название                                                                                                       *)
    DOC_ALINK             = int(2);                            (* @link                                                                                                          *)
    DOC_APARAM            = int(3);                            (* @param                                                                                                         *)
    DOC_ARETURN           = int(4);                            (* @return                                                                                                        *)
    DOC_ATHROWS           = int(5);                            (* @throws                                                                                                        *)
    DOC_ASINCE            = int(7);                            (* @since                                                                                                         *)
    DOC_ASEE              = int(8);                            (* @see                                                                                                           *)
    DOC_VECT_PACK         = int(9);                            (* @@@@                                                                                                           *)
    DOC_VECT_UNPCKL       = int(10);                           (* ####                                                                                                           *)
    DOC_VECT_UNPCKU       = int(11);                           (* ^^^^                                                                                                           *)
    DOC_VECT_MUL          = int(12);                           (* ****                                                                                                           *)
    DOC_VECT_DIV          = int(13);                           (* ////                                                                                                           *)
    DOC_VECT_ADD          = int(14);                           (* ++++                                                                                                           *)
    DOC_VECT_SUB          = int(15);                           (* ----                                                                                                           *)
    DOC_VECT_SAR          = int(16);                           (* >>>>                                                                                                           *)
    DOC_VECT_SAL          = int(17);                           (* <<<<                                                                                                           *)
    DOC_VECT_SHR          = int(18);                           (* >>>>>                                                                                                          *)
    DOC_VECT_G            = int(20);                           (* |>>|                                                                                                           *)
    DOC_VECT_GE           = int(21);                           (* |>=|                                                                                                           *)
    DOC_VECT_L            = int(22);                           (* |<<|                                                                                                           *)
    DOC_VECT_LE           = int(23);                           (* |<=|                                                                                                           *)
    DOC_VECT_E            = int(24);                           (* |==|                                                                                                           *)
    DOC_VECT_NE           = int(25);                           (* |!=|                                                                                                           *)
    DOC_VECT_MULS         = int(26);                           (* |**|                                                                                                           *)
    DOC_VECT_ADDS         = int(27);                           (* |++|                                                                                                           *)
    DOC_VECT_SUBS         = int(28);                           (* |--|                                                                                                           *)
    DOC_VECT_MULU         = int(29);                           (* #**#                                                                                                           *)
    DOC_VECT_ADDU         = int(30);                           (* #++#                                                                                                           *)
    DOC_VECT_SUBU         = int(31);                           (* #--#                                                                                                           *)
    DOC_SCAL_DIVU         = int(32);                           (* //                                                                                                             *)
    DOC_SCAL_REMU         = int(33);                           (* %%                                                                                                             *)
    DOC_SCAL_SAR          = int(34);                           (* >>                                                                                                             *)
    DOC_SCAL_SAL          = int(35);                           (* <<                                                                                                             *)
    DOC_SCAL_SHR          = int(36);                           (* >>>                                                                                                            *)
    DOC_SCAL_GE           = int(37);                           (* >=                                                                                                             *)
    DOC_SCAL_LE           = int(38);                           (* <=                                                                                                             *)
    DOC_END_OF_LINE       = int(39);                           (* конец строки                                                                                                   *)
    DOC_PARENTH_OPENED    = int(40);                           (* (                                                                                                              *)
    DOC_PARENTH_CLOSED    = int(41);                           (* )                                                                                                              *)
    DOC_BRACKET_OPENED    = int(42);                           (* [                                                                                                              *)
    DOC_BRACKET_CLOSED    = int(43);                           (* ]                                                                                                              *)
    DOC_CURLY_OPENED      = int(44);                           (* {                                                                                                              *)
    DOC_CURLY_CLOSED      = int(45);                           (* }                                                                                                              *)
    DOC_TAG_OPENED        = int(46);                           (* <                                                                                                              *)
    DOC_TAG_CLOSED        = int(47);                           (* >                                                                                                              *)
    DOC_EXCLAMATION_MARK  = int(48);                           (* !                                                                                                              *)
    DOC_VERTICAL_LINE     = int(49);                           (* |                                                                                                              *)
    DOC_AMPERSAND         = int(50);                           (* &                                                                                                              *)
    DOC_EQUAL             = int(51);                           (* =                                                                                                              *)
    DOC_TILDE             = int(52);                           (* ~                                                                                                              *)
    DOC_POUND_SIGN        = int(53);                           (* #                                                                                                              *)
    DOC_CIRCUMFLEX_ACCENT = int(54);                           (* ^                                                                                                              *)
    DOC_ASTERISK          = int(55);                           (* *                                                                                                              *)
    DOC_SOLIDUS           = int(56);                           (* /                                                                                                              *)
    DOC_PERCENT           = int(57);                           (* %                                                                                                              *)
    DOC_PLUS              = int(58);                           (* +                                                                                                              *)
    DOC_MINUS             = int(59);                           (* -                                                                                                              *)
    DOC_COMMA             = int(60);                           (* ,                                                                                                              *)
    DOC_PERIOD            = int(61);                           (* .                                                                                                              *)
    DOC_END_OF_PARAGRAPH  = int(62);                           (* конец абзаца                                                                                                   *)
    DOC_END               = int(63);                           (* конец документации                                                                                             *)

const { разрядности кода }
    BITS_32 = int(32);
    BITS_64 = int(64);

const { флаги }
    MASK_VISIBILITY   = int($0007);
    FLAG_PRIVATE      = AVT_PRIVATE;   { группа: видимость                                             }
    FLAG_SOURCE       = AVT_SOURCE;    { группа: видимость                                             }
    FLAG_PACKAGE      = AVT_PACKAGE;   { группа: видимость                                             }
    FLAG_PROTECTED    = AVT_PROTECTED; { группа: видимость                                             }
    FLAG_PUBLIC       = AVT_PUBLIC;    { группа: видимость                                             }
    FLAG_PUBLISHED    = AVT_PUBLISHED; { группа: видимость                                             }
    FLAG_ABSTRACT     = int($0008);    { группа: наследование                                          }
    FLAG_FINAL        = int($0010);    { группа: наследование                                          }
    FLAG_SERVICE      = int($0020);    { группа: тип                                                   }
    FLAG_STRUCT       = int($0040);    { группа: тип                                                   }
    FLAG_INTERFACE    = int($0060);    { группа: тип                                                   }
    FLAG_PRIMITIVE    = int($0080);    { группа: тип                                                   }
    FLAG_STATIC       = int($0100);    { группа: класс/объект                                          }
    FLAG_NATIVE       = int($0200);    { группа: детали реализации (отсутствуют у абстрактных методов) }
    FLAG_INTERRUPT    = int($0400);    { группа: детали реализации (отсутствуют у абстрактных методов) }
    FLAG_SYNCHRONIZED = int($0800);    { группа: детали реализации (отсутствуют у абстрактных методов) }
    FLAG_SYNTHETIC    = int($1000);    { группа: исходный код                                          }

const { типы значений лексем }
    TYPE_NONE    = int(0);
    TYPE_STRING  = int(1);
    TYPE_BOOLEAN = int(2);
    TYPE_INT     = int(3);
    TYPE_LONG    = int(4);
    TYPE_FLOAT   = int(5);
    TYPE_DOUBLE  = int(6);
    TYPE_REAL    = int(7);
    TYPE_BYTE    = int(8);
    TYPE_SHORT   = int(9);
    TYPE_CHAR    = int(10);

const { AVTSource.getLexemeInfo int[]–результат }
    LNFO_LTYPE = int(0);
    LNFO_VTYPE = int(1);
    LNFO_LINE  = int(2);
    LNFO_CHAR  = int(3);

const { AVTNode.setData }
    NO_LINE_INDEX = int(-1);

const { названия специальных методов }
    SPECNAME_INST_INIT  = AnsiString('<init>');
    SPECNAME_CLASS_INIT = AnsiString('<clinit>');

type
    AVTStorage = class;
    AVTStringStorage = class;
    AVTByte2Storage = class;
    AVTByte4Storage = class;
    AVTByte8Storage = class;
    AVTShort2Storage = class;
    AVTShort4Storage = class;
    AVTShort8Storage = class;
    AVTIntStorage = class;
    AVTInt2Storage = class;
    AVTInt4Storage = class;
    AVTInt8Storage = class;
    AVTLongStorage = class;
    AVTLong2Storage = class;
    AVTLong4Storage = class;
    AVTLong8Storage = class;
    AVTFloatStorage = class;
    AVTFloat2Storage = class;
    AVTFloat4Storage = class;
    AVTFloat8Storage = class;
    AVTDoubleStorage = class;
    AVTDouble2Storage = class;
    AVTDouble4Storage = class;
    AVTDouble8Storage = class;
    AVTRealStorage = class;
    AVTProgramme = class;
    AVTSource = class;
    AVTItem = class;
    AVTPackage = class;
    AVTItemExt = class;
    AVTType = class;
    AVTTypeInvalid = class;
    AVTTypePrimitive = class;
    AVTTypeStructured = class;
    AVTTypeArray = class;
    AVTMember = class;
    AVTField = class;
    AVTOverriddable = class;
    AVTMethod = class;
    AVTOperator = class;
    AVTSpecial = class;
    AVTInstInit = class;
    AVTClassInit = class;
    AVTProperty = class;
    AVTVariable = class;
    AVTConstant = class;
    AVTCode = class;
    AVTNode = class;
    AVTException = class;
    AVTCompilerException = class;
    AVTGlobalException = class;
    IllegalLexemeValueTypeException = class;

    AVTTypeStructured_Array1d = packed array of AVTTypeStructured;

    byte2 = packed array[0..1] of byte;
    byte4 = packed array[0..3] of byte;
    byte8 = packed array[0..7] of byte;
    short2 = packed array[0..1] of short;
    short4 = packed array[0..3] of short;
    short8 = packed array[0..7] of short;
    int2 = packed array[0..1] of int;
    int4 = packed array[0..3] of int;
    int8 = packed array[0..7] of int;
    long2 = packed array[0..1] of long;
    long4 = packed array[0..3] of long;
    long8 = packed array[0..7] of long;
    float2 = packed array[0..1] of float;
    float4 = packed array[0..3] of float;
    float8 = packed array[0..7] of float;
    double2 = packed array[0..1] of double;
    double4 = packed array[0..3] of double;
    double8 = packed array[0..7] of double;

    byte2_Array1d = packed array of byte2;
    byte4_Array1d = packed array of byte4;
    byte8_Array1d = packed array of byte8;
    short2_Array1d = packed array of short2;
    short4_Array1d = packed array of short4;
    short8_Array1d = packed array of short8;
    int2_Array1d = packed array of int2;
    int4_Array1d = packed array of int4;
    int8_Array1d = packed array of int8;
    long2_Array1d = packed array of long2;
    long4_Array1d = packed array of long4;
    long8_Array1d = packed array of long8;
    float2_Array1d = packed array of float2;
    float4_Array1d = packed array of float4;
    float8_Array1d = packed array of float8;
    double2_Array1d = packed array of double2;
    double4_Array1d = packed array of double4;
    double8_Array1d = packed array of double8;

    AVTValue = packed record { Не вносить изменений. Используется в программах, написанных на fasm }
        asString: UnicodeString;
        asClass: AVTType;
        isNull: boolean;
        __reserved0: packed array[$01..$17] of byte;
        case int of
        AVT_BOOLEAN: ( asBoolean: boolean );
        AVT_CHAR:    ( asChar: wchar );
        AVT_REAL:    ( asReal: real );
        AVT_BYTE:    ( asByte: byte );
        AVT_BYTE2:   ( asByte2: byte2 );
        AVT_BYTE4:   ( asByte4: byte4 );
        AVT_BYTE8:   ( asByte8: byte8 );
        AVT_SHORT:   ( asShort: short );
        AVT_SHORT2:  ( asShort2: short2 );
        AVT_SHORT4:  ( asShort4: short4 );
        AVT_SHORT8:  ( asShort8: short8 );
        AVT_INT:     ( asInt: int );
        AVT_INT2:    ( asInt2: int2 );
        AVT_INT4:    ( asInt4: int4 );
        AVT_INT8:    ( asInt8: int8 );
        AVT_LONG:    ( asLong: long );
        AVT_LONG2:   ( asLong2: long2 );
        AVT_LONG4:   ( asLong4: long4 );
        AVT_LONG8:   ( asLong8: long8 );
        AVT_FLOAT:   ( asFloat: float );
        AVT_FLOAT2:  ( asFloat2: float2 );
        AVT_FLOAT4:  ( asFloat4: float4 );
        AVT_FLOAT8:  ( asFloat8: float8 );
        AVT_DOUBLE:  ( asDouble: double );
        AVT_DOUBLE2: ( asDouble2: double2 );
        AVT_DOUBLE4: ( asDouble4: double4 );
        AVT_DOUBLE8: ( asDouble8: double8 );
    end;

    AVTStorage = class(_Object)
    protected
        fldLength: int;
    public
        property length: int read fldLength;
    end;

    AVTStringStorage = class(AVTStorage)
    protected
        fldArray: UnicodeString_Array1d; { * }
    public
        constructor create();
        function indexOf(const item: AnsiString): int; overload;
        function indexOf(const item: UnicodeString): int; overload;
        function indexAcquire(const item: AnsiString): int; overload;
        function indexAcquire(const item: UnicodeString): int; overload;
        function itemAt(index: int): UnicodeString;
        property item[index: int]: UnicodeString read itemAt; default;
    end;

    AVTByte2Storage = class(AVTStorage)
    public
        class function equals(const value0, value1: byte2): boolean; static; inline; overload;
    protected
        fldArray: byte2_Array1d;
    public
        constructor create();
        function indexOf(const item: byte2): int;
        function indexAcquire(const item: byte2): int;
        function itemAt(index: int) : byte2;
        property item[index: int]: byte2 read itemAt; default;
    end;

    AVTByte4Storage = class(AVTStorage)
    public
        class function equals(const value0, value1: byte4): boolean; static; inline; overload;
    protected
        fldArray: byte4_Array1d;
    public
        constructor create();
        function indexOf(const item: byte4): int;
        function indexAcquire(const item: byte4): int;
        function itemAt(index: int) : byte4;
        property item[index: int]: byte4 read itemAt; default;
    end;

    AVTByte8Storage = class(AVTStorage)
    public
        class function equals(const value0, value1: byte8): boolean; static; inline; overload;
    protected
        fldArray: byte8_Array1d;
    public
        constructor create();
        function indexOf(const item: byte8): int;
        function indexAcquire(const item: byte8): int;
        function itemAt(index: int) : byte8;
        property item[index: int]: byte8 read itemAt; default;
    end;

    AVTShort2Storage = class(AVTStorage)
    public
        class function equals(const value0, value1: short2): boolean; static; inline; overload;
    protected
        fldArray: short2_Array1d;
    public
        constructor create();
        function indexOf(const item: short2): int;
        function indexAcquire(const item: short2): int;
        function itemAt(index: int) : short2;
        property item[index: int]: short2 read itemAt; default;
    end;

    AVTShort4Storage = class(AVTStorage)
    public
        class function equals(const value0, value1: short4): boolean; static; inline; overload;
    protected
        fldArray: short4_Array1d;
    public
        constructor create();
        function indexOf(const item: short4): int;
        function indexAcquire(const item: short4): int;
        function itemAt(index: int) : short4;
        property item[index: int]: short4 read itemAt; default;
    end;

    AVTShort8Storage = class(AVTStorage)
    public
        class function equals(const value0, value1: short8): boolean; static; inline; overload;
    protected
        fldArray: short8_Array1d;
    public
        constructor create();
        function indexOf(const item: short8): int;
        function indexAcquire(const item: short8): int;
        function itemAt(index: int) : short8;
        property item[index: int]: short8 read itemAt; default;
    end;

    AVTIntStorage = class(AVTStorage)
    protected
        fldArray: int_Array1d; { * }
    public
        constructor create();
        function indexOf(const item: int): int;
        function indexAcquire(const item: int): int;
        function itemAt(index: int): int;
        property item[index: int]: int read itemAt; default;
    end;

    AVTInt2Storage = class(AVTStorage)
    public
        class function equals(const value0, value1: int2): boolean; static; inline; overload;
    protected
        fldArray: int2_Array1d;
    public
        constructor create();
        function indexOf(const item: int2): int;
        function indexAcquire(const item: int2): int;
        function itemAt(index: int) : int2;
        property item[index: int]: int2 read itemAt; default;
    end;

    AVTInt4Storage = class(AVTStorage)
    public
        class function equals(const value0, value1: int4): boolean; static; inline; overload;
    protected
        fldArray: int4_Array1d;
    public
        constructor create();
        function indexOf(const item: int4): int;
        function indexAcquire(const item: int4): int;
        function itemAt(index: int) : int4;
        property item[index: int]: int4 read itemAt; default;
    end;

    AVTInt8Storage = class(AVTStorage)
    public
        class function equals(const value0, value1: int8): boolean; static; inline; overload;
    protected
        fldArray: int8_Array1d;
    public
        constructor create();
        function indexOf(const item: int8): int;
        function indexAcquire(const item: int8): int;
        function itemAt(index: int) : int8;
        property item[index: int]: int8 read itemAt; default;
    end;

    AVTLongStorage = class(AVTStorage)
    protected
        fldArray: long_Array1d; { * }
    public
        constructor create();
        function indexOf(const item: long): int;
        function indexAcquire(const item: long): int;
        function itemAt(index: int): long;
        property item[index: int]: long read itemAt; default;
    end;

    AVTLong2Storage = class(AVTStorage)
    public
        class function equals(const value0, value1: long2): boolean; static; inline; overload;
    protected
        fldArray: long2_Array1d;
    public
        constructor create();
        function indexOf(const item: long2): int;
        function indexAcquire(const item: long2): int;
        function itemAt(index: int) : long2;
        property item[index: int]: long2 read itemAt; default;
    end;

    AVTLong4Storage = class(AVTStorage)
    public
        class function equals(const value0, value1: long4): boolean; static; inline; overload;
    protected
        fldArray: long4_Array1d;
    public
        constructor create();
        function indexOf(const item: long4): int;
        function indexAcquire(const item: long4): int;
        function itemAt(index: int) : long4;
        property item[index: int]: long4 read itemAt; default;
    end;

    AVTLong8Storage = class(AVTStorage)
    public
        class function equals(const value0, value1: long8): boolean; static; inline; overload;
    protected
        fldArray: long8_Array1d;
    public
        constructor create();
        function indexOf(const item: long8): int;
        function indexAcquire(const item: long8): int;
        function itemAt(index: int) : long8;
        property item[index: int]: long8 read itemAt; default;
    end;

    AVTFloatStorage = class(AVTStorage)
    protected
        fldArray: int_Array1d; { * }
    public
        constructor create();
        function indexOf(const item: float): int;
        function indexAcquire(const item: float): int;
        function itemAt(index: int): float;
        property item[index: int]: float read itemAt; default;
    end;

    AVTFloat2Storage = class(AVTStorage)
    public
        class function equals(const value0, value1: float2): boolean; static; inline; overload;
    protected
        fldArray: float2_Array1d;
    public
        constructor create();
        function indexOf(const item: float2): int;
        function indexAcquire(const item: float2): int;
        function itemAt(index: int) : float2;
        property item[index: int]: float2 read itemAt; default;
    end;

    AVTFloat4Storage = class(AVTStorage)
    public
        class function equals(const value0, value1: float4): boolean; static; inline; overload;
    protected
        fldArray: float4_Array1d;
    public
        constructor create();
        function indexOf(const item: float4): int;
        function indexAcquire(const item: float4): int;
        function itemAt(index: int) : float4;
        property item[index: int]: float4 read itemAt; default;
    end;

    AVTFloat8Storage = class(AVTStorage)
    public
        class function equals(const value0, value1: float8): boolean; static; inline; overload;
    protected
        fldArray: float8_Array1d;
    public
        constructor create();
        function indexOf(const item: float8): int;
        function indexAcquire(const item: float8): int;
        function itemAt(index: int) : float8;
        property item[index: int]: float8 read itemAt; default;
    end;

    AVTDoubleStorage = class(AVTStorage)
    protected
        fldArray: long_Array1d; { * }
    public
        constructor create();
        function indexOf(const item: double): int;
        function indexAcquire(const item: double): int;
        function itemAt(index: int): double;
        property item[index: int]: double read itemAt; default;
    end;

    AVTDouble2Storage = class(AVTStorage)
    public
        class function equals(const value0, value1: double2): boolean; static; inline; overload;
    protected
        fldArray: double2_Array1d;
    public
        constructor create();
        function indexOf(const item: double2): int;
        function indexAcquire(const item: double2): int;
        function itemAt(index: int) : double2;
        property item[index: int]: double2 read itemAt; default;
    end;

    AVTDouble4Storage = class(AVTStorage)
    public
        class function equals(const value0, value1: double4): boolean; static; inline; overload;
    protected
        fldArray: double4_Array1d;
    public
        constructor create();
        function indexOf(const item: double4): int;
        function indexAcquire(const item: double4): int;
        function itemAt(index: int) : double4;
        property item[index: int]: double4 read itemAt; default;
    end;

    AVTDouble8Storage = class(AVTStorage)
    public
        class function equals(const value0, value1: double8): boolean; static; inline; overload;
    protected
        fldArray: double8_Array1d;
    public
        constructor create();
        function indexOf(const item: double8): int;
        function indexAcquire(const item: double8): int;
        function itemAt(index: int) : double8;
        property item[index: int]: double8 read itemAt; default;
    end;

    AVTRealStorage = class(AVTStorage)
    protected
        fldArray: real_Array1d; { * }
    public
        constructor create();
        function indexOf(const item: real): int;
        function indexAcquire(const item: real): int;
        function itemAt(index: int): real;
        property item[index: int]: real read itemAt; default;
    end;

    AVTProgramme = class(_Object)
    private
        class procedure sort(const types: AVTTypeStructured_Array1d); static;
    public
        class function isSupportedAVX512ByCPU(): boolean; static;
        class function isSupportedAVX512ByOS(): boolean; static;
    private
        fldIsArraysPrefetched: boolean; { * }
        fldBits: int; { * }
        fldTypes: Vector; { * AVTTypeStructured }
        fldArrays: Vector; { * AVTTypeArray }
        fldSources: Hashtable; { * fileName:UnicodeString, AVTSource }
        fldPackages: Hashtable; { * fullName:AnsiString, AVTPackage }
        fldSystemPackage: AVTPackage; { * }
        procedure addArray(aarray: AVTTypeArray);
        procedure addSource(source: AVTSource);
        procedure addPackage(package: AVTPackage);
        procedure createArrays();
    public
        constructor create(bits: int = BITS_64);
        destructor destroy; override;
        procedure prefetchTypes();
        procedure prefetchArrays();
        function getType(const fullName: AnsiString): AVTType;
        function getArrayOf(elementType: AVTType): AVTTypeArray;
        function getPackage(const fullName: AnsiString): AVTPackage;
        function getSource(const fileName: UnicodeString): AVTSource;
        function packages(): Enumeration;
        function sources(): Enumeration;
        function arrays(): Enumeration;
        function types(): Enumeration;
        property bits: int read fldBits;
        property systemPackage: AVTPackage read fldSystemPackage;
    end;

    AVTSource = class(_Object)
    private
        class function buildLexeme(lineIndex, charIndex, lexemeType, lexemeValueType, lexemeValueIndex: int): long; static;
        class function extractLineIndex(lexeme: long): int; static;
        class function extractCharIndex(lexeme: long): int; static;
        class function extractLexemeType(lexeme: long): int; static;
        class function extractLexemeValueType(lexeme: long): int; static;
        class function extractLexemeValueIndex(lexeme: long): int; static;
    private
        { путь, строки, программа: }
        fldFileName: UnicodeString; { * }
        fldSimpleName: UnicodeString; { * }
        fldLines: UnicodeString_Array1d;
        fldParentProgramme: AVTProgramme; { * }
        { лексемы: }
        fldAmbiguousName: boolean;
        fldPosition: int;
        fldLexemesCount: int;
        fldLexemes: long_Array1d;
        fldStrings: AVTStringStorage;
        fldInts: AVTIntStorage;
        fldLongs: AVTLongStorage;
        fldFloats: AVTFloatStorage;
        fldDoubles: AVTDoubleStorage;
        fldReals: AVTRealStorage;
        { содержимое: }
        fldPackage: AVTPackage;
        fldImportedAll: Vector; { AVTItem }
        fldImportedTypes: Hashtable; { simpleName:AnsiString, AVTTypeStructured }
        fldDeclaredTypesAsVector: Vector; { * AVTTypeStructured }
        fldDeclaredTypesAsTable: Hashtable; { * simpleName:AnsiString, AVTTypeStructured }
        procedure setPackage(package: AVTPackage);
        procedure addDeclaredType(atype: AVTTypeStructured);
        procedure addLexemeInternal(lineIndex, charIndex, lexemeType, lexemeValueType, lexemeValueIndex: int);
        function getLexemeValueTypeInternal(lexeme: long): int;
        function getLength(): int;
        function getLine(index: int): UnicodeString;
        function getStrings(): AVTStringStorage;
        function getInts(): AVTIntStorage;
        function getLongs(): AVTLongStorage;
        function getFloats(): AVTFloatStorage;
        function getDoubles(): AVTDoubleStorage;
        function getReals(): AVTRealStorage;
    public
        constructor create(); overload;
        constructor create(parentProgramme: AVTProgramme; const fileName: UnicodeString); overload;
        destructor destroy; override;
        procedure afterConstruction(); override;
        procedure realize(const lines: UnicodeString_Array1d); overload;
        procedure realize(vfs: ReadOnlyVirtualFileSystem; const directory: UnicodeString); overload;
        procedure addImportedPackage(package: AVTPackage);
        procedure addImportedType(atype: AVTTypeStructured);
        procedure addLexeme(lineIndex, charIndex, lexemeType: int);
        procedure addLexemeBoolean(lineIndex, charIndex, lexemeType: int; const lexemeValue: boolean);
        procedure addLexemeChar(lineIndex, charIndex, lexemeType: int; const lexemeValue: wchar);
        procedure addLexemeByte(lineIndex, charIndex, lexemeType: int; const lexemeValue: byte);
        procedure addLexemeShort(lineIndex, charIndex, lexemeType: int; const lexemeValue: short);
        procedure addLexemeInt(lineIndex, charIndex, lexemeType: int; const lexemeValue: int);
        procedure addLexemeLong(lineIndex, charIndex, lexemeType: int; const lexemeValue: long);
        procedure addLexemeFloat(lineIndex, charIndex, lexemeType: int; const lexemeValue: float);
        procedure addLexemeDouble(lineIndex, charIndex, lexemeType: int; const lexemeValue: double);
        procedure addLexemeReal(lineIndex, charIndex, lexemeType: int; const lexemeValue: real);
        procedure addLexemeAnsiString(lineIndex, charIndex, lexemeType: int; const lexemeValue: AnsiString);
        procedure addLexemeUnicodeString(lineIndex, charIndex, lexemeType: int; const lexemeValue: UnicodeString);
        function getLexemeInfo(position: int): int_Array1d;
        function getLexemeType(position: int): int;
        function getLexemeValueType(position: int): int;
        function getLexemeLineIndex(position: int): int;
        function getLexemeCharIndex(position: int): int;
        function getLexemeBoolean(position: int): boolean;
        function getLexemeChar(position: int): wchar;
        function getLexemeByte(position: int): int;
        function getLexemeShort(position: int): int;
        function getLexemeInt(position: int): int;
        function getLexemeLong(position: int): long;
        function getLexemeFloat(position: int): float;
        function getLexemeDouble(position: int): double;
        function getLexemeReal(position: int): real;
        function getLexemeAnsiString(position: int): AnsiString;
        function getLexemeUnicodeString(position: int): UnicodeString;
        function getLexemesCount(): int;
        function getDeclaredType(const simpleName: AnsiString): AVTTypeStructured;
        function getImportedType(const simpleName: AnsiString): AVTTypeStructured;
        function findImportedType(const simpleName: AnsiString): AVTTypeStructured; overload;
        function findImportedType(const simpleName: AnsiString; from: AVTTypeStructured; position: int): AVTTypeStructured; overload;
        function isImportedPackage(package: AVTPackage): boolean;
        function importedItems(): Enumeration;
        function declaredTypes(): Enumeration;
        property fileName: UnicodeString read fldFileName;
        property simpleName: UnicodeString read fldSimpleName;
        property parentProgramme: AVTProgramme read fldParentProgramme;
        property package: AVTPackage read fldPackage write setPackage;
        property ambiguousName: boolean read fldAmbiguousName write fldAmbiguousName;
        property position: int read fldPosition write fldPosition;
        property length: int read getLength;
        property line[index: int]: UnicodeString read getLine; default;
    end;

    AVTItem = class(_Object)
    private
        fldFlags: int; { * }
        fldSimpleName: AnsiString; { * }
        fldFullName: AnsiString; { * }
        fldDocumentation: UnicodeString; { * }
        fldParentItem: AVTItem; { * }
        function getVisibility(): int;
    protected
        function getFullName(): AnsiString; virtual; abstract;
    public
        constructor create(parentItem: AVTItem; flags: int; const simpleName: AnsiString; const documentation: UnicodeString = '');
        procedure afterConstruction(); override;
        function toString(): AnsiString; override;
        function isStatic(): boolean;
        function isFinal(): boolean;
        function isAbstract(): boolean;
        function isSynthetic(): boolean;
        property flags: int read fldFlags;
        property visibility: int read getVisibility;
        property fullName: AnsiString read fldFullName;
        property simpleName: AnsiString read fldSimpleName;
        property documentation: UnicodeString read fldDocumentation;
        property parentItem: AVTItem read fldParentItem;
    end;

    AVTPackage = class(AVTItem)
    private
        fldSources: Hashtable; { * fileName:UnicodeString, AVTSource }
        fldSubpackages: Hashtable; { simpleName:AnsiString, AVTPackage }
        fldTypesAsTable: Hashtable; { * simpleName:AnsiString, AVTType }
        fldTypesAsVector: Vector; { * AVTType }
        fldParentPackage: AVTPackage; { * }
        fldParentProgramme: AVTProgramme; { * }
        procedure addType(atype: AVTType);
        procedure addSource(source: AVTSource);
        procedure addSubpackage(subpackage: AVTPackage);
    protected
        function getFullName(): AnsiString; override;
    public
        constructor create(parentProgramme: AVTProgramme; parentPackage: AVTPackage; const simpleName: AnsiString; const documentation: UnicodeString = '');
        destructor destroy; override;
        procedure afterConstruction(); override;
        function getSubpackage(const simpleName: AnsiString): AVTPackage;
        function getSource(const fileName: UnicodeString): AVTSource;
        function getType(const simpleName: AnsiString; caseSensitive: boolean = true): AVTType;
        function subpackages(): Enumeration;
        function sources(): Enumeration;
        function types(): Enumeration;
        property parentProgramme: AVTProgramme read fldParentProgramme;
        property parentPackage: AVTPackage read fldParentPackage;
    end;

    AVTItemExt = class(AVTItem)
    private
        fldImplementationPosition: int; { * }
        fldDeclarationPosition: int; { * }
        fldAvtcType: AnsiString; { * }
        fldFasmFullName: AnsiString; { * }
        fldFasmShortName: AnsiString; { * }
        fldSource: AVTSource; { * }
    protected
        function getFullName(): AnsiString; override;
        function getAvtcType(): AnsiString; virtual;
        function getFasmFullName(): AnsiString; virtual; abstract;
        function getFasmShortName(): AnsiString; virtual;
    public
        constructor create(parentItem: AVTItem; flags: int; const simpleName: AnsiString; source: AVTSource = nil; declarationPosition: int = -1; const documentation: UnicodeString = '');
        procedure afterConstruction(); override;
        function isVisible(target, from: AVTTypeStructured): boolean; virtual;
        property implementationPosition: int read fldImplementationPosition write fldImplementationPosition; { На будущее: должны быть два свойства: implementationBeginPosition и implementationEndPosition }
        property declarationPosition: int read fldDeclarationPosition;
        property fasmShortName: AnsiString read fldFasmShortName;
        property fasmFullName: AnsiString read fldFasmFullName;
        property avtcType: AnsiString read fldAvtcType;
        property source: AVTSource read fldSource;
    end;

    AVTType = class(AVTItemExt)
    private
        fldFieldWidth: int; { * }
        fldFasmArgument: AnsiString; { * }
        fldPackage: AVTPackage; { * }
    protected
        function getFieldWidth(): int; virtual; abstract;
        function getFasmFullName(): AnsiString; override; abstract;
        function getFasmArgument(): AnsiString; virtual; abstract;
    public
        constructor create(parentItem: AVTItem; flags: int; const simpleName: AnsiString; source: AVTSource = nil; declarationPosition: int = -1; const documentation: UnicodeString = '');
        procedure afterConstruction(); override;
        function getCommonType(anot: AVTType): AVTType; virtual; abstract;
        { В будущих версиях getCommonType разделится на два метода:
        function getArithmeticCommonType(anot: AVTType): AVTType; virtual; abstract; - для арифметических операций (char + char = int)
        function getTernaryCommonType(anot: AVTType): AVTType; virtual; abstract; - для тернарных операций (boolean ? char : char = char, а не int) }
        function isVisible(target, from: AVTTypeStructured): boolean; override;
        function isConvertableFrom(from: AVTType): boolean; virtual; abstract;
        function isAssignableFrom(from: AVTType): boolean; virtual; abstract;
        function isPrimitive(): boolean; virtual;
        function isStackable(): boolean; virtual;
        function isBoolean(): boolean; virtual;
        function isInt(): boolean; virtual;
        function isNumeric(): boolean; virtual;
        function isCompound(): boolean; virtual;
        function isInterface(): boolean; virtual;
        function isService(): boolean; virtual;
        function isStruct(): boolean; virtual;
        function isClass(): boolean; virtual;
        function isArray(): boolean; virtual;
        function isVoid(): boolean; virtual;
        function isDword(): boolean; virtual;
        function isQword(): boolean; virtual;
        function isTword(): boolean; virtual;
        function isXword(): boolean; virtual;
        function isYword(): boolean; virtual;
        function isZword(): boolean; virtual;
        property fieldWidth: int read fldFieldWidth;
        property fasmArgumentName: AnsiString read fldFasmArgument;
        property package: AVTPackage read fldPackage;
        { В будущих версиях:
        function compatibleWith(anot: AVTType): boolean; virtual; abstract; (* для использования в findDuplicateMembers, a.compatibleWith(b) ≡ b.compatibleWith(a) *)
        function isIntegerVector(): boolean; virtual;
        function isFloatVector(): boolean; virtual;
        function toStackable(): AVTType; virtual; }
    end;

    AVTTypeInvalid = class(AVTType)
    private
        class var instance: AVTTypeInvalid;
    public
        class function getInstance(): AVTTypeInvalid; static;
    protected
        function getFieldWidth(): int; override;
        function getFasmFullName(): AnsiString; override;
        function getFasmArgument(): AnsiString; override;
    public
        constructor create();
        function getCommonType(anot: AVTType): AVTType; override;
        function isConvertableFrom(from: AVTType): boolean; override;
        function isAssignableFrom(from: AVTType): boolean; override;
    end;

    AVTTypePrimitive = class(AVTType)
    public
        class function getName(primitiveKind: int): AnsiString; static;
    private
        fldPrimitiveKind: int; { * }
        function getCompoundBase(): int;
        function getCompoundLength(): int;
    protected
        function getFieldWidth(): int; override;
        function getAvtcType(): AnsiString; override;
        function getFasmFullName(): AnsiString; override;
        function getFasmArgument(): AnsiString; override;
    public
        constructor create(parentPackage: AVTPackage; primitiveKind: int);
        function getCommonType(anot: AVTType): AVTType; override;
        function isConvertableFrom(from: AVTType): boolean; override;
        function isAssignableFrom(from: AVTType): boolean; override;
        function isPrimitive(): boolean; override;
        function isStackable(): boolean; override;
        function isBoolean(): boolean; override;
        function isInt(): boolean; override;
        function isNumeric(): boolean; override;
        function isCompound(): boolean; override;
        function isVoid(): boolean; override;
        function isDword(): boolean; override;
        function isQword(): boolean; override;
        function isTword(): boolean; override;
        function isXword(): boolean; override;
        function isYword(): boolean; override;
        function isZword(): boolean; override;
        property compoundBase: int read getCompoundBase;
        property compoundLength: int read getCompoundLength;
        property primitiveKind: int read fldPrimitiveKind;
    end;

    AVTTypeStructured = class(AVTType)
    private type
        SuperEnumerator = class;
        ExtendsEnumerator = class;
        MemberEnumerator = class;
        SuperEnumerator = class(RefCountInterfacedObject, Enumeration)
        private
            superClasses: boolean;
            all: boolean;
            index: int;
            currType: AVTTypeStructured;
            thisType: AVTTypeStructured;
            procedure next();
        public
            constructor create(thisType: AVTTypeStructured; all: boolean);
            function hasMoreElements(): boolean;
            function nextElement(): Value;
        end;
        ExtendsEnumerator = class(RefCountInterfacedObject, Enumeration)
        private
            currType: AVTTypeStructured;
        public
            constructor create(extends: AVTTypeStructured);
            function hasMoreElements(): boolean;
            function nextElement(): Value;
        end;
        MemberEnumerator = class(RefCountInterfacedObject, Enumeration)
        private
            current: AVTMember;
        public
            constructor create(first: AVTMember);
            function hasMoreElements(): boolean;
            function nextElement(): Value;
        end;
    public type
        Overridden = class;
        SuperType = class;
        Overridden = class(_Object)
        private
            fldThisMember: AVTOverriddable; { * }
            fldSuperMember: AVTOverriddable; { * }
        public
            constructor create(thisMember, superMember: AVTOverriddable);
            property thisMember: AVTOverriddable read fldThisMember;
            property superMember: AVTOverriddable read fldSuperMember;
        end;
        SuperType = class(_Object)
        private
            fldDeclarationPosition: int; { * }
            fldOverriddenList: Vector; { * Overridden }
            fldThisReference: AVTTypeStructured; { * }
            fldSuperReference: AVTTypeStructured; { * }
            procedure addOverridden(thisMember, superMember: AVTOverriddable);
        public
            constructor create(thisReference, superReference: AVTTypeStructured; declarationPosition: int);
            destructor destroy; override;
            function getThisMember(superMember: AVTOverriddable): AVTOverriddable;
            function getSuperMember(thisMember: AVTOverriddable): AVTOverriddable;
            function overriddenMembers(): Enumeration;
            property declarationPosition: int read fldDeclarationPosition;
            property thisReference: AVTTypeStructured read fldThisReference;
            property superReference: AVTTypeStructured read fldSuperReference;
        end;
    private
        fldFromLibrary: boolean; { * }
        fldInstanceSize: int;
        fldStructureSize: int;
        fldExtends: SuperType;
        fldImplementsAsVector: Vector; { SuperType }
        fldImplementsAsTable: Hashtable; { superReference:AVTTypeStructured, SuperType }
        fldMembersAsTable: Hashtable; { * simpleName:AnsiString, AVTMember }
        fldMembersAsVector: Vector; { * AVTMember }
        fldVirtualMethods: Vector; { AVTMethod }
        fldServiceMethods: Vector; { AVTMethod }
        procedure appendMethodsTo(methodList: Vector; const methodName: AnsiString); overload;
        procedure appendMethodsTo(methodList: Vector; const methodName: AnsiString; argumentsCount: int); overload;
        procedure checkImplements();
        procedure addMember(member: AVTMember);
        procedure findOverriddenInSuperClass(extends: AVTTypeStructured);
        procedure findDuplicateMembers();
        procedure checkOverridden();
        procedure checkAbstract();
        function hasAbstractMembers(): boolean;
        function hasOverriddable(member: AVTOverriddable; onlyInSelf: boolean = false): boolean;
        function getVirtualMethodsCount(): int;
        function getServiceMethodsCount(): int;
        function getVirtualMethod(index: int): AVTMethod;
        function getServiceMethod(index: int): AVTMethod;
    protected
        procedure prefetchImplements(); virtual;
        procedure defineFieldOffsets(extends: AVTTypeStructured); virtual;
        procedure insertAbstractMembers(extends: AVTTypeStructured); virtual;
        procedure insertDefaultConstructor(extends: AVTTypeStructured); virtual;
        function getFieldWidth(): int; override;
        function getFullName(): AnsiString; override;
        function getAvtcType(): AnsiString; override;
        function getFasmFullName(): AnsiString; override;
        function getFasmArgument(): AnsiString; override;
    public
        constructor create(parentItem: AVTItem; fromLibrary: boolean; flags: int; const simpleName: AnsiString; source: AVTSource; declarationPosition: int = -1; const documentation: UnicodeString = '');
        destructor destroy; override;
        procedure afterConstruction(); override;
        procedure prefetchMembers();
        procedure prefetchIndices();
        procedure setExtends(atype: AVTTypeStructured; declarationPosition: int = -1);
        procedure addImplements(atype: AVTTypeStructured; declarationPosition: int = -1);
        function getImplements(atype: AVTTypeStructured): SuperType;
        function getMember(const simpleName: AnsiString): AVTMember;
        function getCommonType(anot: AVTType): AVTType; override;
        function isImplements(atype: AVTTypeStructured): boolean;
        function isConvertableFrom(from: AVTType): boolean; override;
        function isAssignableFrom(from: AVTType): boolean; override;
        function isStackable(): boolean; override;
        function isInterface(): boolean; override;
        function isService(): boolean; override;
        function isStruct(): boolean; override;
        function isClass(): boolean; override;
        function virtualMethods(): Enumeration;
        function serviceMethods(): Enumeration;
        function implementsAll(): Enumeration;
        function implements(): Enumeration;
        function extendsAll(): Enumeration;
        function extends(): AVTTypeStructured;
        function members(): Enumeration; overload;
        function members(const simpleName: AnsiString): Enumeration; overload;
        function findField(const simpleName: AnsiString; from: AVTTypeStructured; position: int): AVTMember;
        function findMethod(const simpleName: AnsiString; argumentTypes: Vector; from: AVTTypeStructured; position: int): AVTMethod;
        property fromLibrary: boolean read fldFromLibrary;
        property instanceSize: int read fldInstanceSize;
        property structureSize: int read fldStructureSize;
        property virtualMethodsCount: int read getVirtualMethodsCount;
        property serviceMethodsCount: int read getServiceMethodsCount;
        property virtualMethod[index: int]: AVTMethod read getVirtualMethod;
        property serviceMethod[index: int]: AVTMethod read getServiceMethod;
    end;

    AVTTypeArray = class(AVTTypeStructured)
    private
        fldCompilable: boolean; { * }
        fldDimensionsCount: int; { * }
        fldElementType: AVTType; { * }
        fldCellType: AVTType; { * }
    protected
        procedure prefetchImplements(); override;
        procedure insertDefaultConstructor(extends: AVTTypeStructured); override;
        function getFullName(): AnsiString; override;
        function getAvtcType(): AnsiString; override;
        function getFasmFullName(): AnsiString; override;
        function getFasmArgument(): AnsiString; override;
    public
        constructor create(elementType: AVTType);
        procedure afterConstruction(); override;
        procedure makeCompilable();
        function isAssignableFrom(from: AVTType): boolean; override;
        function isArray(): boolean; override;
        property compilable: boolean read fldCompilable;
        property dimensionsCount: int read fldDimensionsCount;
        property elementType: AVTType read fldElementType;
        property cellType: AVTType read fldCellType;
    end;

    AVTMember = class(AVTItemExt)
    private
        class function getSource(item: AVTItemExt): AVTSource;
    private
        fldPrev: AVTMember;
        fldNext: AVTMember;
        fldParentType: AVTTypeStructured; { * }
    protected
        function getFullName(): AnsiString; override;
        function getFasmFullName(): AnsiString; override;
        function getFasmShortName(): AnsiString; override;
    public
        constructor create(parentType: AVTTypeStructured; flags: int; const simpleName: AnsiString; declarationPosition: int = -1; const documentation: UnicodeString = '');
        procedure afterConstruction(); override;
        function isVisible(target, from: AVTTypeStructured): boolean; override;
        property parentType: AVTTypeStructured read fldParentType;
    end;

    AVTField = class(AVTMember)
    private
        fldValueConstCreated: boolean;
        fldValueConstCreating: boolean;
        fldLength: int; { * }
        fldInstanceOffset: int;
        fldStructureOffset: int;
        fldFasmStructName: AnsiString; { * }
        fldValueType: AVTType; { * }
        fldValueConst: AVTConstant;
    protected
        function getAvtcType(): AnsiString; override;
    public
        constructor create(parentType: AVTTypeStructured; flags: int; valueType: AVTType; length: int; const simpleName: AnsiString; declarationPosition: int = -1; const documentation: UnicodeString = '');
        destructor destroy; override;
        procedure afterConstruction(); override;
        procedure makeValueConstCreated();
        procedure makeValueConstCreating();
        function createValueConst(): AVTConstant;
        property valueConstCreated: boolean read fldValueConstCreated;
        property valueConstCreating: boolean read fldValueConstCreating;
        property length: int read fldLength;
        property instanceOffset: int read fldInstanceOffset;
        property structureOffset: int read fldStructureOffset;
        property fasmStructName: AnsiString read fldFasmStructName;
        property valueConst: AVTConstant read fldValueConst;
        property valueType: AVTType read fldValueType;
    end;

    AVTOverriddable = class(AVTMember)
    private type
        OverriddenEnumerator = class;
        OverriddenEnumerator = class(RefCountInterfacedObject, Enumeration)
        private
            index: int;
            thisMember: AVTOverriddable;
            superMember: AVTOverriddable;
            procedure next();
        public
            constructor create(thisMember: AVTOverriddable);
            function hasMoreElements(): boolean;
            function nextElement(): Value;
        end;
    private
        fldOverridden: boolean;
    protected
        function isOverriddable(member: AVTOverriddable): boolean; virtual;
    public
        procedure findOverriddenMembers(); virtual;
        function isOverridden(): boolean;
        function isOverride(member: AVTOverriddable): boolean; virtual;
        function isTypeOverriddable(member: AVTOverriddable): boolean; virtual; abstract;
        function mismatchThrows(member: AVTOverriddable): AVTTypeStructured; virtual;
        function overriddenMembers(): Enumeration; virtual;
    end;

    AVTMethod = class(AVTOverriddable)
    private
        fldWithNumber: int;
        fldVirtualIndex: int;
        fldServiceIndex: int;
        fldMonitorNumber: int;
        fldThrowsPosition: int;
        fldDebugInfoLength: int;
        fldArgumentsAsString: AnsiString;
        fldReturnType: AVTType; { * }
        fldArgumentThis: AVTVariable; { * }
        fldArgumentsAsVector: Vector; { * AVTVariable }
        fldArgumentsAsTable: Hashtable; { * simpleName:AnsiString, AVTVariable }
        fldThrows: Vector; { AVTTypeStructured }
        fldCode: AVTCode; { * }
        fldLinkedProperty: AVTProperty; { * }
        fldDebugInfoLineNumbers: int_Array1d; { * }
        function containsIn(methodList: Vector): boolean;
    protected
        function isOverriddable(member: AVTOverriddable): boolean; override;
        function getFullName(): AnsiString; override;
        function getAvtcType(): AnsiString; override;
        function getFasmFullName(): AnsiString; override;
        function getFasmShortName(): AnsiString; override;
        function getFasmSimpleName(): AnsiString; virtual;
    public
        constructor create(parentType: AVTTypeStructured; flags: int; returnType: AVTType; const simpleName: AnsiString; arguments: Vector; declarationPosition: int = -1; throwsPosition: int = -1; const documentation: UnicodeString = '');
        destructor destroy; override;
        procedure addThrows(exceptionClass: AVTTypeStructured);
        function isTypeOverriddable(member: AVTOverriddable): boolean; override;
        function isIdentityArguments(arguments: Vector): boolean; overload;
        function isIdentityArguments(method: AVTMethod): boolean; overload;
        function isIdentityArgumentTypes(argumentTypes: Vector): boolean;
        function isConvertableArgumentTypes(argumentTypes: Vector): boolean;
        function isThrows(exceptionClass: AVTTypeStructured): boolean;
        function mightThrown(exceptionClass: AVTTypeStructured): boolean; overload;
        function mightThrown(): boolean; overload;
        function mismatchThrows(member: AVTOverriddable): AVTTypeStructured; override;
        function argumentsToString(): AnsiString;
        function getArgument(const name: AnsiString): AVTVariable;
        function getArgumentAt(index: int): AVTVariable;
        function getArgumentsCount(): int;
        function getDebugInfoLength(): int;
        function getDebugInfoLineNumber(labelIndex: int): int;
        function addDebugInfoLineNumber(lineNumber: int): int;
        function createWithVariable(valueType: AVTTypeStructured): AVTVariable;
        function createMonitorVariable(valueType: AVTTypeStructured): AVTVariable;
        function arguments(): Enumeration;
        function throws(): Enumeration;
        property code: AVTCode read fldCode;
        property virtualIndex: int read fldVirtualIndex;
        property serviceIndex: int read fldServiceIndex;
        property returnType: AVTType read fldReturnType;
        property throwsPosition: int read fldThrowsPosition;
        property argumentThis: AVTVariable read fldArgumentThis;
        property linkedProperty: AVTProperty read fldLinkedProperty;
    end;

    AVTOperator = class(AVTMethod) { не имеет throws }
    public
        class function operatorToChar(operatorKind: int): AnsiString; static;
        class function operatorToName(operatorKind: int): AnsiString; static;
        class function operatorToSpecName(operatorKind: int): AnsiString; static;
        class function specNameToOperator(const operatorName: AnsiString): int; static;
    private
        fldOperatorKind: int; { * }
    protected
        function getFullName(): AnsiString; override;
        function getFasmSimpleName(): AnsiString; override;
    public
        constructor create(parentType: AVTTypeStructured; flags: int; returnType: AVTType; operatorKind: int; arguments: Vector; declarationPosition: int = -1; const documentation: UnicodeString = '');
        property operatorKind: int read fldOperatorKind;
    end;

    AVTSpecial = class(AVTMethod)
    public
        procedure findOverriddenMembers(); override;
        function isOverride(member: AVTOverriddable): boolean; override;
        function overriddenMembers(): Enumeration; override;
    end;

    AVTInstInit = class(AVTSpecial)
    protected
        function getFasmSimpleName(): AnsiString; override;
    public
        constructor create(parentType: AVTTypeStructured; visibility: int; arguments: Vector; declarationPosition: int = -1; throwsPosition: int = -1; const documentation: UnicodeString = '');
    end;

    AVTClassInit = class(AVTSpecial) { не имеет throws }
    protected
        function getFasmSimpleName(): AnsiString; override;
    public
        constructor create(parentType: AVTTypeStructured; declarationPosition: int = 0);
    end;

    AVTProperty = class(AVTOverriddable)
    private
        fldHasIndex: boolean;
        fldReadIsConst: boolean;
        fldStoredIsConst: boolean;
        fldIndex: int;
        fldValueType: AVTType; { * }
        fldReadMember: _Object;
        fldWriteMember: _Object;
        fldStoredMember: _Object;
        fldReadSynthetic: AVTMethod;
        fldWriteSynthetic: AVTMethod;
        fldStoredSynthetic: AVTMethod;
        procedure setIndex(index: int);
        procedure setReadMember(member: _Object);
        procedure setWriteMember(member: _Object);
        procedure setStoredMember(member: _Object);
        procedure createReadSynthetic();
        procedure createWriteSynthetic();
        procedure createStoredSynthetic();
    protected
        function isOverriddable(member: AVTOverriddable): boolean; override;
        function getAvtcType(): AnsiString; override;
    public
        constructor create(parentType: AVTTypeStructured; flags: int; valueType: AVTType; const simpleName: AnsiString; declarationPosition: int = -1; const documentation: UnicodeString = '');
        destructor destroy; override;
        function isTypeOverriddable(member: AVTOverriddable): boolean; override;
        property valueType: AVTType read fldValueType;
        property hasIndex: boolean read fldHasIndex;
        property index: int read fldIndex write setIndex;
        property readMember: _Object read fldReadMember write setReadMember;
        property writeMember: _Object read fldWriteMember write setWriteMember;
        property storedMember: _Object read fldStoredMember write setStoredMember;
        property readSynthetic: AVTMethod read fldReadSynthetic;
        property writeSynthetic: AVTMethod read fldWriteSynthetic;
        property storedSynthetic: AVTMethod read fldStoredSynthetic;
    end;

    AVTVariable = class(AVTItemExt)
    private
        fldValueType: AVTType; { * }
    protected
        function getFasmFullName(): AnsiString; override;
        function getFasmShortName(): AnsiString; override;
    public
        constructor create(valueType: AVTType; const simpleName: AnsiString; source: AVTSource = nil; declarationPosition: int = -1);
        property valueType: AVTType read fldValueType;
    end;

    AVTConstant = class(_Object) { Не вносить изменений. Используется в программах, написанных на fasm }
    private
        fldValueType: AVTType; { * }
    public
        constructor create(valueType: AVTType); overload;
        procedure assignValue(from: AVTConstant);
        procedure assign(from: AVTConstant);
        procedure clear();
        function isDefaultValue(): boolean;
        property valueType: AVTType read fldValueType write fldValueType;
    public
        value: AVTValue; { * }
    end;

    AVTCode = class(_Object, DataHolder, DataEncoder)
    private
        fldShortCodesLength: int;
        fldShortCodes: short_Array1d; { * }
        fldInstructions: Vector; { * AVTNode }
        fldNodes: Vector; { * AVTNode }
        fldRoot: AVTNode; { * }
        fldParentMethod: AVTMethod; { * }
        function getLength(): int;
        function getInstruction(order: int): AVTNode;
    public
        constructor create(parentMethod: AVTMethod);
        destructor destroy; override;
        procedure moveNode(node: AVTNode; index: int); overload;
        procedure moveNode(node, parent: AVTNode; index: int); overload;
        procedure replaceNode(oldNode, newNode: AVTNode);
        procedure assignInstructionOrder(node: AVTNode; order: int);
        procedure clearInstructionOrder(node: AVTNode);
        procedure writeShortCode();
        procedure write(shortCode: int); overload;
        procedure write(const src: short_Array1d); overload;
        procedure write(const src: short_Array1d; offset, length: int); overload;
        procedure saveToDataOutputStream(stream: DataOutput);
        procedure saveToOutputStream(stream: Output);
        procedure clear();
        function isEmpty(): boolean;
        function isHasJumpsTo(node: AVTNode): boolean;
        function nodes(): Enumeration;
        function instructions(): Enumeration;
        function removeNode(node: AVTNode): boolean;
        function appendNode(parent: AVTNode = nil): AVTNode; overload;
        function appendNode(parent: AVTNode; lineIndex: int; dataType: AVTType; instruction: int; operand1: _Object = nil; operand2: _Object = nil): AVTNode; overload;
        function insertNode(parent: AVTNode = nil; index: int = 0): AVTNode; overload;
        function insertNode(parent: AVTNode; index: int; lineIndex: int; dataType: AVTType; instruction: int; operand1: _Object = nil; operand2: _Object = nil): AVTNode; overload;
        function minInstructionOrder(node: AVTNode): int; { перенести в AVTNode  }
        function maxInstructionOrder(node: AVTNode): int; { и сделать свойствами }
        property root: AVTNode read fldRoot;
        property parentMethod: AVTMethod read fldParentMethod;
        property shortCodesLength: int read fldShortCodesLength;
        property length: int read getLength;
        property instruction[order: int]: AVTNode read getInstruction; default;
    end;

    AVTNode = class(_Object)
    private
        { узел: }
        fldOrder: int; { * }
        fldIndex: int; { * }
        fldParent: AVTNode; { * }
        fldChilds: Vector; { AVTNode }
        fldCode: AVTCode; { * }
        { данные: }
        fldOp1IsOwned: boolean;
        fldOp2IsOwned: boolean;
        fldLabelNumber: int; { * }
        fldLineIndex: int;
        fldInstruction: int;
        fldOperand1: _Object;
        fldOperand2: _Object;
        fldDataType: AVTType;
        fldJumpCase: Hashtable; { value:int, AVTNode }
        fldJumpDefault: AVTNode;
        fldShortCode: short_Array1d;
        procedure insertChild(index: int; child: AVTNode);
        procedure deleteChild(index: int);
        procedure setInstruction(value: int);
        procedure setOperand1(value: _Object);
        procedure setOperand2(value: _Object);
        function isOp1IsOwned(): boolean;
        function isOp2IsOwned(): boolean;
        function getLength(): int;
        function getChild(index: int): AVTNode;
    public
        constructor create(code: AVTCode; parent: AVTNode; index: int);
        destructor destroy; override;
        procedure setData(lineIndex: int; dataType: AVTType; instruction: int; operand1: _Object = nil; operand2: _Object = nil);
        procedure setBooleanJump(jumpIsFalse, jumpIsTrue: AVTNode);
        procedure jumpCaseSetNode(caseValue: int; caseNode: AVTNode = nil);
        function jumpCaseGetNode(caseValue: int): AVTNode;
        function jumpCaseValues(): Enumeration;
        function childs(): Enumeration;
        function firstChild(): AVTNode;
        function lastChild(): AVTNode;
        function isLoadNull(): boolean;
        function isWithVariable(): boolean;
        function isParent(node: AVTNode): boolean;
        function isJumpTo(node: AVTNode): boolean;
        property jumpDefault: AVTNode read fldJumpDefault write fldJumpDefault;
        property jumpIsFalse: AVTNode index 0 read jumpCaseGetNode;
        property jumpIsTrue: AVTNode read fldJumpDefault;
        property labelNumber: int read fldLabelNumber write fldLabelNumber; { заполняется в одном из двух случаев:
              1. Инструкция узла выполняется сразу после узла с инструкцией AVT_SWITCH;
              2. Инструкция узла выполняется не только после узла с предыдущей инструкцией (другими словами, существует хотя бы один узел, с которого можно перейти на этот и который не предшествует этому узлу). }
        property lineIndex: int read fldLineIndex write fldLineIndex; { добавить свойство position и/или charIndex (необходима точность до координат/позиции в исходном коде) }
        property instruction: int read fldInstruction write setInstruction;
        property operand1: _Object read fldOperand1 write setOperand1;
        property operand2: _Object read fldOperand2 write setOperand2;
        property dataType: AVTType read fldDataType write fldDataType;
        property shortCode: short_Array1d read fldShortCode write fldShortCode; { В будущем сделать как short[][] (сейчас short[]), чтобы был доступ к каждой инструкции абстрактной виртуальной машины }
        property order: int read fldOrder;
        property index: int read fldIndex;
        property code: AVTCode read fldCode;
        property parent: AVTNode read fldParent;
        property length: int read getLength;
        property child[index: int]: AVTNode read getChild; default;
    end;

    AVTException = class(Exception);

    AVTCompilerException = class(AVTException)
    private
        fldLineIndex: int; { * }
        fldCharIndex: int; { * }
        fldSourceFileName: UnicodeString; { * }
    public
        constructor create(const message: AnsiString; const sourceFileName: UnicodeString; lineIndex, charIndex: int); overload;
        constructor create(const message: AnsiString; source: AVTSource; position: int); overload;
    published
        property lineIndex: int read fldLineIndex write fldLineIndex;
        property charIndex: int read fldCharIndex write fldCharIndex;
        property sourceFileName: UnicodeString read fldSourceFileName write fldSourceFileName;
    end;

    AVTGlobalException = class(AVTException);

    IllegalLexemeValueTypeException = class(RuntimeException);

resourcestring
    msgIllegalLexemeValueType = 'Недопустимый тип значения лексемы.';
{%endregion}

implementation

{%region AVTStringStorage }
    constructor AVTStringStorage.create();
    begin
        inherited create();
        self.fldArray := UnicodeString_Array1d_create(7);
    end;

    function AVTStringStorage.indexOf(const item: AnsiString): int;
    begin
        result := indexOf(stringToUTF16(item));
    end;

    function AVTStringStorage.indexOf(const item: UnicodeString): int;
    var
        idx: int;
        arc: UnicodeString_Array1d;
    begin
        arc := fldArray;
        for idx := 0 to fldLength - 1 do begin
            if arc[idx] <> item then continue;
            result := idx;
            exit;
        end;
        result := -1;
    end;

    function AVTStringStorage.indexAcquire(const item: AnsiString): int;
    begin
        result := indexAcquire(stringToUTF16(item));
    end;

    function AVTStringStorage.indexAcquire(const item: UnicodeString): int;
    var
        idx: int;
        cap: int;
        arc: UnicodeString_Array1d;
        arn: UnicodeString_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                arn := UnicodeString_Array1d_create((cap shl 1) + 1);
                arraycopyUnicodeStrings(arc, 0, arn, 0, cap);
                fldArray := arn;
                arc := arn;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTStringStorage.itemAt(index: int): UnicodeString;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTStringStorage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTByte2Storage }
    class function AVTByte2Storage.equals(const value0, value1: byte2): boolean;
    begin
        result := (value0[0] = value1[0]) and (value0[1] = value1[1]);
    end;

    constructor AVTByte2Storage.create();
    begin
        inherited create();
        setLength(self.fldArray, 7);
    end;

    function AVTByte2Storage.indexOf(const item: byte2): int;
    var
        i: int;
        arc: byte2_Array1d;
    begin
        arc := fldArray;
        for i := 0 to fldLength - 1 do begin
            if equals(arc[i], item) then begin
                result := i;
                exit;
            end;
        end;
        result := -1;
    end;

    function AVTByte2Storage.indexAcquire(const item: byte2): int;
    var
        idx: int;
        cap: int;
        arc: byte2_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                setLength(arc, (cap shl 1) + 1);
                fldArray := arc;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTByte2Storage.itemAt(index: int) : byte2;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTByte2Storage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTByte4Storage }
    class function AVTByte4Storage.equals(const value0, value1: byte4): boolean;
    begin
        result := (value0[0] = value1[0]) and (value0[1] = value1[1]) and (value0[2] = value1[2]) and (value0[3] = value1[3]);
    end;

    constructor AVTByte4Storage.create();
    begin
        inherited create();
        setLength(self.fldArray, 7);
    end;

    function AVTByte4Storage.indexOf(const item: byte4): int;
    var
        i: int;
        arc: byte4_Array1d;
    begin
        arc := fldArray;
        for i := 0 to fldLength - 1 do begin
            if equals(arc[i], item) then begin
                result := i;
                exit;
            end;
        end;
        result := -1;
    end;

    function AVTByte4Storage.indexAcquire(const item: byte4): int;
    var
        idx: int;
        cap: int;
        arc: byte4_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                setLength(arc, (cap shl 1) + 1);
                fldArray := arc;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTByte4Storage.itemAt(index: int) : byte4;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTByte4Storage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTByte8Storage }
    class function AVTByte8Storage.equals(const value0, value1: byte8): boolean;
    begin
        result := (value0[0] = value1[0]) and (value0[1] = value1[1]) and (value0[2] = value1[2]) and (value0[3] = value1[3]) and (value0[4] = value1[4]) and (value0[5] = value1[5]) and (value0[6] = value1[6]) and (value0[7] = value1[7]);
    end;

    constructor AVTByte8Storage.create();
    begin
        inherited create();
        setLength(self.fldArray, 7);
    end;

    function AVTByte8Storage.indexOf(const item: byte8): int;
    var
        i: int;
        arc: byte8_Array1d;
    begin
        arc := fldArray;
        for i := 0 to fldLength - 1 do begin
            if equals(arc[i], item) then begin
                result := i;
                exit;
            end;
        end;
        result := -1;
    end;

    function AVTByte8Storage.indexAcquire(const item: byte8): int;
    var
        idx: int;
        cap: int;
        arc: byte8_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                setLength(arc, (cap shl 1) + 1);
                fldArray := arc;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTByte8Storage.itemAt(index: int) : byte8;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTByte8Storage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTShort2Storage }
    class function AVTShort2Storage.equals(const value0, value1: short2): boolean;
    begin
        result := (value0[0] = value1[0]) and (value0[1] = value1[1]);
    end;

    constructor AVTShort2Storage.create();
    begin
        inherited create();
        setLength(self.fldArray, 7);
    end;

    function AVTShort2Storage.indexOf(const item: short2): int;
    var
        i: int;
        arc: short2_Array1d;
    begin
        arc := fldArray;
        for i := 0 to fldLength - 1 do begin
            if equals(arc[i], item) then begin
                result := i;
                exit;
            end;
        end;
        result := -1;
    end;

    function AVTShort2Storage.indexAcquire(const item: short2): int;
    var
        idx: int;
        cap: int;
        arc: short2_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                setLength(arc, (cap shl 1) + 1);
                fldArray := arc;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTShort2Storage.itemAt(index: int) : short2;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTShort2Storage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTShort4Storage }
    class function AVTShort4Storage.equals(const value0, value1: short4): boolean;
    begin
        result := (value0[0] = value1[0]) and (value0[1] = value1[1]) and (value0[2] = value1[2]) and (value0[3] = value1[3]);
    end;

    constructor AVTShort4Storage.create();
    begin
        inherited create();
        setLength(self.fldArray, 7);
    end;

    function AVTShort4Storage.indexOf(const item: short4): int;
    var
        i: int;
        arc: short4_Array1d;
    begin
        arc := fldArray;
        for i := 0 to fldLength - 1 do begin
            if equals(arc[i], item) then begin
                result := i;
                exit;
            end;
        end;
        result := -1;
    end;

    function AVTShort4Storage.indexAcquire(const item: short4): int;
    var
        idx: int;
        cap: int;
        arc: short4_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                setLength(arc, (cap shl 1) + 1);
                fldArray := arc;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTShort4Storage.itemAt(index: int) : short4;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTShort4Storage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTShort8Storage }
    class function AVTShort8Storage.equals(const value0, value1: short8): boolean;
    begin
        result := (value0[0] = value1[0]) and (value0[1] = value1[1]) and (value0[2] = value1[2]) and (value0[3] = value1[3]) and (value0[4] = value1[4]) and (value0[5] = value1[5]) and (value0[6] = value1[6]) and (value0[7] = value1[7]);
    end;

    constructor AVTShort8Storage.create();
    begin
        inherited create();
        setLength(self.fldArray, 7);
    end;

    function AVTShort8Storage.indexOf(const item: short8): int;
    var
        i: int;
        arc: short8_Array1d;
    begin
        arc := fldArray;
        for i := 0 to fldLength - 1 do begin
            if equals(arc[i], item) then begin
                result := i;
                exit;
            end;
        end;
        result := -1;
    end;

    function AVTShort8Storage.indexAcquire(const item: short8): int;
    var
        idx: int;
        cap: int;
        arc: short8_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                setLength(arc, (cap shl 1) + 1);
                fldArray := arc;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTShort8Storage.itemAt(index: int) : short8;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTShort8Storage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTIntStorage }
    constructor AVTIntStorage.create();
    begin
        inherited create();
        self.fldArray := int_Array1d_create(7);
    end;

    function AVTIntStorage.indexOf(const item: int): int;
    begin
        result := arrayfindeqfPrimitive(fldArray, 0, fldLength, item);
    end;

    function AVTIntStorage.indexAcquire(const item: int): int;
    var
        idx: int;
        cap: int;
        arc: int_Array1d;
        arn: int_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                arn := int_Array1d_create((cap shl 1) + 1);
                arraycopyPrimitives(arc, 0, arn, 0, cap);
                fldArray := arn;
                arc := arn;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTIntStorage.itemAt(index: int): int;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTIntStorage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTInt2Storage }
    class function AVTInt2Storage.equals(const value0, value1: int2): boolean;
    begin
        result := (value0[0] = value1[0]) and (value0[1] = value1[1]);
    end;

    constructor AVTInt2Storage.create();
    begin
        inherited create();
        setLength(self.fldArray, 7);
    end;

    function AVTInt2Storage.indexOf(const item: int2): int;
    var
        i: int;
        arc: int2_Array1d;
    begin
        arc := fldArray;
        for i := 0 to fldLength - 1 do begin
            if equals(arc[i], item) then begin
                result := i;
                exit;
            end;
        end;
        result := -1;
    end;

    function AVTInt2Storage.indexAcquire(const item: int2): int;
    var
        idx: int;
        cap: int;
        arc: int2_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                setLength(arc, (cap shl 1) + 1);
                fldArray := arc;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTInt2Storage.itemAt(index: int) : int2;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTInt2Storage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTInt4Storage }
    class function AVTInt4Storage.equals(const value0, value1: int4): boolean;
    begin
        result := (value0[0] = value1[0]) and (value0[1] = value1[1]) and (value0[2] = value1[2]) and (value0[3] = value1[3]);
    end;

    constructor AVTInt4Storage.create();
    begin
        inherited create();
        setLength(self.fldArray, 7);
    end;

    function AVTInt4Storage.indexOf(const item: int4): int;
    var
        i: int;
        arc: int4_Array1d;
    begin
        arc := fldArray;
        for i := 0 to fldLength - 1 do begin
            if equals(arc[i], item) then begin
                result := i;
                exit;
            end;
        end;
        result := -1;
    end;

    function AVTInt4Storage.indexAcquire(const item: int4): int;
    var
        idx: int;
        cap: int;
        arc: int4_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                setLength(arc, (cap shl 1) + 1);
                fldArray := arc;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTInt4Storage.itemAt(index: int) : int4;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTInt4Storage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTInt8Storage }
    class function AVTInt8Storage.equals(const value0, value1: int8): boolean;
    begin
        result := (value0[0] = value1[0]) and (value0[1] = value1[1]) and (value0[2] = value1[2]) and (value0[3] = value1[3]) and (value0[4] = value1[4]) and (value0[5] = value1[5]) and (value0[6] = value1[6]) and (value0[7] = value1[7]);
    end;

    constructor AVTInt8Storage.create();
    begin
        inherited create();
        setLength(self.fldArray, 7);
    end;

    function AVTInt8Storage.indexOf(const item: int8): int;
    var
        i: int;
        arc: int8_Array1d;
    begin
        arc := fldArray;
        for i := 0 to fldLength - 1 do begin
            if equals(arc[i], item) then begin
                result := i;
                exit;
            end;
        end;
        result := -1;
    end;

    function AVTInt8Storage.indexAcquire(const item: int8): int;
    var
        idx: int;
        cap: int;
        arc: int8_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                setLength(arc, (cap shl 1) + 1);
                fldArray := arc;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTInt8Storage.itemAt(index: int) : int8;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTInt8Storage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTLongStorage }
    constructor AVTLongStorage.create();
    begin
        inherited create();
        self.fldArray := long_Array1d_create(7);
    end;

    function AVTLongStorage.indexOf(const item: long): int;
    begin
        result := arrayfindeqfPrimitive(fldArray, 0, fldLength, item);
    end;

    function AVTLongStorage.indexAcquire(const item: long): int;
    var
        idx: int;
        cap: int;
        arc: long_Array1d;
        arn: long_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                arn := long_Array1d_create(int((cap shl 1) + 1));
                arraycopyPrimitives(arc, 0, arn, 0, cap);
                fldArray := arn;
                arc := arn;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTLongStorage.itemAt(index: int): long;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTLongStorage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTLong2Storage }
    class function AVTLong2Storage.equals(const value0, value1: long2): boolean;
    begin
        result := (value0[0] = value1[0]) and (value0[1] = value1[1]);
    end;

    constructor AVTLong2Storage.create();
    begin
        inherited create();
        setLength(self.fldArray, 7);
    end;

    function AVTLong2Storage.indexOf(const item: long2): int;
    var
        i: int;
        arc: long2_Array1d;
    begin
        arc := fldArray;
        for i := 0 to fldLength - 1 do begin
            if equals(arc[i], item) then begin
                result := i;
                exit;
            end;
        end;
        result := -1;
    end;

    function AVTLong2Storage.indexAcquire(const item: long2): int;
    var
        idx: int;
        cap: int;
        arc: long2_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                setLength(arc, (cap shl 1) + 1);
                fldArray := arc;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTLong2Storage.itemAt(index: int) : long2;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTLong2Storage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTLong4Storage }
    class function AVTLong4Storage.equals(const value0, value1: long4): boolean;
    begin
        result := (value0[0] = value1[0]) and (value0[1] = value1[1]) and (value0[2] = value1[2]) and (value0[3] = value1[3]);
    end;

    constructor AVTLong4Storage.create();
    begin
        inherited create();
        setLength(self.fldArray, 7);
    end;

    function AVTLong4Storage.indexOf(const item: long4): int;
    var
        i: int;
        arc: long4_Array1d;
    begin
        arc := fldArray;
        for i := 0 to fldLength - 1 do begin
            if equals(arc[i], item) then begin
                result := i;
                exit;
            end;
        end;
        result := -1;
    end;

    function AVTLong4Storage.indexAcquire(const item: long4): int;
    var
        idx: int;
        cap: int;
        arc: long4_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                setLength(arc, (cap shl 1) + 1);
                fldArray := arc;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTLong4Storage.itemAt(index: int) : long4;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTLong4Storage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTLong8Storage }
    class function AVTLong8Storage.equals(const value0, value1: long8): boolean;
    begin
        result := (value0[0] = value1[0]) and (value0[1] = value1[1]) and (value0[2] = value1[2]) and (value0[3] = value1[3]) and (value0[4] = value1[4]) and (value0[5] = value1[5]) and (value0[6] = value1[6]) and (value0[7] = value1[7]);
    end;

    constructor AVTLong8Storage.create();
    begin
        inherited create();
        setLength(self.fldArray, 7);
    end;

    function AVTLong8Storage.indexOf(const item: long8): int;
    var
        i: int;
        arc: long8_Array1d;
    begin
        arc := fldArray;
        for i := 0 to fldLength - 1 do begin
            if equals(arc[i], item) then begin
                result := i;
                exit;
            end;
        end;
        result := -1;
    end;

    function AVTLong8Storage.indexAcquire(const item: long8): int;
    var
        idx: int;
        cap: int;
        arc: long8_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                setLength(arc, (cap shl 1) + 1);
                fldArray := arc;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTLong8Storage.itemAt(index: int) : long8;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTLong8Storage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTFloatStorage }
    constructor AVTFloatStorage.create();
    begin
        inherited create();
        self.fldArray := int_Array1d_create(7);
    end;

    function AVTFloatStorage.indexOf(const item: float): int;
    begin
        result := arrayfindeqfPrimitive(fldArray, 0, fldLength, floatToIntBits(item));
    end;

    function AVTFloatStorage.indexAcquire(const item: float): int;
    var
        idx: int;
        cap: int;
        arc: int_Array1d;
        arn: int_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                arn := int_Array1d_create((cap shl 1) + 1);
                arraycopyPrimitives(arc, 0, arn, 0, cap);
                fldArray := arn;
                arc := arn;
            end;
            fldLength := idx + 1;
            arc[idx] := floatToIntBits(item);
        end;
        result := idx;
    end;

    function AVTFloatStorage.itemAt(index: int): float;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTFloatStorage: ' + msgIndexOutOfBounds);
        end;
        result := intBitsToFloat(fldArray[index]);
    end;
{%endregion}

{%region AVTFloat2Storage }
    class function AVTFloat2Storage.equals(const value0, value1: float2): boolean;
    begin
        result := AVTInt2Storage.equals(int2(value0), int2(value1));
    end;

    constructor AVTFloat2Storage.create();
    begin
        inherited create();
        setLength(self.fldArray, 7);
    end;

    function AVTFloat2Storage.indexOf(const item: float2): int;
    var
        i: int;
        arc: float2_Array1d;
    begin
        arc := fldArray;
        for i := 0 to fldLength - 1 do begin
            if equals(arc[i], item) then begin
                result := i;
                exit;
            end;
        end;
        result := -1;
    end;

    function AVTFloat2Storage.indexAcquire(const item: float2): int;
    var
        idx: int;
        cap: int;
        arc: float2_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                setLength(arc, (cap shl 1) + 1);
                fldArray := arc;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTFloat2Storage.itemAt(index: int) : float2;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTFloat2Storage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTFloat4Storage }
    class function AVTFloat4Storage.equals(const value0, value1: float4): boolean;
    begin
        result := AVTInt4Storage.equals(int4(value0), int4(value1));
    end;

    constructor AVTFloat4Storage.create();
    begin
        inherited create();
        setLength(self.fldArray, 7);
    end;

    function AVTFloat4Storage.indexOf(const item: float4): int;
    var
        i: int;
        arc: float4_Array1d;
    begin
        arc := fldArray;
        for i := 0 to fldLength - 1 do begin
            if equals(arc[i], item) then begin
                result := i;
                exit;
            end;
        end;
        result := -1;
    end;

    function AVTFloat4Storage.indexAcquire(const item: float4): int;
    var
        idx: int;
        cap: int;
        arc: float4_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                setLength(arc, (cap shl 1) + 1);
                fldArray := arc;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTFloat4Storage.itemAt(index: int) : float4;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTFloat4Storage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTFloat8Storage }
    class function AVTFloat8Storage.equals(const value0, value1: float8): boolean;
    begin
        result := AVTInt8Storage.equals(int8(value0), int8(value1));
    end;

    constructor AVTFloat8Storage.create();
    begin
        inherited create();
        setLength(self.fldArray, 7);
    end;

    function AVTFloat8Storage.indexOf(const item: float8): int;
    var
        i: int;
        arc: float8_Array1d;
    begin
        arc := fldArray;
        for i := 0 to fldLength - 1 do begin
            if equals(arc[i], item) then begin
                result := i;
                exit;
            end;
        end;
        result := -1;
    end;

    function AVTFloat8Storage.indexAcquire(const item: float8): int;
    var
        idx: int;
        cap: int;
        arc: float8_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                setLength(arc, (cap shl 1) + 1);
                fldArray := arc;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTFloat8Storage.itemAt(index: int) : float8;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTFloat8Storage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTDoubleStorage }
    constructor AVTDoubleStorage.create();
    begin
        inherited create();
        self.fldArray := long_Array1d_create(7);
    end;

    function AVTDoubleStorage.indexOf(const item: double): int;
    begin
        result := arrayfindeqfPrimitive(fldArray, 0, fldLength, doubleToLongBits(item));
    end;

    function AVTDoubleStorage.indexAcquire(const item: double): int;
    var
        idx: int;
        cap: int;
        arc: long_Array1d;
        arn: long_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                arn := long_Array1d_create(int((cap shl 1) + 1));
                arraycopyPrimitives(arc, 0, arn, 0, cap);
                fldArray := arn;
                arc := arn;
            end;
            fldLength := idx + 1;
            arc[idx] := doubleToLongBits(item);
        end;
        result := idx;
    end;

    function AVTDoubleStorage.itemAt(index: int): double;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTDoubleStorage: ' + msgIndexOutOfBounds);
        end;
        result := longBitsToDouble(fldArray[index]);
    end;
{%endregion}

{%region AVTDouble2Storage }
    class function AVTDouble2Storage.equals(const value0, value1: double2): boolean;
    begin
        result := AVTLong2Storage.equals(long2(value0), long2(value1));
    end;

    constructor AVTDouble2Storage.create();
    begin
        inherited create();
        setLength(self.fldArray, 7);
    end;

    function AVTDouble2Storage.indexOf(const item: double2): int;
    var
        i: int;
        arc: double2_Array1d;
    begin
        arc := fldArray;
        for i := 0 to fldLength - 1 do begin
            if equals(arc[i], item) then begin
                result := i;
                exit;
            end;
        end;
        result := -1;
    end;

    function AVTDouble2Storage.indexAcquire(const item: double2): int;
    var
        idx: int;
        cap: int;
        arc: double2_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                setLength(arc, (cap shl 1) + 1);
                fldArray := arc;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTDouble2Storage.itemAt(index: int) : double2;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTDouble2Storage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTDouble4Storage }
    class function AVTDouble4Storage.equals(const value0, value1: double4): boolean;
    begin
        result := AVTLong4Storage.equals(long4(value0), long4(value1));
    end;

    constructor AVTDouble4Storage.create();
    begin
        inherited create();
        setLength(self.fldArray, 7);
    end;

    function AVTDouble4Storage.indexOf(const item: double4): int;
    var
        i: int;
        arc: double4_Array1d;
    begin
        arc := fldArray;
        for i := 0 to fldLength - 1 do begin
            if equals(arc[i], item) then begin
                result := i;
                exit;
            end;
        end;
        result := -1;
    end;

    function AVTDouble4Storage.indexAcquire(const item: double4): int;
    var
        idx: int;
        cap: int;
        arc: double4_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                setLength(arc, (cap shl 1) + 1);
                fldArray := arc;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTDouble4Storage.itemAt(index: int) : double4;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTDouble4Storage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTDouble8Storage }
    class function AVTDouble8Storage.equals(const value0, value1: double8): boolean;
    begin
        result := AVTLong8Storage.equals(long8(value0), long8(value1));
    end;

    constructor AVTDouble8Storage.create();
    begin
        inherited create();
        setLength(self.fldArray, 7);
    end;

    function AVTDouble8Storage.indexOf(const item: double8): int;
    var
        i: int;
        arc: double8_Array1d;
    begin
        arc := fldArray;
        for i := 0 to fldLength - 1 do begin
            if equals(arc[i], item) then begin
                result := i;
                exit;
            end;
        end;
        result := -1;
    end;

    function AVTDouble8Storage.indexAcquire(const item: double8): int;
    var
        idx: int;
        cap: int;
        arc: double8_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                setLength(arc, (cap shl 1) + 1);
                fldArray := arc;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTDouble8Storage.itemAt(index: int) : double8;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTDouble8Storage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTRealStorage }
    constructor AVTRealStorage.create();
    begin
        inherited create();
        self.fldArray := real_Array1d_create(7);
    end;

    function AVTRealStorage.indexOf(const item: real): int;
    var
        idx: int;
        exp: int;
        sig: long;
        itc: real;
        arc: real_Array1d;
    begin
        arc := fldArray;
        exp := realExponent(item);
        sig := realSignificand(item);
        for idx := 0 to fldLength - 1 do begin
            itc := arc[idx];
            if (realExponent(itc) <> exp) or (realSignificand(itc) <> sig) then continue;
            result := idx;
            exit;
        end;
        result := -1;
    end;

    function AVTRealStorage.indexAcquire(const item: real): int;
    var
        idx: int;
        cap: int;
        arc: real_Array1d;
        arn: real_Array1d;
    begin
        idx := indexOf(item);
        if idx < 0 then begin
            arc := fldArray;
            idx := fldLength;
            cap := system.length(arc);
            if idx = cap then begin
                arn := real_Array1d_create((cap shl 1) + 1);
                arraycopyPrimitives(arc, 0, arn, 0, cap);
                fldArray := arn;
                arc := arn;
            end;
            fldLength := idx + 1;
            arc[idx] := item;
        end;
        result := idx;
    end;

    function AVTRealStorage.itemAt(index: int): real;
    begin
        if (index < 0) or (index >= fldLength) then begin
            raise IndexOutOfBoundsException.create('AVTRealStorage: ' + msgIndexOutOfBounds);
        end;
        result := fldArray[index];
    end;
{%endregion}

{%region AVTProgramme }
    class procedure AVTProgramme.sort(const types: AVTTypeStructured_Array1d);
    label
        label0;
    var
        lim: int;
        id0: int;
        id1: int;
        tp0: AVTTypeStructured;
        tp1: AVTTypeStructured;
    begin
        lim := length(types) - 1;
        for id0 := 0 to lim - 1 do begin
            tp0 := types[id0];
            repeat
                for id1 := id0 + 1 to lim do begin
                    tp1 := types[id1];
                    if not tp0.isImplements(tp1) then continue;
                    types[id0] := tp1;
                    types[id1] := tp0;
                    tp0 := tp1;
                    goto label0;
                end;
                break;
                label0:
            until false;
        end;
    end;

    class function AVTProgramme.isSupportedAVX512ByCPU(): boolean; assembler;
    asm
                push    rbx
                mov     eax, $00000001
                cpuid
                test    ecx, $10000000 { AVX }
                jz      @noavx
                mov     eax, $00000007
                mov     ecx, $00000000
                cpuid
                test    ebx, $00000020 { AVX2 }
                jz      @noavx
                and     ebx, $50030000 { AVX-512 }
                cmp     ebx, $50030000
                jnz     @noavx
                mov     eax, $00000001
                jmp     @lexit
        @noavx: xor     eax, eax
        @lexit: pop     rbx
    end;

    class function AVTProgramme.isSupportedAVX512ByOS(): boolean; assembler;
    asm
                push    rbx
                mov     eax, $00000001
                cpuid
                test    ecx, $08000000 { XGETBV включено операционной системой ? }
                jz      @noavx
                xor     ecx, ecx
                xgetbv
                and     eax, $000000e6 { Состояние регистров AVX-512, AVX, SSE и FPU сохраняется операционной системой при переключении контекстов ? }
                cmp     eax, $000000e6
                jnz     @noavx
                mov     eax, $00000001
                jmp     @lexit
        @noavx: xor     eax, eax
        @lexit: pop     rbx
    end;

    procedure AVTProgramme.addArray(aarray: AVTTypeArray);
    begin
        fldArrays.append(ValueOfObject.create(aarray, false));
    end;

    procedure AVTProgramme.addSource(source: AVTSource);
    begin
        fldSources.put(ValueOfUnicodeString.create(source.fldFileName), ValueOfObject.create(source));
    end;

    procedure AVTProgramme.addPackage(package: AVTPackage);
    begin
        fldPackages.put(ValueOfAnsiString.create(package.fldFullName), ValueOfObject.create(package));
    end;

    procedure AVTProgramme.createArrays();
    var
        knd: int;
        nam: AnsiString;
        tpe: AVTType;
        tpa: AVTTypeArray;
        pck: AVTPackage;
        pck_avt_lang: AVTPackage;
        pck_avt_lang_array: AVTPackage;
        typ_avt_lang_Object: AVTTypeStructured;
        typ_avt_lang_RawData: AVTTypeStructured;
        typ_avt_lang_Cloneable: AVTTypeStructured;
        typ_avt_lang_array_Measureable: AVTTypeStructured;
        typ_avt_lang_array_TypeArray: AVTTypeStructured;
        typ_avt_lang_array_MutableTypeArray: AVTTypeStructured;
    begin
        pck := fldSystemPackage;
        pck_avt_lang := getPackage('avt.lang');
        if pck_avt_lang = nil then exit;
        typ_avt_lang_Object := pck_avt_lang.getType('Object') as AVTTypeStructured;
        if (typ_avt_lang_Object = nil) or not typ_avt_lang_Object.isClass() then exit;
        pck_avt_lang_array := getPackage('avt.lang.array');
        typ_avt_lang_RawData := nil;
        typ_avt_lang_Cloneable := nil;
        typ_avt_lang_array_Measureable := nil;
        typ_avt_lang_array_TypeArray := nil;
        typ_avt_lang_array_MutableTypeArray := nil;
        if pck_avt_lang_array <> nil then begin
            typ_avt_lang_RawData := pck_avt_lang.getType('RawData') as AVTTypeStructured;
            typ_avt_lang_Cloneable := pck_avt_lang.getType('Cloneable') as AVTTypeStructured;
            typ_avt_lang_array_Measureable := pck_avt_lang_array.getType('Measureable') as AVTTypeStructured;
        end;
        for knd := AVT_VOID to AVT_DOUBLE8 do begin
            if knd = AVT_VOID then begin
                tpe := typ_avt_lang_Object;
            end else begin
                tpe := pck.getType(AVTTypePrimitive.getName(knd));
            end;
            if pck_avt_lang_array <> nil then begin
                nam := tpe.fldSimpleName;
                nam := charToUpperCase(nam[1]) + stringCopy(nam, 2) + 'Array'; { имя — с большой буквы }
                typ_avt_lang_array_TypeArray := pck_avt_lang_array.getType(nam) as AVTTypeStructured;
                typ_avt_lang_array_MutableTypeArray := pck_avt_lang_array.getType('Mutable' + nam) as AVTTypeStructured;
            end;
            tpa := AVTTypeArray.create(tpe);
            tpa.setExtends(typ_avt_lang_Object);
            if (knd <> AVT_VOID) and (typ_avt_lang_RawData <> nil) and typ_avt_lang_RawData.isService() then tpa.addImplements(typ_avt_lang_RawData);
            if (typ_avt_lang_Cloneable <> nil) and typ_avt_lang_Cloneable.isService() then tpa.addImplements(typ_avt_lang_Cloneable);
            if (typ_avt_lang_array_Measureable <> nil) and typ_avt_lang_array_Measureable.isService() then tpa.addImplements(typ_avt_lang_array_Measureable);
            if (typ_avt_lang_array_MutableTypeArray <> nil) and typ_avt_lang_array_MutableTypeArray.isService() then tpa.addImplements(typ_avt_lang_array_MutableTypeArray);
            if (typ_avt_lang_array_TypeArray <> nil) and typ_avt_lang_array_TypeArray.isService() then tpa.addImplements(typ_avt_lang_array_TypeArray);
            tpa.prefetchImplements();
            tpa.checkImplements();
            tpa.makeCompilable();
        end;
    end;

    constructor AVTProgramme.create(bits: int);
    var
        knd: int;
        pck: AVTPackage;
    begin
        inherited create();
        self.fldBits := bits;
        self.fldTypes := Vector.create();
        self.fldArrays := Vector.create();
        self.fldSources := Hashtable.create();
        self.fldPackages := Hashtable.create();
        pck := AVTPackage.create(self, nil, '');
        self.fldSystemPackage := pck;
        for knd := AVT_VOID to AVT_DOUBLE8 do begin
            AVTTypePrimitive.create(pck, knd);
        end;
    end;

    destructor AVTProgramme.destroy;
    begin
        fldPackages.free();
        fldSources.free();
        fldArrays.free();
        fldTypes.free();
        inherited destroy;
    end;

    procedure AVTProgramme.prefetchTypes();
    var
        idx: int;
        lim: int;
        vec: Vector;
        tpc: AVTType;
        tps: AVTTypeStructured;
        tpa: AVTTypeStructured_Array1d;
        en0: Enumeration;
        en1: Enumeration;
    begin
        vec := fldTypes;
        vec.clear();
        en0 := fldPackages.elements();
        while en0.hasMoreElements() do begin
            en1 := (en0.nextElement().objectValue() as AVTPackage).types();
            while en1.hasMoreElements() do begin
                tpc := en1.nextElement().objectValue() as AVTType;
                if tpc is AVTTypeStructured then vec.append(ValueOfObject.create(tpc, false));
            end;
        end;
        lim := vec.size() - 1;
        tpa := AVTTypeStructured_Array1d(TObject_Array1d_create(lim + 1));
        for idx := lim downto 0 do begin
            tps := vec.elementAt(idx).objectValue() as AVTTypeStructured;
            tps.prefetchImplements();
            tps.checkImplements();
            tpa[idx] := tps;
        end;
        sort(tpa);
        vec.clear();
        for idx := 0 to lim do begin
            vec.append(ValueOfObject.create(tpa[idx], false));
        end;
        createArrays();
    end;

    procedure AVTProgramme.prefetchArrays();
    var
        knd: int;
        vec: Vector;
        arg: Vector;
        tpe: AVTType;
        tpa: AVTTypeArray;
        pck: AVTPackage;
        pck_avt_lang: AVTPackage;
        typ_int: AVTType;
        typ_long: AVTType;
        typ_void: AVTType;
        typ_avt_lang_Cloneable: AVTType;
        typ_avt_lang_Struct: AVTType;
        typ_avt_lang_String: AVTType;
        fld_fldLength: AVTField;
        met_clone: AVTMethod;
        cod: AVTCode;
    begin
        vec := fldArrays;
        pck := fldSystemPackage;
        pck_avt_lang := getPackage('avt.lang');
        if pck_avt_lang = nil then exit;
        typ_avt_lang_Cloneable := pck_avt_lang.getType('Cloneable');
        typ_avt_lang_Struct := pck_avt_lang.getType('Struct');
        typ_avt_lang_String := pck_avt_lang.getType('String');
        typ_int := pck.getType(AVTTypePrimitive.getName(AVT_INT));
        typ_long := pck.getType(AVTTypePrimitive.getName(AVT_LONG));
        typ_void := pck.getType(AVTTypePrimitive.getName(AVT_VOID));
        for knd := AVT_VOID to vec.size() + (AVT_VOID - 1) do begin
            (*
                import avt.lang.array.*;

                public class T[](Object, Measureable, T#Array, Mutable#T#Array, Cloneable)
                {
                    private int fldLength;
                    private Struct fldParentStruct; /* private long reserved0, если Struct не определён */
                    private long reserved1;
                    private long fldOffset;

                    public native String toString(); /* только тип char[] */

                    public native long getPointer();

                    public native long getLength();

                    public native Cloneable clone();

                    public int length { read = fldLength }

                    public native void operator []=(int index, T value);

                    public native T operator [](int index);
                }
            *)
            tpa := vec.elementAt(knd - AVT_VOID).objectValue() as AVTTypeArray;
            if knd <= AVT_DOUBLE8 then begin
                tpe := tpa.fldElementType;
                fld_fldLength := AVTField.create(tpa, FLAG_PRIVATE, typ_int, 0, 'fldLength');
                if typ_avt_lang_Struct <> nil then begin
                    AVTField.create(tpa, FLAG_PRIVATE, typ_avt_lang_Struct, 0, 'fldParentStruct');
                end else begin
                    AVTField.create(tpa, FLAG_PRIVATE, typ_long, 0, 'fldReserved1');
                end;
                AVTField.create(tpa, FLAG_PRIVATE, typ_long, 0, 'fldReserved2');
                AVTField.create(tpa, FLAG_PRIVATE, typ_long, 0, 'fldOffset');
                if (knd = AVT_CHAR) and (typ_avt_lang_String <> nil) then begin
                    with AVTMethod.create(tpa, FLAG_PUBLIC or FLAG_NATIVE, typ_avt_lang_String, 'toString', nil) do begin
                        findOverriddenMembers();
                    end;
                end;
                if knd > AVT_VOID then begin
                    with AVTMethod.create(tpa, FLAG_PUBLIC or FLAG_NATIVE, typ_long, 'getPointer', nil) do begin
                        findOverriddenMembers();
                    end;
                    with AVTMethod.create(tpa, FLAG_PUBLIC or FLAG_NATIVE, typ_long, 'getLength', nil) do begin
                        findOverriddenMembers();
                    end;
                end;
                with AVTMethod.create(tpa, FLAG_PUBLIC or FLAG_NATIVE, tpa, 'clone', nil) do begin
                    findOverriddenMembers();
                end;
                with AVTProperty.create(tpa, FLAG_PUBLIC, typ_int, 'length') do begin
                    findOverriddenMembers();
                    readMember := fld_fldLength;
                end;
                arg := Vector.create();
                try
                    arg.append(ValueOfObject.create(AVTVariable.create(typ_int, 'index')));
                    arg.append(ValueOfObject.create(AVTVariable.create(tpe, 'value')));
                    with AVTOperator.create(tpa, FLAG_PUBLIC or FLAG_NATIVE, typ_void, SET_ARRAY_ELEMENT, arg) do begin
                        findOverriddenMembers();
                    end;
                    arg.delete(1);
                    with AVTOperator.create(tpa, FLAG_PUBLIC or FLAG_NATIVE, tpe, GET_ARRAY_ELEMENT, arg) do begin
                        findOverriddenMembers();
                    end;
                finally
                    arg.free();
                end;
            end;
            tpa.prefetchMembers();
        end;
        fldIsArraysPrefetched := true;
    end;

    function AVTProgramme.getType(const fullName: AnsiString): AVTType;
    var
        dot: int;
        pck: AVTPackage;
    begin
        dot := stringLastIndexOf('.', fullName);
        if dot < 1 then begin
            result := fldSystemPackage.getType(fullName);
            exit;
        end;
        pck := getPackage(stringCopy(fullName, 1, dot));
        if pck = nil then begin
            result := nil;
            exit;
        end;
        result := pck.getType(stringCopy(fullName, dot + 1));
    end;

    function AVTProgramme.getArrayOf(elementType: AVTType): AVTTypeArray;
    var
        pck: AVTPackage;
        tpa: AVTTypeArray;
    begin
        if elementType = nil then begin
            raise NullPointerException.create(msgNullPointerArgument + 'elementType');
        end;
        pck := elementType.fldPackage;
        if (pck = nil) or (pck.fldParentProgramme <> self) then begin
            raise IllegalArgumentException.create(msgIllegalArgument + 'elementType');
        end;
        tpa := pck.getType(elementType.fldSimpleName + '[]') as AVTTypeArray;
        if tpa = nil then begin
            tpa := AVTTypeArray.create(elementType);
            tpa.prefetchImplements();
            tpa.checkImplements();
            if fldIsArraysPrefetched then begin
                tpa.prefetchMembers();
            end;
        end;
        result := tpa;
    end;

    function AVTProgramme.getPackage(const fullName: AnsiString): AVTPackage;
    var
        val: Value;
    begin
        val := fldPackages.get(ValueOfAnsiString.create(fullName));
        if val = nil then begin
            result := nil;
            exit;
        end;
        result := val.objectValue() as AVTPackage;
    end;

    function AVTProgramme.getSource(const fileName: UnicodeString): AVTSource;
    var
        val: Value;
    begin
        val := fldSources.get(ValueOfUnicodeString.create(fileName));
        if val = nil then begin
            result := nil;
            exit;
        end;
        result := val.objectValue() as AVTSource;
    end;

    function AVTProgramme.packages(): Enumeration;
    begin
        result := fldPackages.elements();
    end;

    function AVTProgramme.sources(): Enumeration;
    begin
        result := fldSources.elements();
    end;

    function AVTProgramme.arrays(): Enumeration;
    begin
        result := fldArrays.elements();
    end;

    function AVTProgramme.types(): Enumeration;
    begin
        result := fldTypes.elements();
    end;
{%endregion}

{%region AVTSource }
    {
         63       60 59       56 55                   48 47                   40 39 38 37 36 35 34    32
        |--+--+--+--|--+--+--+--|--+--+--+--|--+--+--+--|--+--+--+--|--+--+--+--|--+--+--+--|--+--+--+--|
        |Line Index |                    Lexeme Value Index                     | LVI | CI  |LT|  LVT   |
        |   19:16   |                           19:00                           |21:20|09:08|08| 02:00  |
        |--+--+--+--|--+--+--+--|--+--+--+--|--+--+--+--|--+--+--+--|--+--+--+--|--+--+--+--|--+--+--+--|

         31                   24 23                   16 15                   08 07                   00
        |--+--+--+--|--+--+--+--|--+--+--+--|--+--+--+--|--+--+--+--|--+--+--+--|--+--+--+--|--+--+--+--|
        |                  Line Index                   |      Char Index       |      Lexeme Type      |
        |                     15:00                     |         07:00         |         07:00         |
        |--+--+--+--|--+--+--+--|--+--+--+--|--+--+--+--|--+--+--+--|--+--+--+--|--+--+--+--|--+--+--+--|

        LVI – Lexeme Value Index (22 bit)
        LVT – Lexeme Value Type (3 bit)
        LI – Line Index (20 bit)
        CI – Char Index (10 bit)
        LT – Lexeme Type (9 bit)
    }

    class function AVTSource.buildLexeme(lineIndex, charIndex, lexemeType, lexemeValueType, lexemeValueIndex: int): long;
    begin
        result :=
        (long(lineIndex and $000f0000) shl (60 - 16)) or
        (long(lineIndex and $0000ffff) shl 16) or
        (long(charIndex and $00000300) shl (36 - 8)) or
        (long(charIndex and $000000ff) shl 8) or
        (long(lexemeType and $00000100) shl (35 - 8)) or
        (long(lexemeType and $000000ff)) or
        (long(lexemeValueType and $00000007) shl 32) or
        (long(lexemeValueIndex and $00300000) shl (38 - 20)) or
        (long(lexemeValueIndex and $000fffff) shl 40);
    end;

    class function AVTSource.extractLineIndex(lexeme: long): int;
    begin
        result := int(lexeme shr (60 - 16)) and $000f0000 or int(lexeme shr 16) and $0000ffff;
    end;

    class function AVTSource.extractCharIndex(lexeme: long): int;
    begin
        result := int(lexeme shr (36 - 8)) and $00000300 or int(lexeme shr 8) and $000000ff;
    end;

    class function AVTSource.extractLexemeType(lexeme: long): int;
    begin
        result := int(lexeme shr (35 - 8)) and $00000100 or int(lexeme) and $000000ff;
    end;

    class function AVTSource.extractLexemeValueType(lexeme: long): int;
    begin
        result := int(lexeme shr 32) and $00000007;
    end;

    class function AVTSource.extractLexemeValueIndex(lexeme: long): int;
    begin
        result := int(lexeme shr (38 - 20)) and $00300000 or int(lexeme shr 40) and $000fffff;
    end;

    procedure AVTSource.setPackage(package: AVTPackage);
    begin
        if (fldPackage = nil) and (package <> nil) then begin
            fldPackage := package;
            package.addSource(self);
        end;
    end;

    procedure AVTSource.addDeclaredType(atype: AVTTypeStructured);
    var
        val: Value;
    begin
        val := ValueOfObject.create(atype, false);
        fldDeclaredTypesAsVector.append(val);
        fldDeclaredTypesAsTable.put(ValueOfAnsiString.create(atype.fldSimpleName), val);
    end;

    procedure AVTSource.addLexemeInternal(lineIndex, charIndex, lexemeType, lexemeValueType, lexemeValueIndex: int);
    var
        len: int;
        cap: int;
        arc: long_Array1d;
        arn: long_Array1d;
    begin
        if ((lineIndex and (-1 shl 20)) <> 0) or ((lexemeValueIndex and (-1 shl 22)) <> 0) then begin
            raise AVTCompilerException.create('Source code is too long', fldFileName, lineIndex, charIndex);
        end;
        if (charIndex and (-1 shl 10)) <> 0 then begin
            raise AVTCompilerException.create('Line is too long', fldFileName, lineIndex, charIndex);
        end;
        arc := fldLexemes;
        len := fldLexemesCount;
        cap := system.length(arc);
        if cap <= 0 then begin
            arc := long_Array1d_create(63);
            fldLexemes := arc;
        end else
        if cap = len then begin
            arn := long_Array1d_create(int((cap shl 1) + 1));
            arraycopyPrimitives(arc, 0, arn, 0, cap);
            fldLexemes := arn;
            arc := arn;
        end;
        fldLexemesCount := len + 1;
        arc[len] := buildLexeme(lineIndex, charIndex, lexemeType, lexemeValueType, lexemeValueIndex);
    end;

    function AVTSource.getLexemeValueTypeInternal(lexeme: long): int;
    var
        lvt: int;
        lvi: int;
        val: int;
    begin
        lvt := extractLexemeValueType(lexeme);
        lvi := extractLexemeValueIndex(lexeme);
        if (lvt = TYPE_BOOLEAN) and ((lvi and $00200000) = 0) then begin
            lvt := TYPE_CHAR;
        end else
        if lvt = TYPE_INT then begin
            val := getInts().itemAt(lvi);
            if (val >= BYTE_MIN_VALUE) and (val <= BYTE_MAX_VALUE) then begin
                lvt := TYPE_BYTE;
            end else
            if (val >= SHORT_MIN_VALUE) and (val <= SHORT_MAX_VALUE) then begin
                lvt := TYPE_SHORT;
            end;
        end;
        result := lvt;
    end;

    function AVTSource.getLength(): int;
    begin
        result := system.length(fldLines);
    end;

    function AVTSource.getLine(index: int): UnicodeString;
    begin
        if (index < 0) or (index >= system.length(fldLines)) then begin
            raise IndexOutOfBoundsException.create('AVTSource.line: ' + msgIndexOutOfBounds);
        end;
        result := fldLines[index];
    end;

    function AVTSource.getStrings(): AVTStringStorage;
    var
        str: AVTStringStorage;
    begin
        str := fldStrings;
        if str = nil then begin
            str := AVTStringStorage.create();
            fldStrings := str;
        end;
        result := str;
    end;

    function AVTSource.getInts(): AVTIntStorage;
    var
        str: AVTIntStorage;
    begin
        str := fldInts;
        if str = nil then begin
            str := AVTIntStorage.create();
            fldInts := str;
        end;
        result := str;
    end;

    function AVTSource.getLongs(): AVTLongStorage;
    var
        str: AVTLongStorage;
    begin
        str := fldLongs;
        if str = nil then begin
            str := AVTLongStorage.create();
            fldLongs := str;
        end;
        result := str;
    end;

    function AVTSource.getFloats(): AVTFloatStorage;
    var
        str: AVTFloatStorage;
    begin
        str := fldFloats;
        if str = nil then begin
            str := AVTFloatStorage.create();
            fldFloats := str;
        end;
        result := str;
    end;

    function AVTSource.getDoubles(): AVTDoubleStorage;
    var
        str: AVTDoubleStorage;
    begin
        str := fldDoubles;
        if str = nil then begin
            str := AVTDoubleStorage.create();
            fldDoubles := str;
        end;
        result := str;
    end;

    function AVTSource.getReals(): AVTRealStorage;
    var
        str: AVTRealStorage;
    begin
        str := fldReals;
        if str = nil then begin
            str := AVTRealStorage.create();
            fldReals := str;
        end;
        result := str;
    end;

    constructor AVTSource.create();
    begin
        inherited create();
        self.fldDeclaredTypesAsVector := Vector.create();
        self.fldDeclaredTypesAsTable := Hashtable.create();
    end;

    constructor AVTSource.create(parentProgramme: AVTProgramme; const fileName: UnicodeString);
    begin
        inherited create();
        self.fldFileName := fileName;
        self.fldSimpleName := stringCopy(fileName, stringLastIndexOf(UnicodeString('/'), fileName) + 1);
        self.fldParentProgramme := parentProgramme;
        self.fldDeclaredTypesAsVector := Vector.create();
        self.fldDeclaredTypesAsTable := Hashtable.create();
    end;

    destructor AVTSource.destroy;
    begin
        fldStrings.free();
        fldInts.free();
        fldLongs.free();
        fldFloats.free();
        fldDoubles.free();
        fldReals.free();
        fldImportedAll.free();
        fldImportedTypes.free();
        fldDeclaredTypesAsVector.free();
        fldDeclaredTypesAsTable.free();
        inherited destroy;
    end;

    procedure AVTSource.afterConstruction();
    var
        app: AVTProgramme;
    begin
        inherited afterConstruction();
        app := fldParentProgramme;
        if app <> nil then app.addSource(self);
    end;

    procedure AVTSource.realize(const lines: UnicodeString_Array1d);
    var
        bcn: int;
        ecn: int;
        idx: int;
        len: int;
        lin: UnicodeString_Array1d;
    begin
        len := system.length(lines);
        bcn := 0;
        ecn := len - 1;
        while (bcn < len) and (system.length(stringTrim(lines[bcn])) <= 0) do inc(bcn);
        while (ecn > bcn) and (system.length(stringTrim(lines[ecn])) <= 0) do dec(ecn);
        lin := UnicodeString_Array1d_create(ecn - bcn + 1);
        for idx := bcn to ecn do begin
            lin[idx - bcn] := stringCopy(lines[idx]);
        end;
        fldLines := lin;
    end;

    procedure AVTSource.realize(vfs: ReadOnlyVirtualFileSystem; const directory: UnicodeString);
    var
        isf: Input;
        tdp: TextDecoder;
    begin
        if vfs = nil then begin
            raise NullPointerException.create('AVTSource.realize: ' + msgNullPointerArgument + 'vfs');
        end;
        tdp := PlainTextCodec.create();
        isf := vfs.openFileForReading(directory + fldFileName);
        try
            tdp.loadFromInputStream(isf);
        finally
            isf.close();
        end;
        fldLines := tdp.getUnicodeStrings();
    end;

    procedure AVTSource.addImportedPackage(package: AVTPackage);
    var
        vec: Vector;
    begin
        if package = nil then begin
            raise NullPointerException.create('AVTSource.addImportedPackage: ' + msgNullPointerArgument + 'package');
        end;
        vec := fldImportedAll;
        if vec = nil then begin
            vec := Vector.create();
            fldImportedAll := vec;
        end;
        vec.append(ValueOfObject.create(package, false));
    end;

    procedure AVTSource.addImportedType(atype: AVTTypeStructured);
    var
        val: Value;
        vec: Vector;
        tab: Hashtable;
    begin
        if atype = nil then begin
            raise NullPointerException.create('AVTSource.addImportedType: ' + msgNullPointerArgument + 'atype');
        end;
        vec := fldImportedAll;
        if vec = nil then begin
            vec := Vector.create();
            fldImportedAll := vec;
        end;
        tab := fldImportedTypes;
        if tab = nil then begin
            tab := Hashtable.create();
            fldImportedTypes := tab;
        end;
        val := ValueOfObject.create(atype, false);
        vec.append(val);
        tab.put(ValueOfAnsiString.create(atype.fldSimpleName), val);
    end;

    procedure AVTSource.addLexeme(lineIndex, charIndex, lexemeType: int);
    begin
        addLexemeInternal(lineIndex, charIndex, lexemeType, TYPE_NONE, 0);
    end;

    procedure AVTSource.addLexemeBoolean(lineIndex, charIndex, lexemeType: int; const lexemeValue: boolean);
    var
        lvi: int;
    begin
        if lexemeValue then begin
            lvi := $00300000;
        end else begin
            lvi := $00200000;
        end;
        addLexemeInternal(lineIndex, charIndex, lexemeType, TYPE_BOOLEAN, lvi);
    end;

    procedure AVTSource.addLexemeChar(lineIndex, charIndex, lexemeType: int; const lexemeValue: wchar);
    begin
        addLexemeInternal(lineIndex, charIndex, lexemeType, TYPE_BOOLEAN, int(lexemeValue));
    end;

    procedure AVTSource.addLexemeByte(lineIndex, charIndex, lexemeType: int; const lexemeValue: byte);
    begin
        addLexemeInternal(lineIndex, charIndex, lexemeType, TYPE_INT, getInts().indexAcquire(lexemeValue));
    end;

    procedure AVTSource.addLexemeShort(lineIndex, charIndex, lexemeType: int; const lexemeValue: short);
    begin
        addLexemeInternal(lineIndex, charIndex, lexemeType, TYPE_INT, getInts().indexAcquire(lexemeValue));
    end;

    procedure AVTSource.addLexemeInt(lineIndex, charIndex, lexemeType: int; const lexemeValue: int);
    begin
        addLexemeInternal(lineIndex, charIndex, lexemeType, TYPE_INT, getInts().indexAcquire(lexemeValue));
    end;

    procedure AVTSource.addLexemeLong(lineIndex, charIndex, lexemeType: int; const lexemeValue: long);
    begin
        addLexemeInternal(lineIndex, charIndex, lexemeType, TYPE_LONG, getLongs().indexAcquire(lexemeValue));
    end;

    procedure AVTSource.addLexemeFloat(lineIndex, charIndex, lexemeType: int; const lexemeValue: float);
    begin
        addLexemeInternal(lineIndex, charIndex, lexemeType, TYPE_FLOAT, getFloats().indexAcquire(lexemeValue));
    end;

    procedure AVTSource.addLexemeDouble(lineIndex, charIndex, lexemeType: int; const lexemeValue: double);
    begin
        addLexemeInternal(lineIndex, charIndex, lexemeType, TYPE_DOUBLE, getDoubles().indexAcquire(lexemeValue));
    end;

    procedure AVTSource.addLexemeReal(lineIndex, charIndex, lexemeType: int; const lexemeValue: real);
    begin
        addLexemeInternal(lineIndex, charIndex, lexemeType, TYPE_REAL, getReals().indexAcquire(lexemeValue));
    end;

    procedure AVTSource.addLexemeAnsiString(lineIndex, charIndex, lexemeType: int; const lexemeValue: AnsiString);
    begin
        addLexemeInternal(lineIndex, charIndex, lexemeType, TYPE_STRING, getStrings().indexAcquire(lexemeValue));
    end;

    procedure AVTSource.addLexemeUnicodeString(lineIndex, charIndex, lexemeType: int; const lexemeValue: UnicodeString);
    begin
        addLexemeInternal(lineIndex, charIndex, lexemeType, TYPE_STRING, getStrings().indexAcquire(lexemeValue));
    end;

    function AVTSource.getLexemeInfo(position: int): int_Array1d;
    var
        lex: long;
    begin
        if (position < 0) or (position >= fldLexemesCount) then begin
            raise IndexOutOfBoundsException.create('AVTSource.getLexemeInfo: ' + msgIndexOutOfBounds);
        end;
        lex := fldLexemes[position];
        result := int_Array1d_create([
            extractLexemeType(lex), getLexemeValueTypeInternal(lex),
            extractLineIndex(lex), extractCharIndex(lex)
        ]);
    end;

    function AVTSource.getLexemeType(position: int): int;
    begin
        if (position < 0) or (position >= fldLexemesCount) then begin
            raise IndexOutOfBoundsException.create('AVTSource.getLexemeType: ' + msgIndexOutOfBounds);
        end;
        result := extractLexemeType(fldLexemes[position]);
    end;

    function AVTSource.getLexemeValueType(position: int): int;
    begin
        if (position < 0) or (position >= fldLexemesCount) then begin
            raise IndexOutOfBoundsException.create('AVTSource.getLexemeValueType: ' + msgIndexOutOfBounds);
        end;
        result := getLexemeValueTypeInternal(fldLexemes[position]);
    end;

    function AVTSource.getLexemeLineIndex(position: int): int;
    begin
        if (position < 0) or (position >= fldLexemesCount) then begin
            raise IndexOutOfBoundsException.create('AVTSource.getLexemeLineIndex: ' + msgIndexOutOfBounds);
        end;
        result := extractLineIndex(fldLexemes[position]);
    end;

    function AVTSource.getLexemeCharIndex(position: int): int;
    begin
        if (position < 0) or (position >= fldLexemesCount) then begin
            raise IndexOutOfBoundsException.create('AVTSource.getLexemeCharIndex: ' + msgIndexOutOfBounds);
        end;
        result := extractCharIndex(fldLexemes[position]);
    end;

    function AVTSource.getLexemeBoolean(position: int): boolean;
    var
        lvt: int;
        lex: long;
    begin
        if (position < 0) or (position >= fldLexemesCount) then begin
            raise IndexOutOfBoundsException.create('AVTSource.getLexemeBoolean: ' + msgIndexOutOfBounds);
        end;
        lex := fldLexemes[position];
        lvt := getLexemeValueTypeInternal(lex);
        if lvt = TYPE_BOOLEAN then begin
            result := (extractLexemeValueIndex(lex) and $00100000) <> 0;
            exit;
        end;
        raise IllegalLexemeValueTypeException.create('AVTSource.getLexemeBoolean: ' + msgIllegalLexemeValueType);
    end;

    function AVTSource.getLexemeChar(position: int): wchar;
    var
        lvt: int;
        lex: long;
    begin
        if (position < 0) or (position >= fldLexemesCount) then begin
            raise IndexOutOfBoundsException.create('AVTSource.getLexemeChar: ' + msgIndexOutOfBounds);
        end;
        lex := fldLexemes[position];
        lvt := getLexemeValueTypeInternal(lex);
        if lvt = TYPE_CHAR then begin
            result := wchar(extractLexemeValueIndex(lex));
            exit;
        end;
        raise IllegalLexemeValueTypeException.create('AVTSource.getLexemeChar: ' + msgIllegalLexemeValueType);
    end;

    function AVTSource.getLexemeByte(position: int): int;
    var
        lvt: int;
        lex: long;
    begin
        if (position < 0) or (position >= fldLexemesCount) then begin
            raise IndexOutOfBoundsException.create('AVTSource.getLexemeByte: ' + msgIndexOutOfBounds);
        end;
        lex := fldLexemes[position];
        lvt := getLexemeValueTypeInternal(lex);
        if lvt = TYPE_BYTE then begin
            result := getInts().itemAt(extractLexemeValueIndex(lex));
            exit;
        end;
        raise IllegalLexemeValueTypeException.create('AVTSource.getLexemeByte: ' + msgIllegalLexemeValueType);
    end;

    function AVTSource.getLexemeShort(position: int): int;
    var
        lvt: int;
        lex: long;
    begin
        if (position < 0) or (position >= fldLexemesCount) then begin
            raise IndexOutOfBoundsException.create('AVTSource.getLexemeShort: ' + msgIndexOutOfBounds);
        end;
        lex := fldLexemes[position];
        lvt := getLexemeValueTypeInternal(lex);
        if (lvt = TYPE_BYTE) or (lvt = TYPE_SHORT) then begin
            result := getInts().itemAt(extractLexemeValueIndex(lex));
            exit;
        end;
        raise IllegalLexemeValueTypeException.create('AVTSource.getLexemeShort: ' + msgIllegalLexemeValueType);
    end;

    function AVTSource.getLexemeInt(position: int): int;
    var
        lvt: int;
        lex: long;
    begin
        if (position < 0) or (position >= fldLexemesCount) then begin
            raise IndexOutOfBoundsException.create('AVTSource.getLexemeInt: ' + msgIndexOutOfBounds);
        end;
        lex := fldLexemes[position];
        lvt := getLexemeValueTypeInternal(lex);
        if (lvt = TYPE_BYTE) or (lvt = TYPE_SHORT) or (lvt = TYPE_INT) then begin
            result := getInts().itemAt(extractLexemeValueIndex(lex));
            exit;
        end;
        raise IllegalLexemeValueTypeException.create('AVTSource.getLexemeInt: ' + msgIllegalLexemeValueType);
    end;

    function AVTSource.getLexemeLong(position: int): long;
    var
        lvt: int;
        lex: long;
    begin
        if (position < 0) or (position >= fldLexemesCount) then begin
            raise IndexOutOfBoundsException.create('AVTSource.getLexemeLong: ' + msgIndexOutOfBounds);
        end;
        lex := fldLexemes[position];
        lvt := getLexemeValueTypeInternal(lex);
        if (lvt = TYPE_BYTE) or (lvt = TYPE_SHORT) or (lvt = TYPE_INT) then begin
            result := getInts().itemAt(extractLexemeValueIndex(lex));
            exit;
        end;
        if lvt = TYPE_LONG then begin
            result := getLongs().itemAt(extractLexemeValueIndex(lex));
            exit;
        end;
        raise IllegalLexemeValueTypeException.create('AVTSource.getLexemeLong: ' + msgIllegalLexemeValueType);
    end;

    function AVTSource.getLexemeFloat(position: int): float;
    var
        lvt: int;
        lex: long;
    begin
        if (position < 0) or (position >= fldLexemesCount) then begin
            raise IndexOutOfBoundsException.create('AVTSource.getLexemeFloat: ' + msgIndexOutOfBounds);
        end;
        lex := fldLexemes[position];
        lvt := getLexemeValueTypeInternal(lex);
        if lvt = TYPE_FLOAT then begin
            result := getFloats().itemAt(extractLexemeValueIndex(lex));
            exit;
        end;
        raise IllegalLexemeValueTypeException.create('AVTSource.getLexemeFloat: ' + msgIllegalLexemeValueType);
    end;

    function AVTSource.getLexemeDouble(position: int): double;
    var
        lvt: int;
        lex: long;
    begin
        if (position < 0) or (position >= fldLexemesCount) then begin
            raise IndexOutOfBoundsException.create('AVTSource.getLexemeDouble: ' + msgIndexOutOfBounds);
        end;
        lex := fldLexemes[position];
        lvt := getLexemeValueTypeInternal(lex);
        if lvt = TYPE_FLOAT then begin
            result := getFloats().itemAt(extractLexemeValueIndex(lex));
            exit;
        end;
        if lvt = TYPE_DOUBLE then begin
            result := getDoubles().itemAt(extractLexemeValueIndex(lex));
            exit;
        end;
        raise IllegalLexemeValueTypeException.create('AVTSource.getLexemeDouble: ' + msgIllegalLexemeValueType);
    end;

    function AVTSource.getLexemeReal(position: int): real;
    var
        lvt: int;
        lex: long;
    begin
        if (position < 0) or (position >= fldLexemesCount) then begin
            raise IndexOutOfBoundsException.create('AVTSource.getLexemeReal: ' + msgIndexOutOfBounds);
        end;
        lex := fldLexemes[position];
        lvt := getLexemeValueTypeInternal(lex);
        if lvt = TYPE_FLOAT then begin
            result := getFloats().itemAt(extractLexemeValueIndex(lex));
            exit;
        end;
        if lvt = TYPE_DOUBLE then begin
            result := getDoubles().itemAt(extractLexemeValueIndex(lex));
            exit;
        end;
        if lvt = TYPE_REAL then begin
            result := getReals().itemAt(extractLexemeValueIndex(lex));
            exit;
        end;
        raise IllegalLexemeValueTypeException.create('AVTSource.getLexemeReal: ' + msgIllegalLexemeValueType);
    end;

    function AVTSource.getLexemeAnsiString(position: int): AnsiString;
    var
        lvt: int;
        lex: long;
    begin
        if (position < 0) or (position >= fldLexemesCount) then begin
            raise IndexOutOfBoundsException.create('AVTSource.getLexemeAnsiString: ' + msgIndexOutOfBounds);
        end;
        lex := fldLexemes[position];
        lvt := getLexemeValueTypeInternal(lex);
        if lvt = TYPE_STRING then begin
            result := stringToUTF8(getStrings().itemAt(extractLexemeValueIndex(lex)));
            exit;
        end;
        raise IllegalLexemeValueTypeException.create('AVTSource.getLexemeAnsiString: ' + msgIllegalLexemeValueType);
    end;

    function AVTSource.getLexemeUnicodeString(position: int): UnicodeString;
    var
        lvt: int;
        lex: long;
    begin
        if (position < 0) or (position >= fldLexemesCount) then begin
            raise IndexOutOfBoundsException.create('AVTSource.getLexemeUnicodeString: ' + msgIndexOutOfBounds);
        end;
        lex := fldLexemes[position];
        lvt := getLexemeValueTypeInternal(lex);
        if lvt = TYPE_STRING then begin
            result := getStrings().itemAt(extractLexemeValueIndex(lex));
            exit;
        end;
        raise IllegalLexemeValueTypeException.create('AVTSource.getLexemeUnicodeString: ' + msgIllegalLexemeValueType);
    end;

    function AVTSource.getLexemesCount(): int;
    begin
        result := fldLexemesCount;
    end;

    function AVTSource.getDeclaredType(const simpleName: AnsiString): AVTTypeStructured;
    var
        val: Value;
    begin
        val := fldDeclaredTypesAsTable.get(ValueOfAnsiString.create(simpleName));
        if val = nil then begin
            result := nil;
            exit;
        end;
        result := val.objectValue() as AVTTypeStructured;
    end;

    function AVTSource.getImportedType(const simpleName: AnsiString): AVTTypeStructured;
    var
        val: Value;
        tab: Hashtable;
    begin
        tab := fldImportedTypes;
        if tab = nil then begin
            result := nil;
            exit;
        end;
        val := tab.get(ValueOfAnsiString.create(simpleName));
        if val = nil then begin
            result := nil;
            exit;
        end;
        result := val.objectValue() as AVTTypeStructured;
    end;

    function AVTSource.findImportedType(const simpleName: AnsiString): AVTTypeStructured;
    var
        idx: int;
        len: int;
        tpl: Vector;
        iml: Vector;
        obj: TObject;
        tpa: AVTType;
        tpc: AVTTypeStructured;
        tpf: AVTTypeStructured;
    begin
        fldAmbiguousName := false;
        iml := fldImportedAll;
        if iml = nil then begin
            result := nil;
            exit;
        end;
        tpl := Vector.create();
        try
            for idx := iml.size() - 1 downto 0 do begin
                obj := iml.elementAt(idx).objectValue();
                if not(obj is AVTPackage) then continue;
                tpa := AVTPackage(obj).getType(simpleName);
                if not(tpa is AVTTypeStructured) then continue;
                tpl.append(ValueOfObject.create(tpa, false));
            end;
            tpf := nil;
            len := tpl.size();
            for idx := len - 1 downto 0 do begin
                tpc := tpl.elementAt(idx).objectValue() as AVTTypeStructured;
                if tpf <> nil then begin
                    fldAmbiguousName := true;
                    result := nil;
                    exit;
                end;
                tpf := tpc;
            end;
            if (tpf = nil) and (len > 0) then begin
                tpf := tpl.firstElement().objectValue() as AVTTypeStructured;
            end;
        finally
            tpl.free();
        end;
        result := tpf;
    end;

    function AVTSource.findImportedType(const simpleName: AnsiString; from: AVTTypeStructured; position: int): AVTTypeStructured;
    var
        idx: int;
        len: int;
        tpl: Vector;
        iml: Vector;
        obj: TObject;
        tpa: AVTType;
        tpc: AVTTypeStructured;
        tpf: AVTTypeStructured;
    begin
        iml := fldImportedAll;
        if iml = nil then begin
            result := nil;
            exit;
        end;
        tpl := Vector.create();
        try
            for idx := iml.size() - 1 downto 0 do begin
                obj := iml.elementAt(idx).objectValue();
                if not(obj is AVTPackage) then continue;
                tpa := AVTPackage(obj).getType(simpleName);
                if not(tpa is AVTTypeStructured) then continue;
                tpl.append(ValueOfObject.create(tpa, false));
            end;
            tpf := nil;
            len := tpl.size();
            for idx := len - 1 downto 0 do begin
                tpc := tpl.elementAt(idx).objectValue() as AVTTypeStructured;
                if tpc.isVisible(nil, from) then begin
                    if tpf <> nil then begin
                        raise AVTCompilerException.create('The type ' + simpleName + ' is ambiguous', from.source, position);
                    end;
                    tpf := tpc;
                end;
            end;
            if (tpf = nil) and (len > 0) then begin
                tpf := tpl.firstElement().objectValue() as AVTTypeStructured;
            end;
        finally
            tpl.free();
        end;
        result := tpf;
    end;

    function AVTSource.isImportedPackage(package: AVTPackage): boolean;
    var
        vec: Vector;
    begin
        vec := fldImportedAll;
        result := (vec <> nil) and vec.contains(ValueOfObject.create(package, false));
    end;

    function AVTSource.importedItems(): Enumeration;
    var
        vec: Vector;
    begin
        vec := fldImportedAll;
        if vec = nil then begin
            result := EmptyEnumerator.create();
            exit;
        end;
        result := vec.elements();
    end;

    function AVTSource.declaredTypes(): Enumeration;
    begin
        result := fldDeclaredTypesAsVector.elements();
    end;
{%endregion}

{%region AVTItem }
    function AVTItem.getVisibility(): int;
    begin
        result := fldFlags and MASK_VISIBILITY;
    end;

    constructor AVTItem.create(parentItem: AVTItem; flags: int; const simpleName: AnsiString; const documentation: UnicodeString);
    begin
        inherited create();
        self.fldFlags := flags;
        self.fldParentItem := parentItem;
        self.fldSimpleName := simpleName;
        self.fldDocumentation := documentation;
    end;

    procedure AVTItem.afterConstruction();
    begin
        inherited afterConstruction();
        self.fldFullName := getFullName();
    end;

    function AVTItem.toString(): AnsiString;
    begin
        result := fldFullName;
    end;

    function AVTItem.isStatic(): boolean;
    begin
        result := (fldFlags and FLAG_STATIC) <> 0;
    end;

    function AVTItem.isFinal(): boolean;
    begin
        result := (fldFlags and FLAG_FINAL) <> 0;
    end;

    function AVTItem.isAbstract(): boolean;
    begin
        result := (fldFlags and FLAG_ABSTRACT) <> 0;
    end;

    function AVTItem.isSynthetic(): boolean;
    begin
        result := (fldFlags and FLAG_SYNTHETIC) <> 0;
    end;
{%endregion}

{%region AVTPackage }
    procedure AVTPackage.addType(atype: AVTType);
    begin
        fldTypesAsTable.put(ValueOfAnsiString.create(atype.fldSimpleName), ValueOfObject.create(atype));
        fldTypesAsVector.append(ValueOfObject.create(atype, false));
    end;

    procedure AVTPackage.addSource(source: AVTSource);
    begin
        fldSources.put(ValueOfUnicodeString.create(source.fldFileName), ValueOfObject.create(source, false));
    end;

    procedure AVTPackage.addSubpackage(subpackage: AVTPackage);
    var
        tab: Hashtable;
    begin
        tab := fldSubpackages;
        if tab = nil then begin
            tab := Hashtable.create();
            fldSubpackages := tab;
        end;
        tab.put(ValueOfAnsiString.create(subpackage.fldSimpleName), ValueOfObject.create(subpackage, false));
    end;

    function AVTPackage.getFullName(): AnsiString;
    var
        pck: AVTPackage;
    begin
        pck := fldParentPackage;
        if pck = nil then begin
            result := fldSimpleName;
            exit;
        end;
        result := pck.fldFullName + '.' + fldSimpleName;
    end;

    constructor AVTPackage.create(parentProgramme: AVTProgramme; parentPackage: AVTPackage; const simpleName: AnsiString; const documentation: UnicodeString);
    begin
        inherited create(parentPackage, FLAG_PUBLIC, simpleName, documentation);
        self.fldSources := Hashtable.create();
        self.fldTypesAsTable := Hashtable.create();
        self.fldTypesAsVector := Vector.create();
        self.fldParentPackage := parentPackage;
        self.fldParentProgramme := parentProgramme;
    end;

    destructor AVTPackage.destroy;
    begin
        fldSources.free();
        fldSubpackages.free();
        fldTypesAsTable.free();
        fldTypesAsVector.free();
        inherited destroy;
    end;

    procedure AVTPackage.afterConstruction();
    var
        pck: AVTPackage;
        app: AVTProgramme;
    begin
        inherited afterConstruction();
        app := fldParentProgramme;
        if app <> nil then app.addPackage(self);
        pck := fldParentPackage;
        if pck <> nil then pck.addSubpackage(self);
    end;

    function AVTPackage.getSubpackage(const simpleName: AnsiString): AVTPackage;
    var
        val: value;
        tab: Hashtable;
    begin
        tab := fldSubpackages;
        if tab = nil then begin
            result := nil;
            exit;
        end;
        val := tab.get(ValueOfAnsiString.create(simpleName));
        if val = nil then begin
            result := nil;
            exit;
        end;
        result := val.objectValue() as AVTPackage;
    end;

    function AVTPackage.getSource(const fileName: UnicodeString): AVTSource;
    var
        val: Value;
    begin
        val := fldSources.get(ValueOfUnicodeString.create(fileName));
        if val = nil then begin
            result := nil;
            exit;
        end;
        result := val.objectValue() as AVTSource;
    end;

    function AVTPackage.getType(const simpleName: AnsiString; caseSensitive: boolean): AVTType;
    var
        val: Value;
        typ: AVTType;
        lowerCaseName: AnsiString;
    begin
        if not caseSensitive then begin
            lowerCaseName := stringToLowerCase(simpleName);
            with fldTypesAsVector.elements() do while hasMoreElements() do begin
                typ := nextElement().objectValue() as AVTType;
                if stringToLowerCase(typ.simpleName) = lowerCaseName then begin
                    result := typ;
                    exit;
                end;
            end;
            result := nil;
            exit;
        end;
        val := fldTypesAsTable.get(ValueOfAnsiString.create(simpleName));
        if val = nil then begin
            result := nil;
            exit;
        end;
        result := val.objectValue() as AVTType;
    end;

    function AVTPackage.subpackages(): Enumeration;
    var
        tab: Hashtable;
    begin
        tab := fldSubpackages;
        if tab = nil then begin
            result := EmptyEnumerator.create();
            exit;
        end;
        result := tab.elements();
    end;

    function AVTPackage.sources(): Enumeration;
    begin
        result := fldSources.elements();
    end;

    function AVTPackage.types(): Enumeration;
    begin
        result := fldTypesAsVector.elements();
    end;
{%endregion}

{%region AVTItemExt }
    function AVTItemExt.getFullName(): AnsiString;
    begin
        result := fldSimpleName;
    end;

    function AVTItemExt.getAvtcType(): AnsiString;
    begin
        result := '';
    end;

    function AVTItemExt.getFasmShortName(): AnsiString;
    begin
        result := fldFasmFullName;
    end;

    constructor AVTItemExt.create(parentItem: AVTItem; flags: int; const simpleName: AnsiString; source: AVTSource; declarationPosition: int; const documentation: UnicodeString);
    begin
        inherited create(parentItem, flags, simpleName, documentation);
        self.fldImplementationPosition := -1;
        self.fldDeclarationPosition := declarationPosition;
        self.fldSource := source;
    end;

    procedure AVTItemExt.afterConstruction();
    begin
        inherited afterConstruction();
        fldAvtcType := getAvtcType();
        fldFasmFullName := getFasmFullName();
        fldFasmShortName := getFasmShortName();
    end;

    function AVTItemExt.isVisible(target, from: AVTTypeStructured): boolean;
    begin
        result := true;
    end;
{%endregion}

{%region AVTType }
    constructor AVTType.create(parentItem: AVTItem; flags: int; const simpleName: AnsiString; source: AVTSource; declarationPosition: int; const documentation: UnicodeString);
    begin
        inherited create(parentItem, flags, simpleName, source, declarationPosition, documentation);
        if parentItem is AVTPackage then begin
            self.fldPackage := AVTPackage(parentItem);
        end;
    end;

    procedure AVTType.afterConstruction();
    var
        pck: AVTPackage;
    begin
        inherited afterConstruction();
        fldFieldWidth := getFieldWidth();
        fldFasmArgument := getFasmArgument();
        pck := fldPackage;
        if pck <> nil then pck.addType(self);
    end;

    function AVTType.isVisible(target, from: AVTTypeStructured): boolean;
    begin
        if from = nil then begin
            raise NullPointerException.create('AVTType.isVisible: ' + msgNullPointerArgument + 'from');
        end;
        case getVisibility() of
        AVT_PUBLISHED, AVT_PUBLIC:
            result := true;
        AVT_PACKAGE:
            result := self.fldPackage = from.fldPackage;
        AVT_SOURCE:
            { На будущее: совпадать должны не сами исходные тексты (obj1.fldSource = obj2.fldSource),
              а их пакеты и простые имена ((source1.fldPackage = source2.fldPackage) and (source1.fldSimpleName = source2.fldSimpleName)) }
            result := self.fldSource = from.fldSource;
        else
            result := false;
        end;
    end;

    function AVTType.isPrimitive(): boolean;
    begin
        result := false;
    end;

    function AVTType.isStackable(): boolean;
    begin
        result := false;
    end;

    function AVTType.isBoolean(): boolean;
    begin
        result := false;
    end;

    function AVTType.isInt(): boolean;
    begin
        result := false;
    end;

    function AVTType.isNumeric(): boolean;
    begin
        result := false;
    end;

    function AVTType.isCompound(): boolean;
    begin
        result := false;
    end;

    function AVTType.isInterface(): boolean;
    begin
        result := false;
    end;

    function AVTType.isService(): boolean;
    begin
        result := false;
    end;

    function AVTType.isStruct(): boolean;
    begin
        result := false;
    end;

    function AVTType.isClass(): boolean;
    begin
        result := false;
    end;

    function AVTType.isArray(): boolean;
    begin
        result := false;
    end;

    function AVTType.isVoid(): boolean;
    begin
        result := false;
    end;

    function AVTType.isDword(): boolean;
    begin
        result := false;
    end;

    function AVTType.isQword(): boolean;
    begin
        result := false;
    end;

    function AVTType.isTword(): boolean;
    begin
        result := false;
    end;

    function AVTType.isXword(): boolean;
    begin
        result := false;
    end;

    function AVTType.isYword(): boolean;
    begin
        result := false;
    end;

    function AVTType.isZword(): boolean;
    begin
        result := false;
    end;
{%endregion}

{%region AVTTypeInvalid }
    class function AVTTypeInvalid.getInstance(): AVTTypeInvalid;
    begin
        if instance = nil then begin
            instance := AVTTypeInvalid.create();
        end;
        result := instance;
    end;

    function AVTTypeInvalid.getFieldWidth(): int;
    begin
        result := 0;
    end;

    function AVTTypeInvalid.getFasmFullName(): AnsiString;
    begin
        result := '';
    end;

    function AVTTypeInvalid.getFasmArgument(): AnsiString;
    begin
        result := '';
    end;

    constructor AVTTypeInvalid.create();
    begin
        inherited create(nil, 0, '<invalid>');
    end;

    function AVTTypeInvalid.getCommonType(anot: AVTType): AVTType;
    begin
        result := self;
    end;

    function AVTTypeInvalid.isConvertableFrom(from: AVTType): boolean;
    begin
        result := false;
    end;

    function AVTTypeInvalid.isAssignableFrom(from: AVTType): boolean;
    begin
        result := false;
    end;
{%endregion}

{%region AVTTypePrimitive }
    class function AVTTypePrimitive.getName(primitiveKind: int): AnsiString;
    begin
        case primitiveKind of
        AVT_VOID:    result := 'void';
        AVT_BOOLEAN: result := 'boolean';
        AVT_CHAR:    result := 'char';
        AVT_REAL:    result := 'real';
        AVT_BYTE:    result := 'byte';
        AVT_BYTE2:   result := 'byte2';
        AVT_BYTE4:   result := 'byte4';
        AVT_BYTE8:   result := 'byte8';
        AVT_SHORT:   result := 'short';
        AVT_SHORT2:  result := 'short2';
        AVT_SHORT4:  result := 'short4';
        AVT_SHORT8:  result := 'short8';
        AVT_INT:     result := 'int';
        AVT_INT2:    result := 'int2';
        AVT_INT4:    result := 'int4';
        AVT_INT8:    result := 'int8';
        AVT_LONG:    result := 'long';
        AVT_LONG2:   result := 'long2';
        AVT_LONG4:   result := 'long4';
        AVT_LONG8:   result := 'long8';
        AVT_FLOAT:   result := 'float';
        AVT_FLOAT2:  result := 'float2';
        AVT_FLOAT4:  result := 'float4';
        AVT_FLOAT8:  result := 'float8';
        AVT_DOUBLE:  result := 'double';
        AVT_DOUBLE2: result := 'double2';
        AVT_DOUBLE4: result := 'double4';
        AVT_DOUBLE8: result := 'double8';
        else         result := '';
        end;
    end;

    function AVTTypePrimitive.getCompoundBase(): int;
    var
        knd: int;
    begin
        knd := fldPrimitiveKind;
        if (knd < AVT_BYTE) or (knd > AVT_DOUBLE8) then begin
            result := knd;
            exit;
        end;
        result := knd and (-4);
    end;

    function AVTTypePrimitive.getCompoundLength(): int;
    var
        knd: int;
    begin
        knd := fldPrimitiveKind;
        if (knd < AVT_BYTE) or (knd > AVT_DOUBLE8) then begin
            result := 1;
            exit;
        end;
        result := 1 shl (knd and 3);
    end;

    function AVTTypePrimitive.getFieldWidth(): int;
    begin
        case fldPrimitiveKind of
        AVT_BOOLEAN, AVT_BYTE:
            result := 1;
        AVT_CHAR, AVT_BYTE2, AVT_SHORT:
            result := 2;
        AVT_BYTE4, AVT_SHORT2, AVT_INT, AVT_FLOAT:
            result := 4;
        AVT_BYTE8, AVT_SHORT4, AVT_INT2, AVT_LONG, AVT_FLOAT2, AVT_DOUBLE:
            result := 8;
        AVT_SHORT8, AVT_INT4, AVT_LONG2, AVT_FLOAT4, AVT_DOUBLE2:
            result := 16;
        AVT_INT8, AVT_LONG4, AVT_FLOAT8, AVT_DOUBLE4:
            result := 32;
        AVT_LONG8, AVT_DOUBLE8:
            result := 64;
        AVT_REAL:
            result := 10;
        else
            result := 0;
        end;
    end;

    function AVTTypePrimitive.getAvtcType(): AnsiString;
    begin
        case fldPrimitiveKind of
        AVT_VOID:    result := 'V';
        AVT_BOOLEAN: result := 'Z';
        AVT_CHAR:    result := 'C';
        AVT_REAL:    result := 'R';
        AVT_BYTE:    result := 'B';
        AVT_BYTE2:   result := 'B2';
        AVT_BYTE4:   result := 'B4';
        AVT_BYTE8:   result := 'B8';
        AVT_SHORT:   result := 'S';
        AVT_SHORT2:  result := 'S2';
        AVT_SHORT4:  result := 'S4';
        AVT_SHORT8:  result := 'S8';
        AVT_INT:     result := 'I';
        AVT_INT2:    result := 'I2';
        AVT_INT4:    result := 'I4';
        AVT_INT8:    result := 'I8';
        AVT_LONG:    result := 'J';
        AVT_LONG2:   result := 'J2';
        AVT_LONG4:   result := 'J4';
        AVT_LONG8:   result := 'J8';
        AVT_FLOAT:   result := 'F';
        AVT_FLOAT2:  result := 'F2';
        AVT_FLOAT4:  result := 'F4';
        AVT_FLOAT8:  result := 'F8';
        AVT_DOUBLE:  result := 'D';
        AVT_DOUBLE2: result := 'D2';
        AVT_DOUBLE4: result := 'D4';
        AVT_DOUBLE8: result := 'D8';
        else
            result := inherited getAvtcType();
        end;
    end;

    function AVTTypePrimitive.getFasmFullName(): AnsiString;
    begin
        result := 'primitive$' + fldSimpleName;
    end;

    function AVTTypePrimitive.getFasmArgument(): AnsiString;
    begin
        result := fldSimpleName;
    end;

    constructor AVTTypePrimitive.create(parentPackage: AVTPackage; primitiveKind: int);
    begin
        inherited create(parentPackage, FLAG_PUBLIC or FLAG_FINAL or FLAG_PRIMITIVE, getName(primitiveKind));
        self.fldPrimitiveKind := primitiveKind;
    end;

    function AVTTypePrimitive.getCommonType(anot: AVTType): AVTType;
    var
        cb0: int;
        cl0: int;
        cb1: int;
        cl1: int;
        cbr: int;
        clr: int;
    begin
        if not(anot is AVTTypePrimitive) then begin
            result := AVTTypeInvalid.getInstance();
            exit;
        end;
        cb0 := getCompoundBase();
        if cb0 >= AVT_BYTE then begin
            cl0 := fldPrimitiveKind and 3;
        end else begin
            cl0 := 0;
        end;
        with AVTTypePrimitive(anot) do begin
            cb1 := getCompoundBase();
            if cb1 >= AVT_BYTE then begin
                cl1 := fldPrimitiveKind and 3;
            end else begin
                cl1 := 0;
            end;
        end;
        if (cb0 = AVT_BOOLEAN) or (cb1 = AVT_BOOLEAN) or (cb0 = AVT_VOID) or (cb1 = AVT_VOID) then begin
            if (cb0 = AVT_BOOLEAN) and (cb1 = AVT_BOOLEAN) then begin
                result := self;
                exit;
            end;
            result := AVTTypeInvalid.getInstance();
            exit;
        end;
        if cb0 = AVT_CHAR then cb0 := AVT_INT;
        if cb1 = AVT_CHAR then cb1 := AVT_INT;
        case cb0 of
        AVT_BYTE: begin
            cbr := cb1;
        end;
        AVT_SHORT: begin
            if cb1 = AVT_BYTE then begin
                cbr := AVT_SHORT;
            end else begin
                cbr := cb1;
            end;
        end;
        AVT_INT: begin
            if (cb1 = AVT_BYTE) or (cb1 = AVT_SHORT) then begin
                cbr := AVT_INT;
            end else
            if cb1 = AVT_FLOAT then begin
                cbr := AVT_DOUBLE;
            end else begin
                cbr := cb1;
            end;
        end;
        AVT_LONG: begin
            if (cb1 = AVT_FLOAT) or (cb1 = AVT_DOUBLE) or (cb1 = AVT_REAL) then begin
                cbr := AVT_REAL;
            end else begin
                cbr := AVT_LONG;
            end;
        end;
        AVT_FLOAT: begin
            if (cb1 = AVT_BYTE) or (cb1 = AVT_SHORT) or (cb1 = AVT_FLOAT) then begin
                cbr := AVT_FLOAT;
            end else
            if (cb1 = AVT_INT) or (cb1 = AVT_DOUBLE) then begin
                cbr := AVT_DOUBLE;
            end else begin
                cbr := AVT_REAL;
            end;
        end;
        AVT_DOUBLE: begin
            if (cb1 = AVT_LONG) or (cb1 = AVT_REAL) then begin
                cbr := AVT_REAL;
            end else begin
                cbr := AVT_DOUBLE;
            end;
        end;
        AVT_REAL: begin
            cbr := AVT_REAL;
        end
        else
            cbr := 0;
        end;
        clr := intMax(cl0, cl1);
        if (cbr = 0) or (cbr = AVT_REAL) and (clr > 0) then begin
            result := AVTTypeInvalid.getInstance();
            exit;
        end;
        result := fldPackage.fldParentProgramme.fldSystemPackage.getType(getName(cbr + clr));
    end;

    function AVTTypePrimitive.isConvertableFrom(from: AVTType): boolean;
    var
        cb0: int;
        cl0: int;
        cb1: int;
        cl1: int;
    begin
        if not(from is AVTTypePrimitive) then begin
            result := false;
            exit;
        end;
        cb0 := getCompoundBase();
        cl0 := getCompoundLength();
        with AVTTypePrimitive(from) do begin
            cb1 := getCompoundBase();
            cl1 := getCompoundLength();
        end;
        case cb0 of
        AVT_BOOLEAN, AVT_CHAR:
            result := cb1 = cb0;
        AVT_REAL:
            result := (cb1 >= AVT_CHAR) and (cb1 <= AVT_DOUBLE) and (cl1 = 1);
        AVT_BYTE:
            result := (cb1 = AVT_BYTE) and (cl1 <= cl0);
        AVT_SHORT:
            result := (cb1 >= AVT_BYTE) and (cb1 <= AVT_SHORT) and (cl1 <= cl0);
        AVT_INT:
            result := ((cb1 = AVT_CHAR) or (cb1 >= AVT_BYTE) and (cb1 <= AVT_INT)) and (cl1 <= cl0);
        AVT_LONG:
            result := ((cb1 = AVT_CHAR) or (cb1 >= AVT_BYTE) and (cb1 <= AVT_LONG)) and (cl1 <= cl0);
        AVT_FLOAT:
            result := ((cb1 = AVT_CHAR) or (cb1 >= AVT_BYTE) and (cb1 <= AVT_SHORT) or (cb1 = AVT_FLOAT)) and (cl1 <= cl0);
        AVT_DOUBLE:
            result := ((cb1 = AVT_CHAR) or (cb1 >= AVT_BYTE) and (cb1 <= AVT_INT) or (cb1 >= AVT_FLOAT) and (cb1 <= AVT_DOUBLE)) and (cl1 <= cl0);
        else
            result := false;
        end;
    end;

    function AVTTypePrimitive.isAssignableFrom(from: AVTType): boolean;
    begin
        result := (from is AVTTypePrimitive) and (AVTTypePrimitive(from).fldPrimitiveKind = fldPrimitiveKind);
    end;

    function AVTTypePrimitive.isPrimitive(): boolean;
    begin
        result := true;
    end;

    function AVTTypePrimitive.isStackable(): boolean;
    var
        knd: int;
    begin
        knd := fldPrimitiveKind;
        result := (knd <> AVT_VOID) and (knd <> AVT_BOOLEAN) and (knd <> AVT_CHAR) and (knd <> AVT_BYTE) and (knd <> AVT_SHORT);
    end;

    function AVTTypePrimitive.isBoolean(): boolean;
    begin
        result := fldPrimitiveKind = AVT_BOOLEAN;
    end;

    function AVTTypePrimitive.isInt(): boolean;
    var
        knd: int;
    begin
        knd := fldPrimitiveKind;
        result := (knd = AVT_BYTE) or (knd = AVT_SHORT) or (knd = AVT_INT);
    end;

    function AVTTypePrimitive.isNumeric(): boolean;
    begin
        result := fldPrimitiveKind > AVT_BOOLEAN;
    end;

    function AVTTypePrimitive.isCompound(): boolean;
    var
        knd: int;
    begin
        knd := fldPrimitiveKind;
        result := (knd > AVT_BYTE) and (knd <= AVT_DOUBLE8) and ((knd and 3) > 0);
    end;

    function AVTTypePrimitive.isVoid(): boolean;
    begin
        result := fldPrimitiveKind = AVT_VOID;
    end;

    function AVTTypePrimitive.isDword(): boolean;
    var
        knd: int;
    begin
        knd := fldPrimitiveKind;
        result := (knd = AVT_BOOLEAN) or (knd = AVT_CHAR) or (knd = AVT_BYTE) or (knd = AVT_SHORT) or (knd = AVT_INT);
    end;

    function AVTTypePrimitive.isQword(): boolean;
    begin
        result := fldPrimitiveKind = AVT_LONG;
    end;

    function AVTTypePrimitive.isTword(): boolean;
    begin
        result := fldPrimitiveKind = AVT_REAL;
    end;

    function AVTTypePrimitive.isXword(): boolean;
    var
        knd: int;
    begin
        knd := fldPrimitiveKind;
        result := (knd >= AVT_BYTE2) and (knd <= AVT_BYTE8) or (knd >= AVT_SHORT2) and (knd <= AVT_SHORT8) or (knd >= AVT_INT2) and (knd <= AVT_INT4) or (knd = AVT_LONG2) or (knd >= AVT_FLOAT) and (knd <= AVT_FLOAT4) or (knd >= AVT_DOUBLE) and (knd <= AVT_DOUBLE2);
    end;

    function AVTTypePrimitive.isYword(): boolean;
    var
        knd: int;
    begin
        knd := fldPrimitiveKind;
        result := (knd = AVT_INT8) or (knd = AVT_LONG4) or (knd = AVT_FLOAT8) or (knd = AVT_DOUBLE4);
    end;

    function AVTTypePrimitive.isZword(): boolean;
    var
        knd: int;
    begin
        knd := fldPrimitiveKind;
        result := (knd = AVT_LONG8) or (knd = AVT_DOUBLE8);
    end;
{%endregion}

{%region AVTTypeStructured.SuperEnumerator }
    procedure AVTTypeStructured.SuperEnumerator.next();
    var
        idx: int;
        vec: Vector;
        tpc: AVTTypeStructured;
    begin
        if superClasses then begin
            tpc := currType;
            if tpc <> nil then begin
                tpc := tpc.extends();
            end;
        end else begin
            idx := index;
            index := idx + 1;
            vec := thisType.fldImplementsAsVector;
            if (vec <> nil) and (idx < vec.size()) then begin
                tpc := (vec.elementAt(idx).objectValue() as SuperType).fldSuperReference;
            end else
            if all then begin
                superClasses := true;
                tpc := thisType.extends();
            end else begin
                tpc := nil;
            end;
        end;
        currType := tpc;
    end;

    constructor AVTTypeStructured.SuperEnumerator.create(thisType: AVTTypeStructured; all: boolean);
    begin
        inherited create();
        self.all := all;
        self.thisType := thisType;
        next();
    end;

    function AVTTypeStructured.SuperEnumerator.hasMoreElements(): boolean;
    begin
        result := currType <> nil;
    end;

    function AVTTypeStructured.SuperEnumerator.nextElement(): Value;
    var
        tpc: AVTTypeStructured;
    begin
        tpc := currType;
        if tpc = nil then begin
            raise NoSuchElementException.create('Enumeration.nextElement: ' + msgNoSuchElement);
        end;
        next();
        result := ValueOfObject.create(tpc, false);
    end;
{%endregion}

{%region AVTTypeStructured.ExtendsEnumerator }
    constructor AVTTypeStructured.ExtendsEnumerator.create(extends: AVTTypeStructured);
    begin
        inherited create();
        self.currType := extends;
    end;

    function AVTTypeStructured.ExtendsEnumerator.hasMoreElements(): boolean;
    begin
        result := currType <> nil;
    end;

    function AVTTypeStructured.ExtendsEnumerator.nextElement(): Value;
    var
        tpc: AVTTypeStructured;
    begin
        tpc := currType;
        if tpc = nil then begin
            raise NoSuchElementException.create('Enumeration.nextElement: ' + msgNoSuchElement);
        end;
        currType := tpc.extends();
        result := ValueOfObject.create(tpc, false);
    end;
{%endregion}

{%region AVTTypeStructured.MemberEnumerator }
    constructor AVTTypeStructured.MemberEnumerator.create(first: AVTMember);
    begin
        inherited create();
        self.current := first;
    end;

    function AVTTypeStructured.MemberEnumerator.hasMoreElements(): boolean;
    begin
        result := current <> nil;
    end;

    function AVTTypeStructured.MemberEnumerator.nextElement(): Value;
    var
        mmc: AVTMember;
    begin
        mmc := current;
        if mmc = nil then begin
            raise NoSuchElementException.create('Enumeration.nextElement: ' + msgNoSuchElement);
        end;
        current := mmc.fldNext;
        result := ValueOfObject.create(mmc, false);
    end;
{%endegion}

{%region AVTTypeStructured.Overridden }
    constructor AVTTypeStructured.Overridden.create(thisMember, superMember: AVTOverriddable);
    begin
        inherited create();
        self.fldThisMember := thisMember;
        self.fldSuperMember := superMember;
    end;
{%endregion}

{%region AVTTypeStructured.SuperType }
    procedure AVTTypeStructured.SuperType.addOverridden(thisMember, superMember: AVTOverriddable);
    begin
        fldOverriddenList.append(ValueOfObject.create(Overridden.create(thisMember, superMember)));
        if not(superMember is AVTMethod) or { thisMember.fldParentType.isClass() and } superMember.fldParentType.isClass() then begin
            superMember.fldOverridden := true;
        end;
    end;

    constructor AVTTypeStructured.SuperType.create(thisReference, superReference: AVTTypeStructured; declarationPosition: int);
    begin
        inherited create();
        self.fldDeclarationPosition := declarationPosition;
        self.fldOverriddenList := Vector.create();
        self.fldThisReference := thisReference;
        self.fldSuperReference := superReference;
    end;

    destructor AVTTypeStructured.SuperType.destroy;
    begin
        fldOverriddenList.free();
        inherited destroy;
    end;

    function AVTTypeStructured.SuperType.getThisMember(superMember: AVTOverriddable): AVTOverriddable;
    var
        ovr: Overridden;
        enm: Enumeration;
    begin
        enm := fldOverriddenList.elements();
        while enm.hasMoreElements() do begin
            ovr := enm.nextElement().objectValue() as Overridden;
            if ovr.fldSuperMember = superMember then begin
                result := ovr.fldThisMember;
                exit;
            end;
        end;
        result := nil;
    end;

    function AVTTypeStructured.SuperType.getSuperMember(thisMember: AVTOverriddable): AVTOverriddable;
    var
        ovr: Overridden;
        enm: Enumeration;
    begin
        enm := fldOverriddenList.elements();
        while enm.hasMoreElements() do begin
            ovr := enm.nextElement().objectValue() as Overridden;
            if ovr.fldThisMember = thisMember then begin
                result := ovr.fldSuperMember;
                exit;
            end;
        end;
        result := nil;
    end;

    function AVTTypeStructured.SuperType.overriddenMembers(): Enumeration;
    begin
        result := fldOverriddenList.elements();
    end;
{%endregion}

{%region AVTTypeStructured }
    procedure AVTTypeStructured.appendMethodsTo(methodList: Vector; const methodName: AnsiString);
    var
        mmc: TObject;
    begin
        with members(methodName) do while hasMoreElements() do begin
            mmc := nextElement().objectValue();
            if (mmc is AVTMethod) and not AVTMethod(mmc).containsIn(methodList) then begin
                methodList.append(ValueOfObject.create(mmc, false));
            end;
        end;
    end;

    procedure AVTTypeStructured.appendMethodsTo(methodList: Vector; const methodName: AnsiString; argumentsCount: int);
    var
        mmc: TObject;
    begin
        with members(methodName) do while hasMoreElements() do begin
            mmc := nextElement().objectValue();
            if (mmc is AVTMethod) and (AVTMethod(mmc).getArgumentsCount() = argumentsCount) and not AVTMethod(mmc).containsIn(methodList) then begin
                methodList.append(ValueOfObject.create(mmc, false));
            end;
        end;
    end;

    procedure AVTTypeStructured.checkImplements();
    var
        id0: int;
        id1: int;
        lim: int;
        vec: Vector;
        tpm: AVTTypeStructured;
        tp0: AVTTypeStructured;
        tp1: AVTTypeStructured;
    begin
        vec := fldImplementsAsVector;
        if vec = nil then exit;
        lim := vec.size() - 1;
        tpm := nil;
        for id0 := 0 to lim do begin
            tp0 := (vec.elementAt(id0).objectValue() as SuperType).fldSuperReference.extends();
            for id1 := id0 + 1 to lim do begin
                tp1 := (vec.elementAt(id1).objectValue() as SuperType).fldSuperReference.extends();
                if (tp0 <> nil) and (tp1 <> nil) and not tp0.isImplements(tp1) and not tp1.isImplements(tp0) then begin
                    raise AVTCompilerException.create('The super classes are incompatible for the super services ' + tp0.fldFullName + ', ' + tp1.fldFullName, fldSource, fldDeclarationPosition);
                end;
            end;
            if (tpm = nil) or (tp0 <> nil) and tp0.isImplements(tpm) then tpm := tp0;
        end;
        if (tpm <> nil) and not isImplements(tpm) then begin
            raise AVTCompilerException.create('The super class must be ' + tpm.fldFullName + ' for the type ' + fldSimpleName, fldSource, fldDeclarationPosition);
        end;
    end;

    procedure AVTTypeStructured.addMember(member: AVTMember);
    var
        val: Value;
        key: Value;
        tab: Hashtable;
        mmf: AVTMember;
        mml: AVTMember;
    begin
        tab := fldMembersAsTable;
        key := ValueOfAnsiString.create(member.fldSimpleName);
        val := tab.get(key);
        if val = nil then begin
            member.fldPrev := member;
            tab.put(key, ValueOfObject.create(member, false));
        end else begin
            mmf := val.objectValue() as AVTMember;
            mml := mmf.fldPrev;
            mmf.fldPrev := member;
            mml.fldNext := member;
            member.fldPrev := mml;
        end;
        fldMembersAsVector.append(ValueOfObject.create(member));
    end;

    procedure AVTTypeStructured.findOverriddenInSuperClass(extends: AVTTypeStructured);
    label
        label0;
    var
        idx: int;
        len: int;
        vis: int;
        vec: Vector;
        stc: SuperType;
        mms: AVTMember;
        mme: AVTMember;
        en0: Enumeration;
        en1: Enumeration;
        tpe: AVTTypeStructured;
    begin
        if extends = nil then exit;
        vec := fldImplementsAsVector;
        if vec = nil then exit;
        len := vec.size();
        for idx := 0 to len - 1 do begin
            stc := vec.elementAt(idx).objectValue() as SuperType;
            en0 := stc.fldSuperReference.members();
            while en0.hasMoreElements() do begin
                mms := en0.nextElement().objectValue() as AVTMember;
                if not(mms is AVTOverriddable) or mms.isStatic() or (stc.getThisMember(AVTOverriddable(mms)) <> nil) then continue;
                vis := mms.getVisibility();
                tpe := extends;
                repeat
                    en1 := tpe.members();
                    while en1.hasMoreElements() do begin
                        mme := en1.nextElement().objectValue() as AVTMember;
                        if (mme is AVTOverriddable) and mme.isVisible(self, self) and (mme.getVisibility() >= vis) and AVTOverriddable(mme).isOverriddable(AVTOverriddable(mms)) and not hasOverriddable(AVTOverriddable(mme), true) then begin
                            stc.addOverridden(AVTOverriddable(mme), AVTOverriddable(mms));
                            goto label0;
                        end;
                    end;
                    tpe := tpe.extends();
                until tpe = nil;
                label0:
            end;
        end;
    end;

    procedure AVTTypeStructured.findDuplicateMembers();
    var
        id0: int;
        id1: int;
        lim: int;
        nam: AnsiString;
        vec: Vector;
        mm0: AVTMember;
        mm1: AVTMember;
        en0: Enumeration;
        en1: Enumeration;
        tp0: AVTTypeStructured;
        tp1: AVTTypeStructured;
    begin
        vec := fldImplementsAsVector;
        if vec = nil then exit;
        lim := vec.size() - 1;
        for id0 := 0 to lim - 1 do begin
            tp0 := (vec.elementAt(id0).objectValue() as SuperType).fldSuperReference;
            for id1 := id0 + 1 to lim do begin
                tp1 := (vec.elementAt(id1).objectValue() as SuperType).fldSuperReference;
                en1 := tp1.members();
                while en1.hasMoreElements() do begin
                    mm1 := en1.nextElement().objectValue() as AVTMember;
                    if not(mm1 is AVTOverriddable) or not mm1.isVisible(self, self) then continue;
                    nam := mm1.fldSimpleName;
                    if stringIndexOf('.', nam) > 0 then continue;
                    en0 := tp0.members(nam);
                    while en0.hasMoreElements() do begin
                        mm0 := en0.nextElement().objectValue() as AVTMember;
                        if not(mm0 is AVTOverriddable) or not mm0.isVisible(self, self) or not AVTOverriddable(mm0).isOverriddable(AVTOverriddable(mm1)) then continue;
                        {
                        Устаревшая проверка типов – теперь не делается
                        if not AVTOverriddable(mm0).isTypeEquals(AVTOverriddable(mm1)) then begin
                            if mm0 is AVTProperty then begin
                                raise AVTCompilerException.create('The value types are incompatible for the inherited properties ' + mm0.fldFullName + ', ' + mm1.fldFullName, fldSource, fldDeclarationPosition);
                            end;
                            if mm0 is AVTOperator then begin
                                raise AVTCompilerException.create('The return types are incompatible for the inherited operators ' + mm0.fldFullName + ', ' + mm1.fldFullName, fldSource, fldDeclarationPosition);
                            end;
                            raise AVTCompilerException.create('The return types are incompatible for the inherited methods ' + mm0.fldFullName + ', ' + mm1.fldFullName, fldSource, fldDeclarationPosition);
                        end;
                        }
                        if isClass() and not hasOverriddable(AVTOverriddable(mm0)) then begin
                            if mm0 is AVTProperty then begin
                                raise AVTCompilerException.create('The inherited property ' + mm0.fldFullName + ' also defined in the type ' + tp1.fldFullName + '. Must define this property again', fldSource, fldDeclarationPosition);
                            end;
                            if mm0 is AVTOperator then begin
                                raise AVTCompilerException.create('The inherited operator ' + mm0.fldFullName + ' also defined in the type ' + tp1.fldFullName + '. Must define this operator again', fldSource, fldDeclarationPosition);
                            end;
                            raise AVTCompilerException.create('The inherited method ' + mm0.fldFullName + ' also defined in the type ' + tp1.fldFullName + '. Must define this method again', fldSource, fldDeclarationPosition);
                        end;
                    end;
                end;
            end;
        end;
    end;

    procedure AVTTypeStructured.checkOverridden();
    var
        str: int;
        idx: int;
        len: int;
        dps: int;
        vec: Vector;
        ste: SuperType;
        stc: SuperType;
        ovr: Overridden;
        enm: Enumeration;
        mms: AVTOverriddable;
        mmt: AVTOverriddable;
        tpe: AVTTypeStructured;
    begin
        ste := fldExtends;
        if ste = nil then begin
            str := 0;
        end else begin
            str := -1;
        end;
        vec := fldImplementsAsVector;
        if vec = nil then begin
            len := 0;
        end else begin
            len := vec.size();
        end;
        for idx := str to len - 1 do begin
            if idx < 0 then begin
                stc := ste;
            end else begin
                stc := vec.elementAt(idx).objectValue() as SuperType;
            end;
            enm := stc.overriddenMembers();
            while enm.hasMoreElements() do begin
                ovr := enm.nextElement().objectValue() as Overridden;
                mmt := ovr.fldThisMember;
                if stringIndexOf('.', mmt.fldSimpleName) > 0 then continue;
                mms := ovr.fldSuperMember;
                if mmt.fldParentType <> self then begin
                    dps := fldDeclarationPosition;
                end else begin
                    dps := mmt.fldDeclarationPosition;
                end;
                if mmt.getVisibility() < mms.getVisibility() then begin
                    raise AVTCompilerException.create('Cannot reduce the visibility of the inherited member ' + mms.fldFullName, fldSource, dps);
                end;
                if mms.isFinal() then begin
                    raise AVTCompilerException.create('Cannot override the final member ' + mms.fldFullName, fldSource, dps);
                end;
                if not mmt.isTypeOverriddable(mms) then begin
                    if mmt is AVTProperty then begin
                        raise AVTCompilerException.create('The value type is incompatible with ' + mms.fldFullName, fldSource, dps);
                    end;
                    raise AVTCompilerException.create('The return type is incompatible with ' + mms.fldFullName, fldSource, dps);
                end;
                tpe := mmt.mismatchThrows(mms);
                if tpe <> nil then begin
                    if mmt.fldParentType <> self then begin
                        dps := fldDeclarationPosition;
                    end else begin
                        dps := AVTMethod(mmt).fldThrowsPosition;
                    end;
                    raise AVTCompilerException.create('Exception ' + tpe.fldFullName + ' is not compatible with throws clause in ' + mms.fldFullName, fldSource, dps);
                end;
            end;
        end;
    end;

    procedure AVTTypeStructured.checkAbstract();
    var
        tpe: AVTTypeStructured;
    begin
        {if not isAbstract() then begin
            if hasAbstractMembers() then begin
                raise AVTCompilerException.create('The type ' + fldSimpleName + ' must be an abstract type to define abstract members', fldSource, fldDeclarationPosition - 1);
            end;
            if isService() then begin
                tpe := extends();
                if (tpe <> nil) and tpe.isAbstract() then begin
                    raise AVTCompilerException.create('The type ' + fldSimpleName + ' must be an abstract type to define abstract members', fldSource, fldDeclarationPosition - 1);
                end;
                with implements() do while hasMoreElements() do begin
                    if (nextElement().objectValue() as AVTTypeStructured).isAbstract() then begin
                        raise AVTCompilerException.create('The type ' + fldSimpleName + ' must be an abstract type to define abstract members', fldSource, fldDeclarationPosition - 1);
                    end;
                end;
            end;
        end;}
        tpe := extends();
        if not isAbstract() and (hasAbstractMembers() or isService() and (tpe <> nil) and tpe.isAbstract()) then begin
            raise AVTCompilerException.create('The type ' + fldSimpleName + ' must be an abstract type to define abstract members', fldSource, fldDeclarationPosition - 1);
        end;
    end;

    function AVTTypeStructured.hasAbstractMembers(): boolean;
    var
        enm: Enumeration;
    begin
        enm := members();
        while enm.hasMoreElements() do begin
            if (enm.nextElement().objectValue() as AVTMember).isAbstract() then begin
                result := true;
                exit;
            end;
        end;
        result := false;
    end;

    function AVTTypeStructured.hasOverriddable(member: AVTOverriddable; onlyInSelf: boolean): boolean;
    var
        vis: int;
        nam: AnsiString;
        mmc: AVTMember;
        enm: Enumeration;
        tpe: AVTTypeStructured;
    begin
        vis := member.getVisibility();
        nam := member.fldSimpleName;
        tpe := self;
        repeat
            enm := tpe.members(nam);
            while enm.hasMoreElements() do begin
                mmc := enm.nextElement().objectValue() as AVTMember;
                if (mmc is AVTOverriddable) and mmc.isVisible(self, self) and (mmc.getVisibility() >= vis) and AVTOverriddable(mmc).isOverriddable(member) then begin
                    result := true;
                    exit;
                end;
            end;
            if onlyInSelf then break;
            tpe := tpe.extends();
        until tpe = nil;
        result := false;
    end;

    function AVTTypeStructured.getVirtualMethodsCount(): int;
    begin
        result := fldVirtualMethods.size();
    end;

    function AVTTypeStructured.getServiceMethodsCount(): int;
    var
        tsm: Vector;
    begin
        tsm := fldServiceMethods;
        if tsm = nil then begin
            result := 0;
        end else begin
            result := tsm.size();
        end;
    end;

    function AVTTypeStructured.getVirtualMethod(index: int): AVTMethod;
    var
        tvm: Vector;
    begin
        tvm := fldVirtualMethods;
        if (index < 0) or (index >= tvm.size()) then begin
            raise IndexOutOfBoundsException.create('AVTTypeStructured.virtualMethod: ' + msgIndexOutOfBounds);
        end;
        result := tvm.elementAt(index).objectValue() as AVTMethod;
    end;

    function AVTTypeStructured.getServiceMethod(index: int): AVTMethod;
    var
        tsm: Vector;
    begin
        tsm := fldServiceMethods;
        if (tsm = nil) or (index < 0) or (index >= tsm.size()) then begin
            raise IndexOutOfBoundsException.create('AVTTypeStructured.serviceMethod: ' + msgIndexOutOfBounds);
        end;
        result := tsm.elementAt(index).objectValue() as AVTMethod;
    end;

    procedure AVTTypeStructured.prefetchImplements();
    var
        id0: int;
        cn0: int;
        id1: int;
        lim: int;
        vc0: Vector;
        vc1: Vector;
        st0: SuperType;
        tp1: AVTTypeStructured;
    begin
        st0 := fldExtends;
        vc0 := fldImplementsAsVector;
        if st0 = nil then begin
            id0 := 0;
        end else begin
            id0 := -1;
        end;
        if vc0 = nil then begin
            cn0 := 0;
        end else begin
            cn0 := vc0.size();
        end;
        while id0 < cn0 do begin
            if id0 < 0 then begin
                vc1 := st0.fldSuperReference.fldImplementsAsVector;
            end else begin
                vc1 := (fldImplementsAsVector.elementAt(id0).objectValue() as SuperType).fldSuperReference.fldImplementsAsVector;
            end;
            if vc1 <> nil then begin
                lim := vc1.size() - 1;
                for id1 := 0 to lim do begin
                    tp1 := (vc1.elementAt(id1).objectValue() as SuperType).fldSuperReference;
                    if not isImplements(tp1) then begin
                        addImplements(tp1);
                        inc(cn0);
                    end;
                end;
            end;
            inc(id0);
        end;
    end;

    procedure AVTTypeStructured.defineFieldOffsets(extends: AVTTypeStructured);
    var
        iof: int;
        sof: int;
        len: int;
        flw: int;
        tpv: AVTType;
        mmc: AVTMember;
        enm: Enumeration;
    begin
        if isService() then begin
            if extends = nil then begin
                fldInstanceSize := 0;
                exit;
            end;
            fldInstanceSize := extends.fldInstanceSize;
            exit;
        end;
        if isClass() then begin
            if extends = nil then begin
                iof := 0;
            end else begin
                iof := extends.fldInstanceSize;
            end;
            enm := members();
            while enm.hasMoreElements() do begin
                mmc := enm.nextElement().objectValue() as AVTMember;
                if not(mmc is AVTField) or mmc.isStatic() then continue;
                with AVTField(mmc) do begin
                    flw := fldValueType.fldFieldWidth;
                    if flw > $08 then begin
                        inc(iof, (-iof) and $0f);
                    end else
                    if flw > $04 then begin
                        inc(iof, (-iof) and $07);
                    end;
                    fldInstanceOffset := iof;
                end;
                inc(iof, flw);
                inc(iof, (-iof) and $03);
            end;
            fldInstanceSize := iof;
            exit;
        end;
        if extends = nil then begin
            iof := 0;
            sof := 0;
        end else begin
            iof := extends.fldInstanceSize;
            sof := extends.fldStructureSize;
        end;
        enm := members();
        while enm.hasMoreElements() do begin
            mmc := enm.nextElement().objectValue() as AVTMember;
            if not(mmc is AVTField) or mmc.isStatic() then continue;
            with AVTField(mmc) do begin
                len := fldLength;
                if len > 0 then begin
                    tpv := fldValueType;
                    if system.length(simpleName) > 0 then begin
                        flw := tpv.fldFieldWidth;
                        if flw > $04 then begin
                            inc(iof, (-iof) and $07);
                        end;
                        fldInstanceOffset := iof;
                        inc(iof, flw);
                        inc(iof, (-iof) and $03);
                    end;
                    fldStructureOffset := sof;
                    inc(sof, len * (tpv as AVTTypeArray).fldElementType.fldFieldWidth);
                end else begin
                    fldInstanceOffset := -1;
                    fldStructureOffset := sof;
                    inc(sof, fldValueType.fldFieldWidth);
                end;
            end;
        end;
        fldInstanceSize := iof + ((-iof) and $0f);
        fldStructureSize := sof;
    end;

    procedure AVTTypeStructured.insertAbstractMembers(extends: AVTTypeStructured);
    label
        label0;
    var
        str: int;
        idx: int;
        len: int;
        vis: int;
        val: Value;
        vec: Vector;
        ahl: Vector;
        mmc: AVTMember;
        en0: Enumeration;
        en1: Enumeration;
        mmn: AVTOverriddable;
        tpc: AVTTypeStructured;
    begin
        with members() do while hasMoreElements() do begin
            mmc := nextElement().objectValue() as AVTMember;
            if mmc is AVTOverriddable then AVTOverriddable(mmc).findOverriddenMembers();
        end;
        vec := fldImplementsAsVector;
        if vec = nil then begin
            len := 0;
        end else begin
            len := vec.size();
        end;
        if isClass() and (extends <> nil) then begin
            str := -1;
        end else begin
            str := 0;
        end;
        ahl := Vector.create();
        try
            repeat
                en0 := members();
                while en0.hasMoreElements() do begin
                    mmc := en0.nextElement().objectValue() as AVTMember;
                    if not(mmc is AVTOverriddable) or (mmc is AVTSpecial) or mmc.isStatic() or (stringIndexOf('.', mmc.fldSimpleName) > 0) then continue;
                    en1 := AVTOverriddable(mmc).overriddenMembers();
                    while en1.hasMoreElements() do begin
                        val := en1.nextElement();
                        if (val.objectValue() as AVTItem).isAbstract() then ahl.append(val);
                    end;
                end;
                for idx := str to len - 1 do begin
                    if idx >= 0 then begin
                        tpc := (vec.elementAt(idx).objectValue() as SuperType).fldSuperReference;
                    end else begin
                        tpc := extends;
                    end;
                    en0 := tpc.members();
                    while en0.hasMoreElements() do begin
                        val := en0.nextElement();
                        mmc := val.objectValue() as AVTMember;
                        if not(mmc is AVTOverriddable) or mmc.isStatic() or not mmc.isAbstract() or (stringIndexOf('.', mmc.fldSimpleName) > 0) then continue;
                        if ahl.contains(val) or ((idx >= 0) and (extends <> nil) and extends.hasOverriddable(AVTOverriddable(mmc))) then continue;
                        vis := mmc.getVisibility();
                        if (vis = AVT_SOURCE) and (mmc.fldParentType.fldSource <> fldSource) or (vis = AVT_PACKAGE) and (mmc.fldParentType.fldPackage <> fldPackage) then begin
                            raise AVTCompilerException.create('This class must implement the inherited abstract member ' + mmc.fldSimpleName + ', but cannot override it since it is not visible from ' + fldSimpleName + '. Make the inherited member visible', fldSource, fldDeclarationPosition);
                        end;
                        if mmc is AVTProperty then with AVTProperty(mmc) do begin
                            mmn := AVTProperty.create(self, getVisibility() or (FLAG_SYNTHETIC or FLAG_ABSTRACT), fldValueType, fldSimpleName);
                            if fldReadSynthetic <> nil then AVTProperty(mmn).createReadSynthetic();
                            if fldWriteSynthetic <> nil then AVTProperty(mmn).createWriteSynthetic();
                            if fldStoredSynthetic <> nil then AVTProperty(mmn).createStoredSynthetic();
                        end else
                        if mmc is AVTOperator then with AVTOperator(mmc) do begin
                            mmn := AVTOperator.create(self, getVisibility() or (FLAG_SYNTHETIC or FLAG_ABSTRACT), fldReturnType, fldOperatorKind, fldArgumentsAsVector);
                        end else
                        if mmc is AVTMethod then with AVTMethod(mmc) do begin
                            mmn := AVTMethod.create(self, getVisibility() or (FLAG_SYNTHETIC or FLAG_ABSTRACT), fldReturnType, fldSimpleName, fldArgumentsAsVector);
                            en1 := throws();
                            while en1.hasMoreElements() do AVTMethod(mmn).addThrows(en1.nextElement().objectValue() as AVTTypeStructured);
                        end else begin
                            continue;
                        end;
                        mmn.findOverriddenMembers();
                        ahl.clear();
                        goto label0;
                    end;
                end;
                break;
                label0:
            until false;
        finally
            ahl.free();
        end;
    end;

    procedure AVTTypeStructured.insertDefaultConstructor(extends: AVTTypeStructured);
    label
        label0;
    var
        cod: AVTCode;
        ndr: AVTNode;
        nd0: AVTNode;
        nd1: AVTNode;
        nde: AVTNode;
        mms: AVTMember;
        mmn: AVTMethod;
        vr0: AVTVariable;
        app: AVTProgramme;
        tpe: AVTTypeStructured;
        pck_avt_lang: AVTPackage;
        typ_void: AVTType;
        typ_avt_lang_Error: AVTTypeStructured;
        typ_avt_lang_RuntimeException: AVTTypeStructured;
    begin
        mms := nil;
        app := fldPackage.fldParentProgramme;
        if extends <> nil then begin
            begin
                with extends.members(SPECNAME_INST_INIT) do while hasMoreElements() do begin
                    mms := nextElement().objectValue() as AVTMember;
                    if (mms is AVTInstInit) and (AVTInstInit(mms).fldArgumentsAsVector.size() <= 0) then begin
                        if mms.isVisible(self, self) then goto label0;
                        raise AVTCompilerException.create('Implicit super constructor ' + extends.fldSimpleName + '() is not visible for default constructor. Must define an explicit constructor', fldSource, fldDeclarationPosition);
                    end;
                end;
                raise AVTCompilerException.create('Implicit super constructor ' + extends.fldSimpleName + '() is undefined for default constructor. Must define an explicit constructor', fldSource, fldDeclarationPosition);
            end;
            label0:
            pck_avt_lang := app.getPackage('avt.lang');
            if pck_avt_lang = nil then begin
                typ_avt_lang_Error := nil;
                typ_avt_lang_RuntimeException := nil;
            end else begin
                typ_avt_lang_Error := pck_avt_lang.getType('Error') as AVTTypeStructured;
                typ_avt_lang_RuntimeException := pck_avt_lang.getType('RuntimeException') as AVTTypeStructured;
            end;
            with AVTInstInit(mms).throws() do while hasMoreElements() do begin
                tpe := nextElement().objectValue() as AVTTypeStructured;
                if (typ_avt_lang_Error <> nil) and tpe.isImplements(typ_avt_lang_Error) or (typ_avt_lang_RuntimeException <> nil) and tpe.isImplements(typ_avt_lang_RuntimeException) then continue;
                raise AVTCompilerException.create('Default constructor cannot handle exception type ' + tpe.fldFullName + ' thrown by implicit super constructor. Must define an explicit constructor', fldSource, fldDeclarationPosition);
            end;
        end;
        typ_void := app.fldSystemPackage.getType(AVTTypePrimitive.getName(AVT_VOID));
        mmn := AVTInstInit.create(self, AVT_PUBLIC, nil, fldDeclarationPosition);
        cod := mmn.fldCode;
        ndr := cod.fldRoot;
        if mms = nil then begin
            nde := cod.appendNode(ndr);
            ndr.setData(NO_LINE_INDEX, typ_void, AVT_ENTER);            (*  {      *)
            nde.setData(NO_LINE_INDEX, typ_void, AVT_LEAVE, typ_void);  (*  └── }  *)
            exit;
        end;
        vr0 := mmn.fldArgumentThis;
        nd0 := cod.appendNode(ndr);
        nd1 := cod.appendNode(nd0);
        nde := cod.appendNode(ndr);
        ndr.setData(NO_LINE_INDEX, typ_void, AVT_ENTER);                   (*  {                   *)
        nd0.setData(NO_LINE_INDEX, typ_void, INVOKE_SPECIAL, mms);         (*  ├── invoke super()  *)
        nd1.setData(NO_LINE_INDEX, vr0.fldValueType, LOAD_VARIABLE, vr0);  (*  │   └── this        *)
        nde.setData(NO_LINE_INDEX, typ_void, AVT_LEAVE, typ_void);         (*  └── }               *)
    end;

    function AVTTypeStructured.getFieldWidth(): int;
    begin
        result := fldPackage.fldParentProgramme.fldBits shr 3;
    end;

    function AVTTypeStructured.getFullName(): AnsiString;
    begin
        result := fldPackage.fldFullName + '.' + fldSimpleName;
    end;

    function AVTTypeStructured.getAvtcType(): AnsiString;
    begin
        result := 'L' + fldPackage.fldFullName + '.' + fldSimpleName + ';';
    end;

    function AVTTypeStructured.getFasmFullName(): AnsiString;
    begin
        result := fldPackage.fldFullName + '.' + fldSimpleName;
    end;

    function AVTTypeStructured.getFasmArgument(): AnsiString;
    begin
        result := fldPackage.fldFullName + '.' + fldSimpleName;
    end;

    constructor AVTTypeStructured.create(parentItem: AVTItem; fromLibrary: boolean; flags: int; const simpleName: AnsiString; source: AVTSource; declarationPosition: int; const documentation: UnicodeString);
    begin
        inherited create(parentItem, flags, simpleName, source, declarationPosition, documentation);
        self.fldFromLibrary := fromLibrary;
        self.fldMembersAsVector := Vector.create();
        self.fldMembersAsTable := Hashtable.create();
        self.fldVirtualMethods := Vector.create();
    end;

    destructor AVTTypeStructured.destroy;
    begin
        fldExtends.free();
        fldImplementsAsVector.free();
        fldImplementsAsTable.free();
        fldMembersAsVector.free();
        fldMembersAsTable.free();
        fldVirtualMethods.free();
        fldServiceMethods.free();
        inherited destroy;
    end;

    procedure AVTTypeStructured.afterConstruction();
    var
        src: AVTSource;
    begin
        inherited afterConstruction();
        src := source;
        if src <> nil then src.addDeclaredType(self);
    end;

    procedure AVTTypeStructured.prefetchMembers();
    var
        tpe: AVTTypeStructured;
    begin
        tpe := extends();
        defineFieldOffsets(tpe);
        if not isStruct() then begin
            if isClass() then begin
                if not members(SPECNAME_INST_INIT).hasMoreElements() then begin
                    insertDefaultConstructor(tpe);
                end;
                findDuplicateMembers();
                findOverriddenInSuperClass(tpe);
            end else begin
                findDuplicateMembers();
            end;
            insertAbstractMembers(tpe);
            checkOverridden();
            checkAbstract();
        end;

        (*
            Для будущих версий:
            tpe := extends();
            if not isService() then begin
                defineFieldOffsets(tpe);
            end;
            if not isStruct() then begin
                if isClass() then begin
                    if not members(SPECNAME_INST_INIT).hasMoreElements() then begin
                        insertDefaultConstructor(tpe);
                    end;
                    findDuplicateMembers();
                    findOverridden();
                    insertAbstractMembers();
                    checkOverridden();
                end;
                checkAbstract();
            end;
        *)
    end;

    procedure AVTTypeStructured.prefetchIndices();
    var
        i: int;
        cnt: int;
        evm: Vector;
        tvm: Vector;
        tsm: Vector;
        met: AVTMethod;
        mem: AVTMember;
        ext: AVTTypeStructured;
    begin
        tvm := fldVirtualMethods;
        ext := extends();
        if ext = nil then begin
            evm := nil;
            cnt := 0;
        end else begin
            evm := ext.fldVirtualMethods;
            cnt := evm.size();
        end;
        i := 0;
        if isService() then begin
            tsm := fldServiceMethods;
            if tsm = nil then begin
                tsm := Vector.create();
                fldServiceMethods := tsm;
            end;
            with members() do while hasMoreElements() do begin
                mem := nextElement().objectValue() as AVTMember;
                if (mem is AVTMethod) and not mem.isStatic() and (mem.visibility > AVT_PRIVATE) then begin
                    met := AVTMethod(mem);
                    met.fldServiceIndex := i;
                    tsm.append(ValueOfObject.create(met, false));
                    inc(i);
                end;
            end;
            {for i := 0 to cnt - 1 do begin
                tvm.append(evm.elementAt(i));
            end;}
            i := 0;
        end;
        while i < cnt do begin
            met := evm.elementAt(i).objectValue() as AVTMethod;
            with members() do while hasMoreElements() do begin
                mem := nextElement().objectValue() as AVTMember;
                if (mem is AVTMethod) and AVTMethod(mem).isOverride(met) then begin
                    met := AVTMethod(mem);
                    met.fldVirtualIndex := i;
                    break;
                end;
            end;
            tvm.append(ValueOfObject.create(met, false));
            inc(i);
        end;
        with members() do while hasMoreElements() do begin
            mem := nextElement().objectValue() as AVTMember;
            if (mem is AVTMethod) and (AVTMethod(mem).fldVirtualIndex < 0) and AVTMethod(mem).isOverridden() then begin
                met := AVTMethod(mem);
                met.fldVirtualIndex := i;
                tvm.append(ValueOfObject.create(met, false));
                inc(i);
            end;
        end;
    end;

    procedure AVTTypeStructured.setExtends(atype: AVTTypeStructured; declarationPosition: int);
    begin
        if (fldExtends = nil) and (atype <> nil) then begin
            if atype.getVisibility() < getVisibility() then begin
                raise AVTCompilerException.create('The type ' + atype.fldFullName + ' has low visibility than ' + fldSimpleName, fldSource, fldDeclarationPosition);
            end;
            if atype.isFinal() then begin
                raise AVTCompilerException.create('The type ' + fldSimpleName + ' cannot subtype the final type ' + atype.fldFullName, fldSource, fldDeclarationPosition);
            end;
            if atype.isImplements(self) then begin
                raise AVTCompilerException.create('Cycle detected: a cycle exists in the type hierarchy between ' + fldSimpleName + ' and ' + atype.fldFullName, fldSource, declarationPosition);
            end;
            fldExtends := SuperType.create(self, atype, declarationPosition);
        end;
    end;

    procedure AVTTypeStructured.addImplements(atype: AVTTypeStructured; declarationPosition: int);
    var
        vec: Vector;
        tab: Hashtable;
        stn: SuperType;
    begin
        if atype <> nil then begin
            if atype.getVisibility() < getVisibility() then begin
                raise AVTCompilerException.create('The type ' + atype.fldFullName + ' has low visibility than ' + fldSimpleName, fldSource, fldDeclarationPosition);
            end;
            if atype.isFinal() then begin
                raise AVTCompilerException.create('The type ' + fldSimpleName + ' cannot subtype the final type ' + atype.fldFullName, fldSource, fldDeclarationPosition);
            end;
            if atype.isImplements(self) then begin
                raise AVTCompilerException.create('Cycle detected: a cycle exists in the type hierarchy between ' + fldSimpleName + ' and ' + atype.fldFullName, fldSource, declarationPosition);
            end;
            if isImplements(atype) then begin
                raise AVTCompilerException.create('Duplicate service ' + atype.fldFullName + ' for the type ' + fldSimpleName, fldSource, declarationPosition);
            end;
            vec := fldImplementsAsVector;
            if vec = nil then begin
                vec := Vector.create();
                fldImplementsAsVector := vec;
            end;
            tab := fldImplementsAsTable;
            if tab = nil then begin
                tab := Hashtable.create();
                fldImplementsAsTable := tab;
            end;
            stn := SuperType.create(self, atype, declarationPosition);
            tab.put(ValueOfObject.create(atype, false), ValueOfObject.create(stn));
            vec.append(ValueOfObject.create(stn, false));
        end;
    end;

    function AVTTypeStructured.getImplements(atype: AVTTypeStructured): SuperType;
    var
        val: Value;
        tab: Hashtable;
        ste: SuperType;
    begin
        ste := fldExtends;
        if (ste <> nil) and (ste.fldSuperReference = atype) then begin
            result := ste;
            exit;
        end;
        tab := fldImplementsAsTable;
        if tab = nil then begin
            result := nil;
            exit;
        end;
        val := tab.get(ValueOfObject.create(atype, false));
        if val = nil then begin
            result := nil;
            exit;
        end;
        result := val.objectValue() as SuperType;
    end;

    function AVTTypeStructured.getMember(const simpleName: AnsiString): AVTMember;
    begin
        with members(simpleName) do if hasMoreElements() then begin
            result := nextElement().objectValue() as AVTMember;
            exit;
        end;
        with extendsAll() do while hasMoreElements() do with (nextElement().objectValue() as AVTTypeStructured).members(simpleName) do if hasMoreElements() then begin
            result := nextElement().objectValue() as AVTMember;
            exit;
        end;
        with implements() do while hasMoreElements() do with (nextElement().objectValue() as AVTTypeStructured).members(simpleName) do if hasMoreElements() then begin
            result := nextElement().objectValue() as AVTMember;
            exit;
        end;
        result := nil;
    end;

    function AVTTypeStructured.getCommonType(anot: AVTType): AVTType;
    begin
        if anot = nil then begin
            result := self;
            exit;
        end;
        if not(anot is AVTTypeStructured) then begin
            result := AVTTypeInvalid.getInstance();
            exit;
        end;
        if anot.isAssignableFrom(self) then begin
            result := anot;
            exit;
        end;
        if isAssignableFrom(anot) then begin
            result := self;
            exit;
        end;
        result := AVTTypeInvalid.getInstance();
    end;

    function AVTTypeStructured.isImplements(atype: AVTTypeStructured): boolean;
    var
        ste: SuperType;
        tpe: AVTTypeStructured;
    begin
        if atype = self then begin
            result := true;
            exit;
        end;
        ste := fldExtends;
        while ste <> nil do begin
            tpe := ste.superReference;
            if tpe = atype then begin
                result := true;
                exit;
            end;
            ste := tpe.fldExtends;
        end;
        result := getImplements(atype) <> nil;
    end;

    function AVTTypeStructured.isConvertableFrom(from: AVTType): boolean;
    begin
        result := isAssignableFrom(from);
    end;

    function AVTTypeStructured.isAssignableFrom(from: AVTType): boolean;
    begin
        result := (from = nil) or (from is AVTTypeStructured) and AVTTypeStructured(from).isImplements(self);
    end;

    function AVTTypeStructured.isStackable(): boolean;
    begin
        result := true;
    end;

    function AVTTypeStructured.isInterface(): boolean;
    begin
        result := (flags and FLAG_INTERFACE) = FLAG_INTERFACE;
    end;

    function AVTTypeStructured.isService(): boolean;
    begin
        result := (flags and FLAG_SERVICE) = FLAG_SERVICE;
    end;

    function AVTTypeStructured.isStruct(): boolean;
    begin
        result := (flags and FLAG_INTERFACE) = FLAG_STRUCT;
    end;

    function AVTTypeStructured.isClass(): boolean;
    begin
        result := (flags and FLAG_INTERFACE) = 0;
    end;

    function AVTTypeStructured.virtualMethods(): Enumeration;
    var
        vec: Vector;
    begin
        vec := fldVirtualMethods;
        if vec = nil then begin
            result := EmptyEnumerator.create();
            exit;
        end;
        result := vec.elements();
    end;

    function AVTTypeStructured.serviceMethods(): Enumeration;
    var
        vec: Vector;
    begin
        vec := fldServiceMethods;
        if vec = nil then begin
            result := EmptyEnumerator.create();
            exit;
        end;
        result := vec.elements();
    end;

    function AVTTypeStructured.implementsAll(): Enumeration;
    begin
        result := SuperEnumerator.create(self, true);
    end;

    function AVTTypeStructured.implements(): Enumeration;
    begin
        result := SuperEnumerator.create(self, false);
    end;

    function AVTTypeStructured.extendsAll(): Enumeration;
    begin
        result := ExtendsEnumerator.create(extends());
    end;

    function AVTTypeStructured.extends(): AVTTypeStructured;
    var
        ste: SuperType;
        tpe: AVTTypeStructured;
    begin
        tpe := nil;
        ste := fldExtends;
        if ste <> nil then begin
            tpe := ste.fldSuperReference;
        end;
        result := tpe;
    end;

    function AVTTypeStructured.members(): Enumeration;
    begin
        result := fldMembersAsVector.elements();
    end;

    function AVTTypeStructured.members(const simpleName: AnsiString): Enumeration;
    var
        val: Value;
    begin
        val := fldMembersAsTable.get(ValueOfAnsiString.create(simpleName));
        if val = nil then begin
            result := EmptyEnumerator.create();
            exit;
        end;
        result := MemberEnumerator.create(val.objectValue() as AVTMember);
    end;

    function AVTTypeStructured.findField(const simpleName: AnsiString; from: AVTTypeStructured; position: int): AVTMember;
    var
        idx: int;
        len: int;
        mml: Vector;
        mma: TObject;
        mmc: AVTMember;
        mmf: AVTMember;
        tpc: AVTTypeStructured;
    begin
        with members(simpleName) do if hasMoreElements() then begin
            mma := nextElement().objectValue();
            if (mma is AVTField) or (mma is AVTProperty) then begin
                result := AVTMember(mma);
                exit;
            end;
        end;
        with extendsAll() do while hasMoreElements() do with (nextElement().objectValue() as AVTTypeStructured).members(simpleName) do while hasMoreElements() do begin
            mma := nextElement().objectValue();
            if (mma is AVTField) or (mma is AVTProperty) then begin
                result := AVTMember(mma);
                exit;
            end;
        end;
        mml := Vector.create();
        try
            with implements() do while hasMoreElements() do with (nextElement().objectValue() as AVTTypeStructured).members(simpleName) do if hasMoreElements() then begin
                mma := nextElement().objectValue();
                if not(mma is AVTField) and not(mma is AVTProperty) then continue;
                mml.append(ValueOfObject.create(mma, false));
            end;
            mmf := nil;
            len := mml.size();
            for idx := len - 1 downto 0 do begin
                mmc := mml.elementAt(idx).objectValue() as AVTMember;
                if mmc.isVisible(self, from) then begin
                    if mmf <> nil then begin
                        raise AVTCompilerException.create('The field ' + simpleName + ' is ambiguous', from.source, position);
                    end;
                    mmf := mmc;
                    if mmf is AVTProperty then break;
                end;
            end;
            if (mmf = nil) and (len > 0) then begin
                mmf := mml.firstElement().objectValue() as AVTMember;
            end;
        finally
            mml.free();
        end;
        result := mmf;
    end;

    function AVTTypeStructured.findMethod(const simpleName: AnsiString; argumentTypes: Vector; from: AVTTypeStructured; position: int): AVTMethod;
    var
        len: int;
        idx: int;
        lim: int;
        mtl: Vector;
        mtc: AVTMethod;
        mtf: AVTMethod;
    begin
        len := 0;
        if argumentTypes <> nil then len := argumentTypes.size();
        mtl := Vector.create();
        try
            appendMethodsTo(mtl, simpleName, len);
            if simpleName <> SPECNAME_INST_INIT then begin
                with extendsAll() do while hasMoreElements() do begin
                    (nextElement().objectValue() as AVTTypeStructured).appendMethodsTo(mtl, simpleName, len);
                end;
                with implements() do while hasMoreElements() do begin
                    (nextElement().objectValue() as AVTTypeStructured).appendMethodsTo(mtl, simpleName, len);
                end;
            end;
            if mtl.size() <= 0 then begin
                appendMethodsTo(mtl, simpleName);
                if simpleName <> SPECNAME_INST_INIT then begin
                    with extendsAll() do while hasMoreElements() do begin
                        (nextElement().objectValue() as AVTTypeStructured).appendMethodsTo(mtl, simpleName);
                    end;
                    with implements() do while hasMoreElements() do begin
                        (nextElement().objectValue() as AVTTypeStructured).appendMethodsTo(mtl, simpleName);
                    end;
                end;
            end;
            lim := mtl.size() - 1;
            for idx := 0 to lim do begin
                mtc := mtl.elementAt(idx).objectValue() as AVTMethod;
                if mtc.isVisible(self, from) and mtc.isIdentityArgumentTypes(argumentTypes) then begin
                    result := mtc;
                    exit;
                end;
            end;
            mtf := nil;
            for idx := 0 to lim do begin
                mtc := mtl.elementAt(idx).objectValue() as AVTMethod;
                if mtc.isVisible(self, from) and mtc.isConvertableArgumentTypes(argumentTypes) then begin
                    if mtf <> nil then begin
                        if mtf is AVTInstInit then begin
                            raise AVTCompilerException.create('The constructor ' + fldSimpleName + mtf.argumentsToString() + ' is ambiguous', from.fldSource, position);
                        end;
                        if mtf is AVTOperator then begin
                            raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(AVTOperator(mtf).fldOperatorKind) + mtf.argumentsToString() + ' is ambiguous', from.fldSource, position);
                        end;
                        raise AVTCompilerException.create('The method ' + simpleName + mtf.argumentsToString() + ' is ambiguous', from.fldSource, position);
                    end;
                    mtf := mtc;
                end;
            end;
            if mtf = nil then begin
                for idx := 0 to lim do begin
                    mtc := mtl.elementAt(idx).objectValue() as AVTMethod;
                    if mtc.isConvertableArgumentTypes(argumentTypes) then begin
                        mtf := mtc;
                        break;
                    end;
                end;
            end;
            if (mtf = nil) and (lim >= 0) then begin
                mtf := mtl.firstElement().objectValue() as AVTMethod;
            end;
        finally
            mtl.free();
        end;
        result := mtf;
    end;
{%endregion}

{%region AVTTypeArray }
    procedure AVTTypeArray.prefetchImplements();
    label
        label0;
    var
        tpe: AVTType;
        pck: AVTPackage;
        app: AVTProgramme;
    begin
        tpe := fldElementType;
        if (tpe is AVTTypeStructured) and (AVTTypeStructured(tpe).extends() <> nil) then begin
            pck := fldPackage;
            if pck = nil then goto label0;
            app := pck.fldParentProgramme;
            if app = nil then goto label0;
            pck := app.getPackage('avt.lang');
            if pck = nil then goto label0;
            tpe := pck.getType('Object[]');
            if tpe = nil then goto label0;
            setExtends(tpe as AVTTypeStructured);
            label0:
        end;
        inherited prefetchImplements();
    end;

    procedure AVTTypeArray.insertDefaultConstructor(extends: AVTTypeStructured);
    begin
    end;

    function AVTTypeArray.getFullName(): AnsiString;
    var
        ofs: int;
        len: int;
        str: char_Array1d;
    begin
        ofs := 0;
        len := fldDimensionsCount shl 1;
        str := char_Array1d_create(len);
        while ofs < len do begin
            str[ofs] := '[';
            inc(ofs);
            str[ofs] := ']';
            inc(ofs);
        end;
        result := fldCellType.fldFullName + AnsiString_create(str, 0, len);
    end;

    function AVTTypeArray.getAvtcType(): AnsiString;
    var
        dim: int;
        str: char_Array1d;
    begin
        dim := fldDimensionsCount;
        str := char_Array1d_create(dim);
        arrayfillPrimitives(str, 0, dim, '[');
        result := AnsiString_create(str, 0, dim) + fldCellType.fldAvtcType;
    end;

    function AVTTypeArray.getFasmFullName(): AnsiString;
    var
        dim: int;
        str: char_Array1d;
    begin
        dim := fldDimensionsCount;
        str := char_Array1d_create([
            char((dim div 10) + int('0')),
            char((dim mod 10) + int('0'))
        ]);
        result := fldCellType.fldFullName + '.' + AnsiString_create(str, 0, length(str)) + 'd';
    end;

    function AVTTypeArray.getFasmArgument(): AnsiString;
    var
        dim: int;
        str: char_Array1d;
    begin
        dim := fldDimensionsCount;
        str := char_Array1d_create([
            char((dim div 10) + int('0')),
            char((dim mod 10) + int('0'))
        ]);
        result := fldCellType.fldFullName + '.' + AnsiString_create(str, 0, length(str)) + 'd';
    end;

    constructor AVTTypeArray.create(elementType: AVTType);
    begin
        inherited create(elementType.fldParentItem, true, elementType.getVisibility(), elementType.fldSimpleName + '[]', nil);
        self.fldElementType := elementType;
        if elementType is AVTTypeArray then begin
            self.fldDimensionsCount := AVTTypeArray(elementType).fldDimensionsCount + 1;
            self.fldCellType := AVTTypeArray(elementType).fldCellType;
        end else begin
            self.fldDimensionsCount := 1;
            self.fldCellType := elementType;
        end;
    end;

    procedure AVTTypeArray.afterConstruction();
    var
        pck: AVTPackage;
        app: AVTProgramme;
    begin
        inherited afterConstruction();
        pck := package;
        if pck <> nil then begin
            app := pck.fldParentProgramme;
            if app <> nil then app.addArray(self);
        end;
    end;

    procedure AVTTypeArray.makeCompilable();
    var
        tpe: AVTType;
    begin
        if fldCompilable then exit;
        fldCompilable := true;
        tpe := fldElementType;
        while tpe is AVTTypeArray do begin
            AVTTypeArray(tpe).fldCompilable := true;
            tpe := AVTTypeArray(tpe).fldElementType;
        end;
    end;

    function AVTTypeArray.isAssignableFrom(from: AVTType): boolean;
    var
        idx: int;
        dc0: int;
        dc1: int;
        tp0: AVTType;
        tp1: AVTType;
        tpe: AVTTypeArray;
    begin
        if from = nil then begin
            result := true;
            exit;
        end;
        if not(from is AVTTypeArray) then begin
            result := false;
            exit;
        end;
        tp0 := fldCellType;
        dc0 := fldDimensionsCount;
        with AVTTypeArray(from) do begin
            tp1 := fldCellType;
            dc1 := fldDimensionsCount;
        end;
        if dc0 = dc1 then begin
            result := tp0.isAssignableFrom(tp1);
            exit;
        end;
        if (dc0 > dc1) or not(tp0 is AVTTypeStructured) then begin
            result := false;
            exit;
        end;
        tpe := AVTTypeArray(from);
        for idx := dc0 - 1 downto 0 do tpe := tpe.fldElementType as AVTTypeArray;
        result := tpe.isImplements(AVTTypeStructured(tp0));
    end;

    function AVTTypeArray.isArray(): boolean;
    begin
        result := true;
    end;
{%endregion}

{%region AVTMember }
    class function AVTMember.getSource(item: AVTItemExt): AVTSource;
    begin
        if item = nil then begin
            result := nil;
            exit;
        end;
        result := item.fldSource;
    end;

    function AVTMember.getFullName(): AnsiString;
    var
        tpp: AVTTypeStructured;
    begin
        tpp := fldParentType;
        if tpp = nil then begin
            result := inherited getFullName();
            exit;
        end;
        result := tpp.fldFullName + '.' + fldSimpleName;
    end;

    function AVTMember.getFasmFullName(): AnsiString;
    var
        tpp: AVTTypeStructured;
    begin
        tpp := fldParentType;
        if tpp = nil then begin
            result := fldSimpleName;
            exit;
        end;
        result := tpp.fldFasmArgument + '$' + fldSimpleName;
    end;

    function AVTMember.getFasmShortName(): AnsiString;
    begin
        result := fldSimpleName;
    end;

    constructor AVTMember.create(parentType: AVTTypeStructured; flags: int; const simpleName: AnsiString; declarationPosition: int; const documentation: UnicodeString);
    begin
        inherited create(parentType, flags, simpleName, getSource(parentType), declarationPosition, documentation);
        self.fldParentType := parentType;
    end;

    procedure AVTMember.afterConstruction();
    var
        tpp: AVTTypeStructured;
    begin
        inherited afterConstruction();
        tpp := fldParentType;
        if tpp <> nil then tpp.addMember(self);
    end;

    function AVTMember.isVisible(target, from: AVTTypeStructured): boolean;
    label
        label0;
    var
        obj: TObject;
        enm: Enumeration;
        tpc: AVTTypeStructured;
        tpp: AVTTypeStructured;
    begin
        tpp := fldParentType;
        if target = nil then begin
            target := tpp;
        end;
        if not target.isImplements(tpp) then begin
            raise IllegalArgumentException.create('AVTMember.isVisible: ' + msgIllegalArgument + 'target');
        end;
        if from = nil then begin
            raise NullPointerException.create('AVTMember.isVisible: ' + msgNullPointerArgument + 'from');
        end;
        case getVisibility() of
        AVT_PRIVATE: begin
            if (target = tpp) and (tpp = from) then begin
                result := true;
                exit;
            end;
        end;
        AVT_SOURCE: begin
            { На будущее: совпадать должны не сами исходные тексты (obj1.fldSource = obj2.fldSource),
              а их пакеты и простые имена ((source1.fldPackage = source2.fldPackage) and (source1.fldSimpleName = source2.fldSimpleName)) }
            obj := from.fldSource;
            if target.fldSource = obj then begin
                enm := target.implementsAll();
                while enm.hasMoreElements() do begin
                    tpc := enm.nextElement().objectValue() as AVTTypeStructured;
                    if target.isImplements(tpc) and tpc.isImplements(tpp) and (tpc.fldSource <> obj) then goto label0;
                end;
                result := true;
                exit;
            end;
        end;
        AVT_PACKAGE: begin
            obj := from.fldPackage;
            if target.fldPackage = obj then begin
                enm := target.implementsAll();
                while enm.hasMoreElements() do begin
                    tpc := enm.nextElement().objectValue() as AVTTypeStructured;
                    if target.isImplements(tpc) and tpc.isImplements(tpp) and (tpc.fldPackage <> obj) then goto label0;
                end;
                result := true;
                exit;
            end;
        end;
        AVT_PROTECTED: begin
            if target.isImplements(from) and from.isImplements(tpp) or (tpp.fldPackage = from.fldPackage) then begin
                result := true;
                exit;
            end;
        end;
        AVT_PUBLIC, AVT_PUBLISHED: begin
            result := true;
            exit;
        end;
        end;
        label0:
        result := false;
    end;
{%endregion}

{%region AVTField }
    function AVTField.getAvtcType(): AnsiString;
    begin
        result := fldValueType.fldAvtcType;
    end;

    constructor AVTField.create(parentType: AVTTypeStructured; flags: int; valueType: AVTType; length: int; const simpleName: AnsiString; declarationPosition: int; const documentation: UnicodeString);
    begin
        inherited create(parentType, flags, simpleName, declarationPosition, documentation);
        self.fldValueType := valueType;
        if valueType is AVTTypeArray then begin
            self.fldLength := length;
        end else begin
            self.fldLength := 0;
        end;
    end;

    destructor AVTField.destroy;
    begin
        fldValueConst.free();
        inherited destroy;
    end;

    procedure AVTField.afterConstruction();
    begin
        inherited afterConstruction();
        fldFasmStructName := fldFasmFullName + '.struct';
    end;

    procedure AVTField.makeValueConstCreated();
    begin
        fldValueConstCreated := true;
        fldValueConstCreating := false;;
    end;

    procedure AVTField.makeValueConstCreating();
    begin
        fldValueConstCreated := false;
        fldValueConstCreating := true;
    end;

    function AVTField.createValueConst(): AVTConstant;
    var
        con: AVTConstant;
    begin
        con := fldValueConst;
        if con = nil then begin
            con := AVTConstant.create();
            fldValueConst := con;
        end;
        result := con;
    end;
{%endregion}

{%region AVTOverriddable.OverriddenEnumerator }
    procedure AVTOverriddable.OverriddenEnumerator.next();
    var
        idx: int;
        len: int;
        vec: Vector;
        mmt: AVTOverriddable;
        mms: AVTOverriddable;
        tpp: AVTTypeStructured;
        ste: AVTTypeStructured.SuperType;
    begin
        idx := index;
        mmt := thisMember;
        tpp := mmt.fldParentType;
        vec := tpp.fldImplementsAsVector;
        if vec = nil then begin
            len := 0;
        end else begin
            len := vec.size();
        end;
        repeat
            if idx < 0 then begin
                ste := tpp.fldExtends;
                if ste = nil then begin
                    mms := nil;
                end else begin
                    mms := ste.getSuperMember(mmt);
                end;
            end else
            if idx >= len then begin
                mms := nil;
            end else begin
                mms := (vec.elementAt(idx).objectValue() as AVTTypeStructured.SuperType).getSuperMember(mmt);
            end;
            inc(idx);
        until (mms <> nil) or (idx >= len);
        superMember := mms;
        index := idx;
    end;

    constructor AVTOverriddable.OverriddenEnumerator.create(thisMember: AVTOverriddable);
    begin
        inherited create();
        self.index := -1;
        self.thisMember := thisMember;
        next();
    end;

    function AVTOverriddable.OverriddenEnumerator.hasMoreElements(): boolean;
    begin
        result := superMember <> nil;
    end;

    function AVTOverriddable.OverriddenEnumerator.nextElement(): Value;
    var
        mms: AVTOverriddable;
    begin
        mms := superMember;
        if mms = nil then begin
            raise NoSuchElementException.create('Enumeration.nextElement: ' + msgNoSuchElement);
        end;
        next();
        result := ValueOfObject.create(mms, false);
    end;
{%endregion}

{%region AVTOverriddable }
    function AVTOverriddable.isOverriddable(member: AVTOverriddable): boolean;
    begin
        result := not isStatic() and not member.isStatic() and (fldSimpleName = member.fldSimpleName);
    end;

    procedure AVTOverriddable.findOverriddenMembers();
    label
        label0;
    var
        idx: int;
        len: int;
        vis: int;
        nam: AnsiString;
        vec: Vector;
        mms: AVTMember;
        enm: Enumeration;
        tpp: AVTTypeStructured;
        tps: AVTTypeStructured;
        spt: AVTTypeStructured.SuperType;
    begin
        if isStatic() then exit;
        nam := fldSimpleName;
        tpp := fldParentType;
        spt := tpp.fldExtends;
        vis := getVisibility();
        if spt <> nil then begin
            tps := spt.fldSuperReference;
            repeat
                enm := tps.members(nam);
                while enm.hasMoreElements() do begin
                    mms := enm.nextElement().objectValue() as AVTMember;
                    if (mms is AVTOverriddable) and mms.isVisible(tpp, tpp) and (vis >= mms.getVisibility()) and isOverriddable(AVTOverriddable(mms)) then begin
                        spt.addOverridden(self, AVTOverriddable(mms));
                        goto label0;
                    end;
                end;
                tps := tps.extends();
            until tps = nil;
        end;
        label0:
        vec := tpp.fldImplementsAsVector;
        if vec = nil then begin
            len := 0;
        end else begin
            len := vec.size();
        end;
        for idx := 0 to len - 1 do begin
            spt := vec.elementAt(idx).objectValue() as AVTTypeStructured.SuperType;
            tps := spt.fldSuperReference;
            enm := tps.members(nam);
            while enm.hasMoreElements() do begin
                mms := enm.nextElement().objectValue() as AVTMember;
                if (mms is AVTOverriddable) and mms.isVisible(tpp, tpp) and (vis >= mms.getVisibility()) and isOverriddable(AVTOverriddable(mms)) then begin
                    spt.addOverridden(self, AVTOverriddable(mms));
                    break;
                end;
            end;
        end;
    end;

    function AVTOverriddable.isOverridden(): boolean;
    begin
        if fldOverridden then begin
            result := true;
            exit;
        end;
        if isStatic() or not fldParentType.isClass() then begin
            result := false;
            exit;
        end;
        if isAbstract() then begin
            result := true;
            exit;
        end;
        with overriddenMembers() do while hasMoreElements() do if (nextElement().objectValue() as AVTMember).fldParentType.isClass() then begin
            result := true;
            exit;
        end;
        result := false;
    end;

    function AVTOverriddable.isOverride(member: AVTOverriddable): boolean;
    begin
        with OverriddenEnumerator.create(self) as Enumeration do while hasMoreElements() do if nextElement().objectValue() = member then begin
            result := true;
            exit;
        end;
        result := false;
    end;

    function AVTOverriddable.mismatchThrows(member: AVTOverriddable): AVTTypeStructured;
    begin
        result := nil;
    end;

    function AVTOverriddable.overriddenMembers(): Enumeration;
    begin
        result := OverriddenEnumerator.create(self);
    end;
{%endregion}

{%region AVTMethod }
    function AVTMethod.containsIn(methodList: Vector): boolean;
    var
        vec: Vector;
        mmc: TObject;
    begin
        vec := fldArgumentsAsVector;
        with methodList.elements() do while hasMoreElements() do begin
            mmc := nextElement().objectValue();
            if (mmc is AVTMethod) and AVTMethod(mmc).isIdentityArguments(vec) then begin
                result := true;
                exit;
            end;
        end;
        result := false;
    end;

    function AVTMethod.isOverriddable(member: AVTOverriddable): boolean;
    begin
        result := (member is AVTMethod) and inherited isOverriddable(member) and isIdentityArguments(AVTMethod(member).fldArgumentsAsVector);
    end;

    function AVTMethod.getFullName(): AnsiString;
    begin
        result := inherited getFullName() + argumentsToString();
    end;

    function AVTMethod.getAvtcType(): AnsiString;
    var
        idx: int;
        res: AnsiString;
        vec: Vector;
    begin
        res := '(';
        vec := fldArgumentsAsVector;
        for idx := 0 to vec.size() - 1 do begin
            res := res + (vec.elementAt(idx).objectValue() as AVTVariable).fldValueType.fldAvtcType;
        end;
        result := res + ')' + fldReturnType.fldAvtcType;
    end;

    function AVTMethod.getFasmFullName(): AnsiString;
    var
        idx: int;
        nam: AnsiString;
        vec: Vector;
        tpp: AVTTypeStructured;
    begin
        vec := fldArgumentsAsVector;
        tpp := fldParentType;
        if tpp = nil then begin
            nam := getFasmSimpleName() + '$';
        end else begin
            nam := tpp.fldFasmArgument + '$' + getFasmSimpleName() + '$';
        end;
        for idx := 0 to vec.size() - 1 do begin
            nam := nam + (vec.elementAt(idx).objectValue() as AVTVariable).fldValueType.fldFasmArgument + '$';
        end;
        result := nam;
    end;

    function AVTMethod.getFasmShortName(): AnsiString;
    var
        idx: int;
        nam: AnsiString;
        vec: Vector;
    begin
        vec := fldArgumentsAsVector;
        nam := getFasmSimpleName() + '$';
        for idx := 0 to vec.size() - 1 do begin
            nam := nam + (vec.elementAt(idx).objectValue() as AVTVariable).fldValueType.fldFasmArgument + '$';
        end;
        result := nam;
    end;

    function AVTMethod.getFasmSimpleName(): AnsiString;
    begin
        result := fldSimpleName;
    end;

    constructor AVTMethod.create(parentType: AVTTypeStructured; flags: int; returnType: AVTType; const simpleName: AnsiString; arguments: Vector; declarationPosition: int; throwsPosition: int; const documentation: UnicodeString);
    var
        idx: int;
        vec: Vector;
        tab: Hashtable;
        arg: AVTVariable;
    begin
        inherited create(parentType, flags, simpleName, declarationPosition, documentation);
        if returnType = nil then begin
            returnType := parentType.fldPackage.fldParentProgramme.fldSystemPackage.getType(AVTTypePrimitive.getName(AVT_VOID));
        end;
        vec := Vector.create();
        tab := Hashtable.create();
        if arguments <> nil then begin
            for idx := 0 to arguments.size() - 1 do begin
                arg := arguments.elementAt(idx).objectValue() as AVTVariable;
                arg := AVTVariable.create(arg.fldValueType, arg.fldSimpleName, arg.fldSource, arg.fldDeclarationPosition);
                tab.put(ValueOfAnsiString.create(arg.fldSimpleName), ValueOfObject.create(arg, false));
                vec.append(ValueOfObject.create(arg));
            end;
        end;
        self.fldVirtualIndex := -1;
        self.fldServiceIndex := -1;
        self.fldThrowsPosition := throwsPosition;
        self.fldReturnType := returnType;
        if (flags and FLAG_STATIC) = 0 then begin
            self.fldArgumentThis := AVTVariable.create(parentType, 'this');
        end;
        self.fldArgumentsAsVector := vec;
        self.fldArgumentsAsTable := tab;
        if (flags and (FLAG_ABSTRACT or FLAG_NATIVE)) = 0 then begin
            self.fldCode := AVTCode.create(self);
        end;
        self.fldDebugInfoLineNumbers := int_Array1d_create(7);
    end;

    destructor AVTMethod.destroy;
    begin
        fldCode.free();
        fldThrows.free();
        fldArgumentThis.free();
        fldArgumentsAsTable.free();
        fldArgumentsAsVector.free();
        inherited destroy;
    end;

    procedure AVTMethod.addThrows(exceptionClass: AVTTypeStructured);
    var
        vec: Vector;
    begin
        if exceptionClass = nil then begin
            raise NullPointerException.create('AVTMethod.addThrows: ' + msgNullPointerArgument + 'exceptionClass');
        end;
        vec := fldThrows;
        if vec = nil then begin
            vec := Vector.create();
            fldThrows := vec;
        end;
        vec.append(ValueOfObject.create(exceptionClass, false));
    end;

    function AVTMethod.isTypeOverriddable(member: AVTOverriddable): boolean;
    begin
        result := (member is AVTMethod) and AVTMethod(member).fldReturnType.isAssignableFrom(fldReturnType);
    end;

    function AVTMethod.isIdentityArguments(arguments: Vector): boolean;
    var
        idx: int;
        sz0: int;
        sz1: int;
        vc0: Vector;
        vc1: Vector absolute arguments;
    begin
        vc0 := fldArgumentsAsVector;
        sz0 := vc0.size();
        if vc1 = nil then begin
            sz1 := 0;
        end else begin
            sz1 := vc1.size();
        end;
        if sz0 <> sz1 then begin
            result := false;
            exit;
        end;
        for idx := 0 to sz0 - 1 do begin
            if (vc0.elementAt(idx).objectValue() as AVTVariable).fldValueType <> (vc1.elementAt(idx).objectValue() as AVTVariable).fldValueType then begin
                result := false;
                exit;
            end;
        end;
        result := true;
    end;

    function AVTMethod.isIdentityArguments(method: AVTMethod): boolean;
    begin
        if method = nil then begin
            raise NullPointerException.create('AVTMethod.isIdentityArguments: ' + msgNullPointerArgument + 'method');
        end;
        result := isIdentityArguments(method.fldArgumentsAsVector);
    end;

    function AVTMethod.isIdentityArgumentTypes(argumentTypes: Vector): boolean;
    var
        idx: int;
        sz0: int;
        sz1: int;
        vc0: Vector;
        vc1: Vector absolute argumentTypes;
    begin
        vc0 := fldArgumentsAsVector;
        sz0 := vc0.size();
        if vc1 = nil then begin
            sz1 := 0;
        end else begin
            sz1 := vc1.size();
        end;
        if sz0 <> sz1 then begin
            result := false;
            exit;
        end;
        for idx := 0 to sz0 - 1 do begin
            if (vc0.elementAt(idx).objectValue() as AVTVariable).fldValueType <> vc1.elementAt(idx).objectValue() then begin
                result := false;
                exit;
            end;
        end;
        result := true;
    end;

    function AVTMethod.isConvertableArgumentTypes(argumentTypes: Vector): boolean;
    var
        idx: int;
        sz0: int;
        sz1: int;
        vc0: Vector;
        vc1: Vector absolute argumentTypes;
    begin
        vc0 := fldArgumentsAsVector;
        sz0 := vc0.size();
        if vc1 = nil then begin
            sz1 := 0;
        end else begin
            sz1 := vc1.size();
        end;
        if sz0 <> sz1 then begin
            result := false;
            exit;
        end;
        for idx := 0 to sz0 - 1 do begin
            if not (vc0.elementAt(idx).objectValue() as AVTVariable).fldValueType.isConvertableFrom(vc1.elementAt(idx).objectValue() as AVTType) then begin
                result := false;
                exit;
            end;
        end;
        result := true;
    end;

    function AVTMethod.isThrows(exceptionClass: AVTTypeStructured): boolean;
    var
        vec: Vector;
    begin
        if exceptionClass = nil then begin
            raise NullPointerException.create('AVTMethod.isThrows: ' + msgNullPointerArgument + 'exceptionClass');
        end;
        vec := fldThrows;
        result := (vec <> nil) and vec.contains(ValueOfObject.create(exceptionClass, false));
    end;

    function AVTMethod.mightThrown(exceptionClass: AVTTypeStructured): boolean;
    var
        idx: int;
        vec: Vector;
        app: AVTProgramme;
        pck_avt_lang: AVTPackage;
        typ_avt_lang_Error: AVTTypeStructured;
        typ_avt_lang_RuntimeException: AVTTypeStructured;
    begin
        if exceptionClass = nil then begin
            result := true;
            exit;
        end;
        app := fldParentType.fldPackage.fldParentProgramme;
        pck_avt_lang := app.getPackage('avt.lang');
        if pck_avt_lang = nil then begin
            typ_avt_lang_RuntimeException := nil;
            typ_avt_lang_Error := nil;
        end else begin
            typ_avt_lang_RuntimeException := pck_avt_lang.getType('RuntimeException') as AVTTypeStructured;
            typ_avt_lang_Error := pck_avt_lang.getType('Error') as AVTTypeStructured;
        end;
        if (typ_avt_lang_RuntimeException <> nil) and exceptionClass.isImplements(typ_avt_lang_RuntimeException) or (typ_avt_lang_Error <> nil) and exceptionClass.isImplements(typ_avt_lang_Error) then begin
            result := true;
            exit;
        end;
        vec := fldThrows;
        if vec = nil then begin
            result := false;
            exit;
        end;
        for idx := 0 to vec.size() - 1 do begin
            if exceptionClass.isImplements(vec.elementAt(idx).objectValue() as AVTTypeStructured) then begin
                result := true;
                exit;
            end;
        end;
        result := false;
    end;

    function AVTMethod.mightThrown(): boolean;
    var
        idx: int;
        vec: Vector;
        app: AVTProgramme;
        tpe: AVTTypeStructured;
        pck_avt_lang: AVTPackage;
        typ_avt_lang_Error: AVTTypeStructured;
        typ_avt_lang_RuntimeException: AVTTypeStructured;
    begin
        app := fldParentType.fldPackage.fldParentProgramme;
        pck_avt_lang := app.getPackage('avt.lang');
        if pck_avt_lang = nil then begin
            typ_avt_lang_RuntimeException := nil;
            typ_avt_lang_Error := nil;
        end else begin
            typ_avt_lang_RuntimeException := pck_avt_lang.getType('RuntimeException') as AVTTypeStructured;
            typ_avt_lang_Error := pck_avt_lang.getType('Error') as AVTTypeStructured;
        end;
        vec := fldThrows;
        if vec = nil then begin
            result := false;
            exit;
        end;
        for idx := 0 to vec.size() - 1 do begin
            tpe := vec.elementAt(idx).objectValue() as AVTTypeStructured;
            if (typ_avt_lang_RuntimeException <> nil) and tpe.isImplements(typ_avt_lang_RuntimeException) or (typ_avt_lang_Error <> nil) and tpe.isImplements(typ_avt_lang_Error) then continue;
            result := true;
            exit;
        end;
        result := false;
    end;

    function AVTMethod.mismatchThrows(member: AVTOverriddable): AVTTypeStructured;
    var
        idx: int;
        vec: Vector;
        tpe: AVTTypeStructured;
    begin
        vec := fldThrows;
        if not(member is AVTMethod) then begin
            if (vec = nil) or (vec.size() <= 0) then begin
                result := nil;
                exit;
            end;
            result := vec.elementAt(0).objectValue() as AVTTypeStructured;
            exit;
        end;
        if vec = nil then begin
            result := nil;
            exit;
        end;
        for idx := 0 to vec.size() - 1 do begin
            tpe := vec.elementAt(idx).objectValue() as AVTTypeStructured;
            if AVTMethod(member).mightThrown(tpe) then continue;
            result := tpe;
            exit;
        end;
        result := nil;
    end;

    function AVTMethod.argumentsToString(): AnsiString;
    var
        idx: int;
        lim: int;
        str: AnsiString;
        vec: Vector;
    begin
        str := fldArgumentsAsString;
        if length(str) > 0 then begin
            result := str;
            exit;
        end;
        str := '(';
        vec := fldArgumentsAsVector;
        lim := vec.size() - 1;
        for idx := 0 to lim do begin
            str := str + (vec.elementAt(idx).objectValue() as AVTVariable).fldValueType.fldFullName;
            if idx < lim then str := str + ', ';
        end;
        str := str + ')';
        fldArgumentsAsString := str;
        result := str;
    end;

    function AVTMethod.getArgument(const name: AnsiString): AVTVariable;
    var
        val: Value;
    begin
        val := fldArgumentsAsTable.get(ValueOfAnsiString.create(name));
        if val = nil then begin
            result := nil;
            exit;
        end;
        result := val.objectValue() as AVTVariable;
    end;

    function AVTMethod.getArgumentAt(index: int): AVTVariable;
    var
        vec: Vector;
    begin
        vec := fldArgumentsAsVector;
        if (index < 0) and (index >= vec.size()) then begin
            raise IndexOutOfBoundsException.create('AVTMethod.getArgumentAt: ' + msgIndexOutOfBounds);
        end;
        result := vec.elementAt(index).objectValue() as AVTVariable;
    end;

    function AVTMethod.getArgumentsCount(): int;
    begin
        result := fldArgumentsAsVector.size();
    end;

    function AVTMethod.getDebugInfoLength(): int;
    begin
        result := fldDebugInfoLength;
    end;

    function AVTMethod.getDebugInfoLineNumber(labelIndex: int): int;
    begin
        if (labelIndex < 0) or (labelIndex >= fldDebugInfoLength) then begin
            raise IndexOutOfBoundsException.create(msgIndexOutOfBounds);
        end;
        result := fldDebugInfoLineNumbers[labelIndex];
    end;

    function AVTMethod.addDebugInfoLineNumber(lineNumber: int): int;
    var
        len: int;
        ain: int_Array1d;
        bin: int_Array1d;
    begin
        len := fldDebugInfoLength;
        ain := fldDebugInfoLineNumbers;
        if len = length(ain) then begin
            bin := int_Array1d_create((len shl 1) + 1);
            arraycopyPrimitives(ain, 0, bin, 0, len);
            fldDebugInfoLineNumbers := bin;
            ain := bin;
        end;
        ain[len] := lineNumber;
        fldDebugInfoLength := len + 1;
        result := len;
    end;

    function AVTMethod.createWithVariable(valueType: AVTTypeStructured): AVTVariable;
    var
        num: int;
    begin
        num := fldWithNumber;
        fldWithNumber := num + 1;
        result := AVTVariable.create(valueType, 'with.' + intToString(num), fldSource);
    end;

    function AVTMethod.createMonitorVariable(valueType: AVTTypeStructured): AVTVariable;
    var
        num: int;
    begin
        num := fldMonitorNumber;
        fldMonitorNumber := num + 1;
        result := AVTVariable.create(valueType, 'monitor.' + intToString(num), fldSource);
    end;

    function AVTMethod.arguments(): Enumeration;
    begin
        result := fldArgumentsAsVector.elements();
    end;

    function AVTMethod.throws(): Enumeration;
    var
        vec: Vector;
    begin
        vec := fldThrows;
        if vec = nil then begin
            result := EmptyEnumerator.create();
            exit;
        end;
        result := vec.elements();
    end;
{%endregion}

{%region AVTOperator }
    class function AVTOperator.operatorToChar(operatorKind: int): AnsiString;
    begin
        case operatorKind of
        SET_ARRAY_ELEMENT:   result := '[]=';   { void operator []=(T index, T value)          }
        GET_ARRAY_ELEMENT:   result := '[]';    { T operator [](T index)                       }
        INVOKE_VIRTUAL:      result := '()';    { T|void operator ()(T arg1, T arg2, … T argN) }
        OPER_BIT_NOT:        result := '~';     { T operator ~()                               }
        OPER_BIT_AND:        result := '&';     { T operator &(T operand)                      }
        OPER_BIT_OR:         result := '|';     { T operator |(T operand)                      }
        OPER_BIT_XOR:        result := '^';     { T operator ^(T operand)                      }
        OPER_SCAL_PLUS:      result := '+';     { T operator +()                               }
        OPER_SCAL_MINUS:     result := '-';     { T operator -()                               }
        OPER_SCAL_MUL:       result := '*';     { T operator *(T operand)                      }
        OPER_SCAL_DIV:       result := '/';     { T operator /(T operand)                      }
        OPER_SCAL_DIVU:      result := '//';    { T operator //(T operand)                     }
        OPER_SCAL_REM:       result := '%';     { T operator %(T operand)                      }
        OPER_SCAL_REMU:      result := '%%';    { T operator %%(T operand)                     }
        OPER_SCAL_ADD:       result := '+';     { T operator +(T operand)                      }
        OPER_SCAL_SUB:       result := '-';     { T operator -(T operand)                      }
        OPER_SCAL_SAR:       result := '>>';    { T operator >>(T operand)                     }
        OPER_SCAL_SAL:       result := '<<';    { T operator <<(T operand)                     }
        OPER_SCAL_SHR:       result := '>>>';   { T operator >>>(T operand)                    }
        OPER_SCAL_G:         result := '>';     { boolean operator >(T operand)                }
        OPER_SCAL_GE:        result := '>=';    { boolean operator >=(T operand)               }
        OPER_SCAL_L:         result := '<';     { boolean operator <(T operand)                }
        OPER_SCAL_LE:        result := '<=';    { boolean operator <=(T operand)               }
        OPER_VECT_UNPCKL:    result := '####';  { T operator ####()                            }
        OPER_VECT_UNPCKU:    result := '^^^^';  { T operator ^^^^()                            }
        OPER_VECT_PACK:      result := '@@@@';  { T operator @@@@()                            }
        OPER_VECT_PLUS:      result := '++++';  { T operator ++++()                            }
        OPER_VECT_MINUS:     result := '----';  { T operator ----()                            }
        OPER_VECT_MUL:       result := '****';  { T operator ****(T operand)                   }
        OPER_VECT_DIV:       result := '////';  { T operator ////(T operand)                   }
        OPER_VECT_ADD:       result := '++++';  { T operator ++++(T operand)                   }
        OPER_VECT_SUB:       result := '----';  { T operator ----(T operand)                   }
        OPER_VECT_SAR:       result := '>>>>';  { T operator >>>>(T operand)                   }
        OPER_VECT_SAL:       result := '<<<<';  { T operator <<<<(T operand)                   }
        OPER_VECT_SHR:       result := '>>>>>'; { T operator >>>>>(T operand)                  }
        OPER_VECT_G:         result := '|>>|';  { T operator |>>|(T operand)                   }
        OPER_VECT_GE:        result := '|>=|';  { T operator |>=|(T operand)                   }
        OPER_VECT_L:         result := '|<<|';  { T operator |<<|(T operand)                   }
        OPER_VECT_LE:        result := '|<=|';  { T operator |<=|(T operand)                   }
        OPER_VECT_E:         result := '|==|';  { T operator |==|(T operand)                   }
        OPER_VECT_NE:        result := '|!=|';  { T operator |!=|(T operand)                   }
        OPER_VECT_MULS:      result := '|**|';  { T operator |**|(T operand)                   }
        OPER_VECT_ADDS:      result := '|++|';  { T operator |++|(T operand)                   }
        OPER_VECT_SUBS:      result := '|--|';  { T operator |--|(T operand)                   }
        OPER_VECT_MULU:      result := '#**#';  { T operator #**#(T operand)                   }
        OPER_VECT_ADDU:      result := '#++#';  { T operator #++#(T operand)                   }
        OPER_VECT_SUBU:      result := '#--#';  { T operator #--#(T operand)                   }
        else                 result := '';
        end;
    end;

    class function AVTOperator.operatorToName(operatorKind: int): AnsiString;
    begin
        case operatorKind of
        SET_ARRAY_ELEMENT:   result := 'awr';   { void operator []=(T index, T value)          }
        GET_ARRAY_ELEMENT:   result := 'ard';   { T operator [](T index)                       }
        INVOKE_VIRTUAL:      result := 'par';   { T|void operator ()(T arg1, T arg2, … T argN) }
        OPER_BIT_NOT:        result := 'not';   { T operator ~()                               }
        OPER_BIT_AND:        result := 'and';   { T operator &(T operand)                      }
        OPER_BIT_OR:         result := 'or';    { T operator |(T operand)                      }
        OPER_BIT_XOR:        result := 'xor';   { T operator ^(T operand)                      }
        OPER_SCAL_PLUS:      result := 'pos';   { T operator +()                               }
        OPER_SCAL_MINUS:     result := 'neg';   { T operator -()                               }
        OPER_SCAL_MUL:       result := 'mul';   { T operator *(T operand)                      }
        OPER_SCAL_DIV:       result := 'div';   { T operator /(T operand)                      }
        OPER_SCAL_DIVU:      result := 'divu';  { T operator //(T operand)                     }
        OPER_SCAL_REM:       result := 'rem';   { T operator %(T operand)                      }
        OPER_SCAL_REMU:      result := 'remu';  { T operator %%(T operand)                     }
        OPER_SCAL_ADD:       result := 'add';   { T operator +(T operand)                      }
        OPER_SCAL_SUB:       result := 'sub';   { T operator -(T operand)                      }
        OPER_SCAL_SAR:       result := 'sar';   { T operator >>(T operand)                     }
        OPER_SCAL_SAL:       result := 'sal';   { T operator <<(T operand)                     }
        OPER_SCAL_SHR:       result := 'shr';   { T operator >>>(T operand)                    }
        OPER_SCAL_G:         result := 'g';     { boolean operator >(T operand)                }
        OPER_SCAL_GE:        result := 'ge';    { boolean operator >=(T operand)               }
        OPER_SCAL_L:         result := 'l';     { boolean operator <(T operand)                }
        OPER_SCAL_LE:        result := 'le';    { boolean operator <=(T operand)               }
        OPER_VECT_UNPCKL:    result := 'vupl';  { T operator ####()                            }
        OPER_VECT_UNPCKU:    result := 'vupu';  { T operator ^^^^()                            }
        OPER_VECT_PACK:      result := 'vpck';  { T operator @@@@()                            }
        OPER_VECT_PLUS:      result := 'vpos';  { T operator ++++()                            }
        OPER_VECT_MINUS:     result := 'vneg';  { T operator ----()                            }
        OPER_VECT_MUL:       result := 'vmul';  { T operator ****(T operand)                   }
        OPER_VECT_DIV:       result := 'vdiv';  { T operator ////(T operand)                   }
        OPER_VECT_ADD:       result := 'vadd';  { T operator ++++(T operand)                   }
        OPER_VECT_SUB:       result := 'vsub';  { T operator ----(T operand)                   }
        OPER_VECT_SAR:       result := 'vsar';  { T operator >>>>(T operand)                   }
        OPER_VECT_SAL:       result := 'vsal';  { T operator <<<<(T operand)                   }
        OPER_VECT_SHR:       result := 'vshr';  { T operator >>>>>(T operand)                  }
        OPER_VECT_G:         result := 'vg';    { T operator |>>|(T operand)                   }
        OPER_VECT_GE:        result := 'vge';   { T operator |>=|(T operand)                   }
        OPER_VECT_L:         result := 'vl';    { T operator |<<|(T operand)                   }
        OPER_VECT_LE:        result := 'vle';   { T operator |<=|(T operand)                   }
        OPER_VECT_E:         result := 've';    { T operator |==|(T operand)                   }
        OPER_VECT_NE:        result := 'vne';   { T operator |!=|(T operand)                   }
        OPER_VECT_MULS:      result := 'vmuls'; { T operator |**|(T operand)                   }
        OPER_VECT_ADDS:      result := 'vadds'; { T operator |++|(T operand)                   }
        OPER_VECT_SUBS:      result := 'vsubs'; { T operator |--|(T operand)                   }
        OPER_VECT_MULU:      result := 'vmulu'; { T operator #**#(T operand)                   }
        OPER_VECT_ADDU:      result := 'vaddu'; { T operator #++#(T operand)                   }
        OPER_VECT_SUBU:      result := 'vsubu'; { T operator #--#(T operand)                   }
        else                 result := '';
        end;
    end;

    class function AVTOperator.operatorToSpecName(operatorKind: int): AnsiString;
    begin
        result := '<' + operatorToName(operatorKind) + '>';
    end;

    class function AVTOperator.specNameToOperator(const operatorName: AnsiString): int;
    var
        id0: int;
        id1: int;
        nam: AnsiString;
    begin
        id0 := 1;
        id1 := length(operatorName) + 1;
        if id1 > 1 then begin
            if operatorName[1] = '<' then inc(id0);
            if operatorName[id1 - 1] = '>' then dec(id1);
        end;
        nam := stringCopy(operatorName, id0, id1);
        for id0 := 0 to $01ff do begin
            if operatorToName(id0) = nam then begin
                result := id0;
                exit;
            end;
        end;
        result := -1;
    end;

    function AVTOperator.getFullName(): AnsiString;
    var
        idx: int;
        lim: int;
        nam: AnsiString;
        vec: Vector;
        tpp: AVTTypeStructured;
    begin
        tpp := fldParentType;
        if tpp = nil then begin
            nam := 'operator ';
        end else begin
            nam := tpp.fldFullName + '.operator ';
        end;
        nam := nam + operatorToChar(fldOperatorKind) + '(';
        vec := fldArgumentsAsVector;
        lim := vec.size() - 1;
        for idx := 0 to lim do begin
            nam := nam + (vec.elementAt(idx).objectValue() as AVTVariable).fldValueType.fldFullName;
            if idx < lim then nam := nam + ', ';
        end;
        result := nam + ')';
    end;

    function AVTOperator.getFasmSimpleName(): AnsiString;
    begin
        result := '$' + operatorToName(fldOperatorKind) + '$';
    end;

    constructor AVTOperator.create(parentType: AVTTypeStructured; flags: int; returnType: AVTType; operatorKind: int; arguments: Vector; declarationPosition: int; const documentation: UnicodeString);
    begin
        inherited create(parentType, flags, returnType, operatorToSpecName(operatorKind), arguments, declarationPosition, -1, documentation);
        self.fldOperatorKind := operatorKind;
    end;
{%endregion}

{%region AVTSpecial }
    procedure AVTSpecial.findOverriddenMembers();
    begin
    end;

    function AVTSpecial.isOverride(member: AVTOverriddable): boolean;
    begin
        result := false;
    end;

    function AVTSpecial.overriddenMembers(): Enumeration;
    begin
        result := EmptyEnumerator.create();
    end;
{%endregion}

{%region AVTInstInit }
    function AVTInstInit.getFasmSimpleName(): AnsiString;
    begin
        result := '$init$';
    end;

    constructor AVTInstInit.create(parentType: AVTTypeStructured; visibility: int; arguments: Vector; declarationPosition: int; throwsPosition: int; const documentation: UnicodeString);
    begin
        inherited create(parentType, visibility and MASK_VISIBILITY, nil, SPECNAME_INST_INIT, arguments, declarationPosition, throwsPosition, documentation);
    end;
{%endregion}

{%region AVTClassInit }
    function AVTClassInit.getFasmSimpleName(): AnsiString;
    begin
        result := '$clinit$';
    end;

    constructor AVTClassInit.create(parentType: AVTTypeStructured; declarationPosition: int);
    begin
        inherited create(parentType, FLAG_SOURCE or FLAG_STATIC, nil, SPECNAME_CLASS_INIT, nil, declarationPosition);
    end;
{%endregion}

{%region AVTProperty }
    procedure AVTProperty.setIndex(index: int);
    begin
        self.fldHasIndex := true;
        self.fldIndex := index;
    end;

    procedure AVTProperty.setReadMember(member: _Object);
    var
        isc: boolean;
        con: AVTConstant;
    begin
        isc := member is AVTConstant;
        if isc then begin
            con := AVTConstant.create();
            con.assign(AVTConstant(member));
            member := con;
        end;
        self.fldReadIsConst := isc;
        self.fldReadMember := member;
        createReadSynthetic();
    end;

    procedure AVTProperty.setWriteMember(member: _Object);
    begin
        self.fldWriteMember := member;
        createWriteSynthetic();
    end;

    procedure AVTProperty.setStoredMember(member: _Object);
    var
        isc: boolean;
        con: AVTConstant;
    begin
        isc := member is AVTConstant;
        if isc then begin
            con := AVTConstant.create();
            con.assign(AVTConstant(member));
            member := con;
        end;
        self.fldStoredIsConst := isc;
        self.fldStoredMember := member;
        createStoredSynthetic();
    end;

    procedure AVTProperty.createReadSynthetic();
    var
        ndi: int;
        mmr: _Object;
        cod: AVTCode;
        ndr: AVTNode;
        nd0: AVTNode;
        nd1: AVTNode;
        nd2: AVTNode;
        nd3: AVTNode;
        nde: AVTNode;
        typ: AVTType;
        syn: AVTMethod;
        pck: AVTPackage;
        con: AVTConstant;
        vr0: AVTVariable;
        tpp: AVTTypeStructured;
        typ_void: AVTType;
    begin
        syn := fldReadSynthetic;
        if syn <> nil then exit;
        tpp := fldParentType;
        syn := AVTMethod.create(tpp, fldFlags and $1f or FLAG_SYNTHETIC, fldValueType, fldSimpleName + '.read', nil);
        syn.fldLinkedProperty := self;
        syn.findOverriddenMembers();
        fldReadSynthetic := syn;
        cod := syn.fldCode;
        if cod = nil then exit;
        pck := tpp.fldPackage.fldParentProgramme.fldSystemPackage;
        typ_void := pck.getType(AVTTypePrimitive.getName(AVT_VOID));
        ndr := cod.fldRoot;
        mmr := fldReadMember;
        if mmr is AVTConstant then begin
            con := AVTConstant.create();
            con.assign(AVTConstant(mmr));
            typ := con.fldValueType;
            nd0 := cod.appendNode(ndr);
            nd1 := cod.appendNode(nd0);
            nde := cod.appendNode(ndr);
            ndr.setData(NO_LINE_INDEX, typ_void, AVT_ENTER);       (*  {                   *)
            nd0.setData(NO_LINE_INDEX, typ_void, AVT_RETURN);      (*  ├── return          *)
            nd1.setData(NO_LINE_INDEX, typ, LOAD_CONST, con);      (*  │   └── <constant>  *)
            nde.setData(NO_LINE_INDEX, typ_void, AVT_LEAVE, typ);  (*  └── }               *)
            exit;
        end;
        vr0 := syn.fldArgumentThis;
        if mmr is AVTField then begin
            typ := AVTField(mmr).fldValueType;
            nd0 := cod.appendNode(ndr);
            nd1 := cod.appendNode(nd0);
            nd2 := cod.appendNode(nd1);
            nde := cod.appendNode(ndr);
            ndr.setData(NO_LINE_INDEX, typ_void, AVT_ENTER);                   (*  {                 *)
            nd0.setData(NO_LINE_INDEX, typ_void, AVT_RETURN);                  (*  ├── return        *)
            nd1.setData(NO_LINE_INDEX, typ, GET_FIELD, mmr);                   (*  │   └── .<field>  *)
            nd2.setData(NO_LINE_INDEX, vr0.fldValueType, LOAD_VARIABLE, vr0);  (*  │       └── this  *)
            nde.setData(NO_LINE_INDEX, typ_void, AVT_LEAVE, typ);              (*  └── }             *)
            exit;
        end;
        if not(mmr is AVTMethod) then exit;
        typ := AVTMethod(mmr).fldReturnType;
        if AVTItem(mmr).getVisibility() = AVT_PRIVATE then begin
            ndi := INVOKE_SPECIAL;
        end else
        if AVTMember(mmr).fldParentType.isService() then begin
            ndi := INVOKE_SERVICE;
        end else begin
            ndi := INVOKE_VIRTUAL;
        end;
        if fldHasIndex then begin
            con := AVTConstant.create(pck.getType(AVTTypePrimitive.getName(AVT_INT)));
            con.value.asInt := fldIndex;
            nd0 := cod.appendNode(ndr);
            nd1 := cod.appendNode(nd0);
            nd2 := cod.appendNode(nd1);
            nd3 := cod.appendNode(nd1);
            nde := cod.appendNode(ndr);
            ndr.setData(NO_LINE_INDEX, typ_void, AVT_ENTER);                   (*  {                        *)
            nd0.setData(NO_LINE_INDEX, typ_void, AVT_RETURN);                  (*  ├── return               *)
            nd1.setData(NO_LINE_INDEX, typ, ndi, mmr);                         (*  │   └── invoke <method>  *)
            nd2.setData(NO_LINE_INDEX, vr0.fldValueType, LOAD_VARIABLE, vr0);  (*  │       ├── this         *)
            nd3.setData(NO_LINE_INDEX, con.fldValueType, LOAD_CONST, con);     (*  │       └── <index>      *)
            nde.setData(NO_LINE_INDEX, typ_void, AVT_LEAVE, typ);              (*  └── }                    *)
            exit;
        end;
        nd0 := cod.appendNode(ndr);
        nd1 := cod.appendNode(nd0);
        nd2 := cod.appendNode(nd1);
        nde := cod.appendNode(ndr);
        ndr.setData(NO_LINE_INDEX, typ_void, AVT_ENTER);                   (*  {                        *)
        nd0.setData(NO_LINE_INDEX, typ_void, AVT_RETURN);                  (*  ├── return               *)
        nd1.setData(NO_LINE_INDEX, typ, ndi, mmr);                         (*  │   └── invoke <method>  *)
        nd2.setData(NO_LINE_INDEX, vr0.fldValueType, LOAD_VARIABLE, vr0);  (*  │       └── this         *)
        nde.setData(NO_LINE_INDEX, typ_void, AVT_LEAVE, typ);              (*  └── }                    *)
    end;

    procedure AVTProperty.createWriteSynthetic();
    var
        ndi: int;
        arg: Vector;
        mmw: _Object;
        cod: AVTCode;
        ndr: AVTNode;
        nd0: AVTNode;
        nd1: AVTNode;
        nd2: AVTNode;
        nd3: AVTNode;
        nde: AVTNode;
        syn: AVTMethod;
        pck: AVTPackage;
        con: AVTConstant;
        vr0: AVTVariable;
        vr1: AVTVariable;
        tpp: AVTTypeStructured;
        typ_void: AVTType;
    begin
        syn := fldWriteSynthetic;
        if syn <> nil then exit;
        tpp := fldParentType;
        arg := Vector.create();
        try
            arg.append(ValueOfObject.create(AVTVariable.create(fldValueType, 'value')));
            syn := AVTMethod.create(tpp, fldFlags and $1f or FLAG_SYNTHETIC, nil, fldSimpleName + '.write', arg);
        finally
            arg.free();
        end;
        syn.fldLinkedProperty := self;
        syn.findOverriddenMembers();
        fldWriteSynthetic := syn;
        cod := syn.fldCode;
        if cod = nil then exit;
        pck := tpp.fldPackage.fldParentProgramme.fldSystemPackage;
        typ_void := pck.getType(AVTTypePrimitive.getName(AVT_VOID));
        ndr := cod.fldRoot;
        mmw := fldWriteMember;
        vr0 := syn.fldArgumentThis;
        vr1 := syn.getArgumentAt(0);
        if mmw is AVTField then begin
            nd0 := cod.appendNode(ndr);
            nd1 := cod.appendNode(nd0);
            nd2 := cod.appendNode(nd0);
            nde := cod.appendNode(ndr);
            ndr.setData(NO_LINE_INDEX, typ_void, AVT_ENTER);                   (*  {               *)
            nd0.setData(NO_LINE_INDEX, typ_void, SET_FIELD, mmw);              (*  ├── .<field> =  *)
            nd1.setData(NO_LINE_INDEX, vr0.fldValueType, LOAD_VARIABLE, vr0);  (*  │   ├── this    *)
            nd2.setData(NO_LINE_INDEX, vr1.fldValueType, LOAD_VARIABLE, vr1);  (*  │   └── value   *)
            nde.setData(NO_LINE_INDEX, typ_void, AVT_LEAVE, typ_void);         (*  └── }           *)
            exit;
        end;
        if not(mmw is AVTMethod) then exit;
        if AVTItem(mmw).getVisibility() = AVT_PRIVATE then begin
            ndi := INVOKE_SPECIAL;
        end else
        if AVTMember(mmw).fldParentType.isService() then begin
            ndi := INVOKE_SERVICE;
        end else begin
            ndi := INVOKE_VIRTUAL;
        end;
        if fldHasIndex then begin
            con := AVTConstant.create(pck.getType(AVTTypePrimitive.getName(AVT_INT)));
            con.value.asInt := fldIndex;
            nd0 := cod.appendNode(ndr);
            nd1 := cod.appendNode(nd0);
            nd2 := cod.appendNode(nd0);
            nd3 := cod.appendNode(nd0);
            nde := cod.appendNode(ndr);
            ndr.setData(NO_LINE_INDEX, typ_void, AVT_ENTER);                   (*  {                    *)
            nd0.setData(NO_LINE_INDEX, typ_void, ndi, mmw);                    (*  ├── invoke <method>  *)
            nd1.setData(NO_LINE_INDEX, vr0.fldValueType, LOAD_VARIABLE, vr0);  (*  │   ├── this         *)
            nd2.setData(NO_LINE_INDEX, con.fldValueType, LOAD_CONST, con);     (*  │   ├── <index>      *)
            nd3.setData(NO_LINE_INDEX, vr1.fldValueType, LOAD_VARIABLE, vr1);  (*  │   └── value        *)
            nde.setData(NO_LINE_INDEX, typ_void, AVT_LEAVE, typ_void);         (*  └── }                *)
            exit;
        end;
        nd0 := cod.appendNode(ndr);
        nd1 := cod.appendNode(nd0);
        nd2 := cod.appendNode(nd0);
        nde := cod.appendNode(ndr);
        ndr.setData(NO_LINE_INDEX, typ_void, AVT_ENTER);                   (*  {                    *)
        nd0.setData(NO_LINE_INDEX, typ_void, ndi, mmw);                    (*  ├── invoke <method>  *)
        nd1.setData(NO_LINE_INDEX, vr0.fldValueType, LOAD_VARIABLE, vr0);  (*  │   ├── this         *)
        nd2.setData(NO_LINE_INDEX, vr1.fldValueType, LOAD_VARIABLE, vr1);  (*  │   └── value        *)
        nde.setData(NO_LINE_INDEX, typ_void, AVT_LEAVE, typ_void);         (*  └── }                *)
    end;

    procedure AVTProperty.createStoredSynthetic();
    var
        ndi: int;
        mms: _Object;
        cod: AVTCode;
        ndr: AVTNode;
        nd0: AVTNode;
        nd1: AVTNode;
        nd2: AVTNode;
        nd3: AVTNode;
        nde: AVTNode;
        syn: AVTMethod;
        pck: AVTPackage;
        con: AVTConstant;
        vr0: AVTVariable;
        tpp: AVTTypeStructured;
        typ_boolean: AVTType;
        typ_void: AVTType;
    begin
        syn := fldStoredSynthetic;
        if syn <> nil then exit;
        tpp := fldParentType;
        pck := tpp.fldPackage.fldParentProgramme.fldSystemPackage;
        typ_boolean := pck.getType(AVTTypePrimitive.getName(AVT_BOOLEAN));
        syn := AVTMethod.create(tpp, fldFlags and $1f or FLAG_SYNTHETIC, typ_boolean, fldSimpleName + '.stored', nil);
        syn.fldLinkedProperty := self;
        syn.findOverriddenMembers();
        fldStoredSynthetic := syn;
        cod := syn.fldCode;
        if cod = nil then exit;
        typ_void := pck.getType(AVTTypePrimitive.getName(AVT_VOID));
        ndr := cod.fldRoot;
        mms := fldStoredMember;
        if mms is AVTConstant then begin
            con := AVTConstant.create();
            con.assign(AVTConstant(mms));
            nd0 := cod.appendNode(ndr);
            nd1 := cod.appendNode(nd0);
            nde := cod.appendNode(ndr);
            ndr.setData(NO_LINE_INDEX, typ_void, AVT_ENTER);                   (*  {                   *)
            nd0.setData(NO_LINE_INDEX, typ_void, AVT_RETURN);                  (*  ├── return          *)
            nd1.setData(NO_LINE_INDEX, con.fldValueType, LOAD_CONST, con);     (*  │   └── <constant>  *)
            nde.setData(NO_LINE_INDEX, typ_void, AVT_LEAVE, typ_boolean);      (*  └── }               *)
            exit;
        end;
        vr0 := syn.fldArgumentThis;
        if mms is AVTField then begin
            nd0 := cod.appendNode(ndr);
            nd1 := cod.appendNode(nd0);
            nd2 := cod.appendNode(nd1);
            nde := cod.appendNode(ndr);
            ndr.setData(NO_LINE_INDEX, typ_void, AVT_ENTER);                          (*  {                 *)
            nd0.setData(NO_LINE_INDEX, typ_void, AVT_RETURN);                         (*  ├── return        *)
            nd1.setData(NO_LINE_INDEX, AVTField(mms).fldValueType, GET_FIELD, mms);   (*  │   └── .<field>  *)
            nd2.setData(NO_LINE_INDEX, vr0.fldValueType, LOAD_VARIABLE, vr0);         (*  │       └── this  *)
            nde.setData(NO_LINE_INDEX, typ_void, AVT_LEAVE, typ_boolean);             (*  └── }             *)
            exit;
        end;
        if not(mms is AVTMethod) then exit;
        if AVTItem(mms).getVisibility() = AVT_PRIVATE then begin
            ndi := INVOKE_SPECIAL;
        end else
        if AVTMember(mms).fldParentType.isService() then begin
            ndi := INVOKE_SERVICE;
        end else begin
            ndi := INVOKE_VIRTUAL;
        end;
        if fldHasIndex then begin
            con := AVTConstant.create(pck.getType(AVTTypePrimitive.getName(AVT_INT)));
            con.value.asInt := fldIndex;
            nd0 := cod.appendNode(ndr);
            nd1 := cod.appendNode(nd0);
            nd2 := cod.appendNode(nd1);
            nd3 := cod.appendNode(nd1);
            nde := cod.appendNode(ndr);
            ndr.setData(NO_LINE_INDEX, typ_void, AVT_ENTER);                     (*  {                        *)
            nd0.setData(NO_LINE_INDEX, typ_void, AVT_RETURN);                    (*  ├── return               *)
            nd1.setData(NO_LINE_INDEX, AVTMethod(mms).fldReturnType, ndi, mms);  (*  │   └── invoke <method>  *)
            nd2.setData(NO_LINE_INDEX, vr0.fldValueType, LOAD_VARIABLE, vr0);    (*  │       ├── this         *)
            nd3.setData(NO_LINE_INDEX, con.fldValueType, LOAD_CONST, con);       (*  │       └── <index>      *)
            nde.setData(NO_LINE_INDEX, typ_void, AVT_LEAVE, typ_boolean);        (*  └── }                    *)
            exit;
        end;
        nd0 := cod.appendNode(ndr);
        nd1 := cod.appendNode(nd0);
        nd2 := cod.appendNode(nd1);
        nde := cod.appendNode(ndr);
        ndr.setData(NO_LINE_INDEX, typ_void, AVT_ENTER);                     (*  {                        *)
        nd0.setData(NO_LINE_INDEX, typ_void, AVT_RETURN);                    (*  ├── return               *)
        nd1.setData(NO_LINE_INDEX, AVTMethod(mms).fldReturnType, ndi, mms);  (*  │   └── invoke <method>  *)
        nd2.setData(NO_LINE_INDEX, vr0.fldValueType, LOAD_VARIABLE, vr0);    (*  │       └── this         *)
        nde.setData(NO_LINE_INDEX, typ_void, AVT_LEAVE, typ_boolean);        (*  └── }                    *)
    end;

    function AVTProperty.isOverriddable(member: AVTOverriddable): boolean;
    begin
        result := (member is AVTProperty) and inherited isOverriddable(member);
    end;

    function AVTProperty.getAvtcType(): AnsiString;
    begin
        result := fldValueType.fldAvtcType;
    end;

    constructor AVTProperty.create(parentType: AVTTypeStructured; flags: int; valueType: AVTType; const simpleName: AnsiString; declarationPosition: int; const documentation: UnicodeString);
    begin
        inherited create(parentType, flags, simpleName, declarationPosition, documentation);
        self.fldValueType := valueType;
    end;

    destructor AVTProperty.destroy;
    begin
        if fldReadIsConst then fldReadMember.free();
        if fldStoredIsConst then fldStoredMember.free();
        inherited destroy;
    end;

    function AVTProperty.isTypeOverriddable(member: AVTOverriddable): boolean;
    begin
        if fldWriteMember <> nil then begin
            result := (member is AVTProperty) and (AVTProperty(member).fldValueType = fldValueType);
            exit;
        end;
        result := (member is AVTProperty) and AVTProperty(member).fldValueType.isAssignableFrom(fldValueType);
    end;
{%endregion}

{%region AVTVariable }
    function AVTVariable.getFasmFullName(): AnsiString;
    begin
        result := '.' + getFasmShortName();
    end;

    function AVTVariable.getFasmShortName(): AnsiString;
    var
        n: AnsiString;
        name: AnsiString;
    begin
        name := fldSimpleName;
        n := stringToLowerCase(name);
        if  (n = 'align') or (n = 'as') or (n = 'at') or (n = 'defined') or (n = 'dup') or (n = 'eq') or
            (n = 'eqtype') or (n = 'from') or (n = 'in') or (n = 'on') or (n = 'relativeto') or (n = 'used')
        then begin
            result := '$' + name + '$';
            exit;
        end;
        result := name;
    end;

    constructor AVTVariable.create(valueType: AVTType; const simpleName: AnsiString; source: AVTSource; declarationPosition: int);
    begin
        inherited create(nil, 0, simpleName, source, declarationPosition);
        self.fldValueType := valueType;
    end;
{%endregion}

{%region AVTConstant }
    constructor AVTConstant.create(valueType: AVTType);
    begin
        inherited create();
        self.fldValueType := valueType;
    end;

    procedure AVTConstant.assignValue(from: AVTConstant);
    begin
        if from <> nil then begin
            self.value.isNull := from.value.isNull;
            self.value.asLong8 := from.value.asLong8;
            self.value.asClass := from.value.asClass;
            self.value.asString := from.value.asString;
        end;
    end;

    procedure AVTConstant.assign(from: AVTConstant);
    begin
        if from <> nil then begin
            self.fldValueType := from.fldValueType;
            self.value.isNull := from.value.isNull;
            self.value.asLong8 := from.value.asLong8;
            self.value.asClass := from.value.asClass;
            self.value.asString := from.value.asString;
        end;
    end;

    procedure AVTConstant.clear();
    var
        i: int;
    begin
        fldValueType := nil;
        value.isNull := false;
        value.asClass := nil;
        value.asString := '';
        for i := 0 to 7 do begin
            value.asLong8[i] := 0;
        end;
    end;

    function AVTConstant.isDefaultValue(): boolean;
    label
        label0;
    var
        idx: int;
        knd: int;
        typ: AVTType;
    begin
        typ := fldValueType;
        if (typ = nil) or (typ is AVTTypeStructured) then begin
            result := value.isNull;
            exit;
        end;
        if typ is AVTTypePrimitive then begin
            knd := AVTTypePrimitive(typ).compoundBase;
            for idx := AVTTypePrimitive(typ).compoundLength - 1 downto 0 do begin
                case knd of
                AVT_BOOLEAN:
                    if value.asBoolean <> false then goto label0;
                AVT_CHAR:
                    if value.asChar <> #0000 then goto label0;
                AVT_REAL:
                    if (realExponent(value.asReal) <> 0) or (realSignificand(value.asReal) <> 0) then goto label0;
                AVT_BYTE:
                    if value.asByte8[idx] <> 0 then goto label0;
                AVT_SHORT:
                    if value.asShort8[idx] <> 0 then goto label0;
                AVT_INT, AVT_FLOAT:
                    if value.asInt8[idx] <> 0 then goto label0;
                AVT_LONG, AVT_DOUBLE:
                    if value.asLong8[idx] <> 0 then goto label0;
                end;
            end;
            result := true;
            exit;
        end;
        label0:
        result := false;
    end;
{%endregion}

{%region AVTCode }
    function AVTCode.getLength(): int;
    begin
        result := fldInstructions.size();
    end;

    function AVTCode.getInstruction(order: int): AVTNode;
    var
        vec: Vector;
    begin
        vec := fldInstructions;
        if (order < 0) or (order >= vec.size()) then begin
            raise IndexOutOfBoundsException.create('AVTCode: ' + msgIndexOutOfBounds);
        end;
        result := vec.elementAt(order).objectValue() as AVTNode;
    end;

    constructor AVTCode.create(parentMethod: AVTMethod);
    var
        vec: Vector;
        ndr: AVTNode;
    begin
        inherited create();
        vec := Vector.create();
        ndr := AVTNode.create(self, nil, -1);
        vec.append(ValueOfObject.create(ndr));
        self.fldShortCodes := short_Array1d_create(7);
        self.fldInstructions := Vector.create();
        self.fldNodes := vec;
        self.fldRoot := ndr;
        self.fldParentMethod := parentMethod;
    end;

    destructor AVTCode.destroy;
    begin
        fldInstructions.free();
        fldNodes.free();
        inherited destroy;
    end;

    procedure AVTCode.moveNode(node: AVTNode; index: int);
    var
        idx: int;
        len: int;
        ido: int;
        prc: AVTNode;
    begin
        if node = nil then begin
            raise NullPointerException.create('AVTCode.moveNode: ' + msgNullPointerArgument + 'node');
        end;
        if node.fldCode <> self then begin
            raise IllegalArgumentException.create('AVTCode.moveNode: ' + msgIllegalArgument + 'node');
        end;
        ido := node.fldIndex;
        prc := node.fldParent;
        len := prc.getLength();
        if index > len then index := len;
        if index < 0 then index := 0;
        if index > ido then begin
            prc.deleteChild(ido);
            prc.insertChild(index - 1, node);
            for idx := ido to index - 1 do begin
                prc.getChild(idx).fldIndex := idx;
            end;
        end else
        if index < ido then begin
            prc.deleteChild(ido);
            prc.insertChild(index, node);
            for idx := index to ido do begin
                prc.getChild(idx).fldIndex := idx;
            end;
        end;
    end;

    procedure AVTCode.moveNode(node, parent: AVTNode; index: int);
    var
        idx: int;
        len: int;
        ido: int;
        pro: AVTNode;
    begin
        if node = nil then begin
            raise NullPointerException.create('AVTCode.moveNode: ' + msgNullPointerArgument + 'node');
        end;
        if node.fldCode <> self then begin
            raise IllegalArgumentException.create('AVTCode.moveNode: ' + msgIllegalArgument + 'node');
        end;
        if parent = nil then parent := fldRoot;
        if (parent.fldCode <> self) or parent.isParent(node) then begin
            raise IllegalArgumentException.create('AVTCode.moveNode: ' + msgIllegalArgument + 'parent');
        end;
        ido := node.fldIndex;
        pro := node.fldParent;
        len := parent.getLength();
        if index > len then index := len;
        if index < 0 then index := 0;
        if parent <> pro then begin
            pro.deleteChild(ido);
            parent.insertChild(index, node);
            for idx := ido to pro.getLength() - 1 do begin
                pro.getChild(idx).fldIndex := idx;
            end;
            for idx := index to len do begin
                parent.getChild(idx).fldIndex := idx;
            end;
            node.fldParent := parent;
        end else
        if index > ido then begin
            pro.deleteChild(ido);
            pro.insertChild(index - 1, node);
            for idx := ido to index - 1 do begin
                pro.getChild(idx).fldIndex := idx;
            end;
        end else
        if index < ido then begin
            pro.deleteChild(ido);
            pro.insertChild(index, node);
            for idx := index to ido do begin
                pro.getChild(idx).fldIndex := idx;
            end;
        end;
    end;

    procedure AVTCode.replaceNode(oldNode, newNode: AVTNode);
    var
        val: int;
    begin
        with nodes() do while hasMoreElements() do with nextElement().objectValue() as AVTNode do begin
            if jumpDefault = oldNode then begin
                jumpDefault := newNode;
            end;
            with jumpCaseValues() do while hasMoreElements() do begin
                val := nextElement().intValue();
                if jumpCaseGetNode(val) = oldNode then begin
                    jumpCaseSetNode(val, newNode);
                end;
            end;
        end;
    end;

    procedure AVTCode.assignInstructionOrder(node: AVTNode; order: int);
    var
        idx: int;
        len: int;
        vec: Vector;
    begin
        if node = nil then node := fldRoot;
        if (node.fldCode <> self) or (node.fldOrder >= 0) then begin
            raise IllegalArgumentException.create('AVTCode.assignInstructionOrder: ' + msgIllegalArgument + 'node');
        end;
        vec := fldInstructions;
        len := vec.size();
        if order > len then order := len;
        if order < 0 then order := 0;
        vec.insert(order, ValueOfObject.create(node, false));
        for idx := order to len do begin
            (vec.elementAt(idx).objectValue() as AVTNode).fldOrder := idx;
        end;
    end;

    procedure AVTCode.clearInstructionOrder(node: AVTNode);
    var
        idx: int;
        ord: int;
        len: int;
        vec: Vector;
    begin
        if node = nil then node := fldRoot;
        if node.fldCode <> self then begin
            raise IllegalArgumentException.create('AVTCode.clearInstructionOrder: ' + msgIllegalArgument + 'node');
        end;
        ord := node.fldOrder;
        if ord < 0 then exit;
        vec := fldInstructions;
        len := vec.size() - 1;
        node.fldOrder := -1;
        vec.delete(ord);
        for idx := ord to len - 1 do begin
            (vec.elementAt(idx).objectValue() as AVTNode).fldOrder := idx;
        end;
    end;

    procedure AVTCode.writeShortCode();
    var
        idx: int;
        vec: Vector;
    begin
        vec := fldInstructions;
        for idx := 0 to vec.size() - 1 do begin
            write((vec.elementAt(idx).objectValue() as AVTNode).fldShortCode);
        end;
    end;

    procedure AVTCode.write(shortCode: int);
    var
        cap: int;
        cpn: int;
        pos: int;
        buf: short_Array1d;
        bfn: short_Array1d;
    begin
        buf := fldShortCodes;
        cap := system.length(buf);
        pos := fldShortCodesLength;
        if pos = INT_MAX_VALUE then begin
            raise IOException.create('AVTCode.write: ' + msgArrayFull);
        end;
        if pos = cap then begin
            cpn := int(longMin((long(cap) shl 1) + 1, INT_MAX_VALUE));
            bfn := short_Array1d_create(cpn);
            arraycopyPrimitives(buf, 0, bfn, 0, pos);
            fldShortCodes := bfn;
            buf := bfn;
        end;
        fldShortCodesLength := pos + 1;
        buf[pos] := short(shortCode);
    end;

    procedure AVTCode.write(const src: short_Array1d);
    begin
        write(src, 0, system.length(src));
    end;

    procedure AVTCode.write(const src: short_Array1d; offset, length: int);
    var
        cap: int;
        cpn: int;
        pos: int;
        psn: int;
        buf: short_Array1d;
        bfn: short_Array1d;
    begin
        arrayCheckBounds('AVTCode.write', system.length(src), offset, length);
        if length <= 0 then exit;
        buf := fldShortCodes;
        cap := system.length(buf);
        pos := fldShortCodesLength;
        psn := pos + length;
        if psn < 0 then begin
            raise IOException.create('AVTCode.write: ' + msgArrayFull);
        end;
        if psn > cap then begin
            cpn := int(longMin((long(cap) shl 1) + 1, INT_MAX_VALUE));
            if cpn < psn then cpn := int(longMin(long(psn) + 7, INT_MAX_VALUE));
            bfn := short_Array1d_create(cpn);
            arraycopyPrimitives(buf, 0, bfn, 0, pos);
            fldShortCodes := bfn;
            buf := bfn;
        end;
        fldShortCodesLength := psn;
        arraycopyPrimitives(src, offset, buf, pos, length);
    end;

    procedure AVTCode.saveToDataOutputStream(stream: DataOutput);
    var
        idx: int;
        buf: short_Array1d;
    begin
        buf := fldShortCodes;
        for idx := 0 to fldShortCodesLength - 1 do begin
            stream.writeShort(buf[idx]);
        end;
    end;

    procedure AVTCode.saveToOutputStream(stream: Output);
    begin
        saveToDataOutputStream(DataOutputStream.create(stream));
    end;

    procedure AVTCode.clear();
    begin
        fldShortCodesLength := 0;
        fldShortCodes := short_Array1d_create(7);
    end;

    function AVTCode.isEmpty(): boolean;
    begin
        result := fldShortCodesLength <= 0;
    end;

    function AVTCode.isHasJumpsTo(node: AVTNode): boolean;
    begin
        with nodes() do while hasMoreElements() do if (nextElement().objectValue() as AVTNode).isJumpTo(node) then begin
            result := true;
            exit;
        end;
        result := false;
    end;

    function AVTCode.nodes(): Enumeration;
    begin
        result := fldNodes.elements();
    end;

    function AVTCode.instructions(): Enumeration;
    begin
        result := fldInstructions.elements();
    end;

    function AVTCode.removeNode(node: AVTNode): boolean;
    var
        idx: int;
        ndp: AVTNode;
    begin
        if node = nil then begin
            raise NullPointerException.create('AVTCode.deleteNode: ' + msgNullPointerArgument + 'node');
        end;
        ndp := node.fldParent;
        if (node.fldCode <> self) or (ndp = nil) then begin
            raise IllegalArgumentException.create('AVTCode.deleteNode: ' + msgIllegalArgument + 'node');
        end;
        if node.getLength() > 0 then begin
            result := false;
            exit;
        end;
        clearInstructionOrder(node);
        idx := node.fldIndex;
        ndp.deleteChild(idx);
        fldNodes.remove(ValueOfObject.create(node, false));
        for idx := idx to ndp.getLength() - 1 do begin
            ndp.getChild(idx).fldIndex := idx;
        end;
        result := true;
    end;

    function AVTCode.appendNode(parent: AVTNode): AVTNode;
    var
        idx: int;
        ndn: AVTNode;
    begin
        if parent = nil then parent := fldRoot;
        if parent.fldCode <> self then begin
            raise IllegalArgumentException.create('AVTCode.appendNode: ' + msgIllegalArgument + 'parent');
        end;
        idx := parent.getLength();
        ndn := AVTNode.create(self, parent, idx);
        fldNodes.append(ValueOfObject.create(ndn));
        parent.insertChild(idx, ndn);
        result := ndn;
    end;

    function AVTCode.appendNode(parent: AVTNode; lineIndex: int; dataType: AVTType; instruction: int; operand1, operand2: _Object): AVTNode;
    var
        ndn: AVTNode;
    begin
        ndn := appendNode(parent);
        ndn.setData(lineIndex, dataType, instruction, operand1, operand2);
        result := ndn;
    end;

    function AVTCode.insertNode(parent: AVTNode; index: int): AVTNode;
    var
        idx: int;
        len: int;
        ndn: AVTNode;
    begin
        if parent = nil then parent := fldRoot;
        if parent.fldCode <> self then begin
            raise IllegalArgumentException.create('AVTCode.insertNode: ' + msgIllegalArgument + 'parent');
        end;
        len := parent.getLength();
        if index > len then index := len;
        if index < 0 then index := 0;
        ndn := AVTNode.create(self, parent, index);
        fldNodes.append(ValueOfObject.create(ndn));
        parent.insertChild(index, ndn);
        for idx := index + 1 to len do begin
            parent.getChild(idx).fldIndex := idx;
        end;
        result := ndn;
    end;

    function AVTCode.insertNode(parent: AVTNode; index: int; lineIndex: int; dataType: AVTType; instruction: int; operand1, operand2: _Object): AVTNode;
    var
        ndn: AVTNode;
    begin
        ndn := insertNode(parent, index);
        ndn.setData(lineIndex, dataType, instruction, operand1, operand2);
        result := ndn;
    end;

    function AVTCode.minInstructionOrder(node: AVTNode): int;
    var
        orc: int;
        orl: int;
        ndc: AVTNode;
        enm: Enumeration;
    begin
        if node = nil then node := fldRoot;
        if node.fldCode <> self then begin
            raise IllegalArgumentException.create('AVTCode.childWithMinInstructionOrder: ' + msgIllegalArgument + 'node');
        end;
        orl := -1;
        enm := fldNodes.elements();
        while enm.hasMoreElements() do begin
            ndc := enm.nextElement().objectValue() as AVTNode;
            if ndc.isParent(node) then begin
                orc := ndc.fldOrder;
                if (orc >= 0) and ((orl < 0) or (orc < orl)) then begin
                    orl := orc;
                end;
            end;
        end;
        result := orl;
    end;

    function AVTCode.maxInstructionOrder(node: AVTNode): int;
    var
        orc: int;
        orl: int;
        ndc: AVTNode;
        enm: Enumeration;
    begin
        if node = nil then node := fldRoot;
        if node.fldCode <> self then begin
            raise IllegalArgumentException.create('AVTCode.childWithMaxInstructionOrder: ' + msgIllegalArgument + 'node');
        end;
        orl := -1;
        enm := fldNodes.elements();
        while enm.hasMoreElements() do begin
            ndc := enm.nextElement().objectValue() as AVTNode;
            if ndc.isParent(node) then begin
                orc := ndc.fldOrder;
                if orc > orl then begin
                    orl := orc;
                end;
            end;
        end;
        result := orl;
    end;
{%endregion}

{%region AVTNode }
    procedure AVTNode.insertChild(index: int; child: AVTNode);
    var
        vec: Vector;
    begin
        vec := fldChilds;
        if vec = nil then begin
            vec := Vector.create();
            fldChilds := vec;
        end;
        vec.insert(index, ValueOfObject.create(child, false));
    end;

    procedure AVTNode.deleteChild(index: int);
    var
        vec: Vector;
    begin
        vec := fldChilds;
        if vec <> nil then vec.delete(index);
    end;

    procedure AVTNode.setInstruction(value: int);
    begin
        self.fldInstruction := value;
        self.fldOp1IsOwned := isOp1IsOwned();
        self.fldOp2IsOwned := isOp2IsOwned();
    end;

    procedure AVTNode.setOperand1(value: _Object);
    begin
        self.fldOperand1 := value;
        self.fldOp1IsOwned := isOp1IsOwned();
    end;

    procedure AVTNode.setOperand2(value: _Object);
    begin
        self.fldOperand2 := value;
        self.fldOp2IsOwned := isOp2IsOwned();
    end;

    function AVTNode.isOp1IsOwned(): boolean;
    var
        ins: int;
        asc: _Object;
    begin
        asc := fldOperand1;
        ins := fldInstruction;
        result := (asc is AVTConstant) or ((ins = DECLARE_VARIABLE) or (ins = AVT_CATCH)) and (asc is AVTVariable);
    end;

    function AVTNode.isOp2IsOwned(): boolean;
    begin
        result := fldOperand2 is AVTConstant;
    end;

    function AVTNode.getLength(): int;
    var
        vec: Vector;
    begin
        vec := fldChilds;
        if vec = nil then begin
            result := 0;
            exit;
        end;
        result := vec.size();
    end;

    function AVTNode.getChild(index: int): AVTNode;
    var
        vec: Vector;
    begin
        vec := fldChilds;
        if (vec = nil) or (index < 0) or (index >= vec.size()) then begin
            raise IndexOutOfBoundsException.create('AVTNode: ' + msgIndexOutOfBounds);
        end;
        result := vec.elementAt(index).objectValue() as AVTNode;
    end;

    constructor AVTNode.create(code: AVTCode; parent: AVTNode; index: int);
    begin
        inherited create();
        self.fldOrder := -1;
        self.fldIndex := index;
        self.fldParent := parent;
        self.fldCode := code;
        self.fldLabelNumber := -1;
        self.fldLineIndex := -1;
    end;

    destructor AVTNode.destroy;
    begin
        if fldOp1IsOwned then fldOperand1.free();
        if fldOp2IsOwned then fldOperand2.free();
        fldChilds.free();
        fldJumpCase.free();
        inherited destroy;
    end;

    procedure AVTNode.setData(lineIndex: int; dataType: AVTType; instruction: int; operand1, operand2: _Object);
    begin
        self.fldLineIndex := lineIndex;
        self.fldDataType := dataType;
        self.fldInstruction := instruction;
        self.fldOperand1 := operand1;
        self.fldOperand2 := operand2;
        self.fldOp1IsOwned := isOp1IsOwned();
        self.fldOp2IsOwned := isOp2IsOwned();
    end;

    procedure AVTNode.setBooleanJump(jumpIsFalse, jumpIsTrue: AVTNode);
    var
        tab: Hashtable;
    begin
        tab := fldJumpCase;
        if tab <> nil then begin
            tab.clear();
        end else begin
            tab := Hashtable.create();
            fldJumpCase := tab;
        end;
        tab.put(ValueOfLong.create(0), ValueOfObject.create(jumpIsFalse, false));
        fldJumpDefault := jumpIsTrue;
    end;

    procedure AVTNode.jumpCaseSetNode(caseValue: int; caseNode: AVTNode);
    var
        tab: Hashtable;
    begin
        tab := fldJumpCase;
        if caseNode <> nil then begin
            if tab = nil then begin
                tab := Hashtable.create();
                fldJumpCase := tab;
            end;
            tab.put(ValueOfLong.create(caseValue), ValueOfObject.create(caseNode, false));
        end else
        if tab <> nil then begin
            tab.remove(ValueOfLong.create(caseValue));
        end;
    end;

    function AVTNode.jumpCaseGetNode(caseValue: int): AVTNode;
    var
        tab: Hashtable;
        val: Value;
    begin
        tab := fldJumpCase;
        if tab = nil then begin
            result := nil;
            exit;
        end;
        val := tab.get(ValueOfLong.create(caseValue));
        if val = nil then begin
            result := nil;
            exit;
        end;
        result := val.objectValue() as AVTNode;
    end;

    function AVTNode.jumpCaseValues(): Enumeration;
    var
        tab: Hashtable;
    begin
        tab := fldJumpCase;
        if tab = nil then begin
            result := EmptyEnumerator.create();
            exit;
        end;
        result := tab.keys();
    end;

    function AVTNode.childs(): Enumeration;
    var
        vec: Vector;
    begin
        vec := fldChilds;
        if vec = nil then begin
            result := EmptyEnumerator.create();
            exit;
        end;
        result := vec.elements();
    end;

    function AVTNode.firstChild(): AVTNode;
    var
        vec: Vector;
    begin
        vec := fldChilds;
        if (vec = nil) or (vec.size() <= 0) then begin
            raise IndexOutOfBoundsException.create('AVTNode: ' + msgIndexOutOfBounds);
        end;
        result := vec.elementAt(0).objectValue() as AVTNode;
    end;

    function AVTNode.lastChild(): AVTNode;
    var
        idx: int;
        vec: Vector;
    begin
        vec := fldChilds;
        if vec = nil then begin
            raise IndexOutOfBoundsException.create('AVTNode: ' + msgIndexOutOfBounds);
        end;
        idx := vec.size() - 1;
        if idx < 0 then begin
            raise IndexOutOfBoundsException.create('AVTNode: ' + msgIndexOutOfBounds);
        end;
        result := vec.elementAt(idx).objectValue() as AVTNode;
    end;

    function AVTNode.isLoadNull(): boolean;
    var
        typ: AVTType;
    begin
        if fldInstruction = LOAD_CONST then with fldOperand1 as AVTConstant, value do begin
            typ := valueType;
            result := ((typ = nil) or (typ is AVTTypeStructured)) and isNull;
            exit;
        end;
        result := false;
        exit;
    end;

    function AVTNode.isWithVariable(): boolean;
    var
        op1: _Object;
    begin
        op1 := fldOperand1;
        result := (op1 is AVTVariable) and stringStartsWith('with.', AVTVariable(op1).fldSimpleName);
    end;

    function AVTNode.isParent(node: AVTNode): boolean;
    var
        ndc: AVTNode;
    begin
        ndc := self;
        repeat
            if ndc = node then begin
                result := true;
                exit;
            end;
            ndc := ndc.fldParent;
        until ndc = nil;
        result := false;
    end;

    function AVTNode.isJumpTo(node: AVTNode): boolean;
    var
        jcs: Hashtable;
    begin
        if fldJumpDefault = node then begin
            result := true;
            exit;
        end;
        jcs := fldJumpCase;
        if jcs <> nil then with jcs.elements() do while hasMoreElements() do if nextElement().objectValue() = node then begin
            result := true;
            exit;
        end;
        result := false;
    end;
{%endregion}

{%region AVTCompilerException }
    constructor AVTCompilerException.create(const message: AnsiString; const sourceFileName: UnicodeString; lineIndex, charIndex: int);
    begin
        inherited create(message);
        self.fldLineIndex := lineIndex;
        self.fldCharIndex := charIndex;
        self.fldSourceFileName := sourceFileName;
    end;

    constructor AVTCompilerException.create(const message: AnsiString; source: AVTSource; position: int);
    var
        lxi: int_Array1d;
    begin
        inherited create(message);
        if source <> nil then begin
            self.fldSourceFileName := source.fldFileName;
            if (position >= 0) and (position < source.fldLexemesCount) then begin
                lxi := source.getLexemeInfo(position);
                self.fldLineIndex := lxi[LNFO_LINE];
                self.fldCharIndex := lxi[LNFO_CHAR];
                exit;
            end;
        end;
        self.fldLineIndex := -1;
        self.fldCharIndex := -1;
    end;
{%endregion}

finalization
    AVTTypeInvalid.instance.free();

end.