ru.malik.elaborarer.avt.compiler.pas

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

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

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

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

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

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

unit ru.malik.elaborarer.avt.compiler;

{$MODE DELPHI}

interface

uses
    charset,
    cp866,
    pascalx.lang,
    pascalx.io,
    pascalx.io.vfs,
    pascalx.osapi,
    pascalx.utils,
    ru.malik.elaborarer.avt.programme,
    ru.malik.elaborarer.avt.operation,
    ru.malik.elaborarer.avt.lexer,
    ru.malik.elaborarer.avt.table,
    ru.malik.elaborarer.avt.tree,
    ru.malik.elaborarer.avt.generator;

{$ASMMODE INTEL,CALLING REGISTER,TYPEINFO ON}

{%region pulic }
type
    AVTLibrarySource = class;
    AVTCompiler = class;

    AVTLibrarySource = class(AVTSource)
    private
        fldDirectory: UnicodeString;
    public
        constructor create(parentProgramme: AVTProgramme; const directory, fileName: UnicodeString);
        procedure realize(); overload;
    end;

    AVTCompiler = class(_Object)
    private
        class function asConsoleString(const str: AnsiString): AnsiString; static;
        class function toConsoleString(const str: AnsiString): AnsiString; static; overload;
        class function toConsoleString(const str: UnicodeString): AnsiString; static; overload;
        class function makeFullName(const path, workingDirectory: UnicodeString): UnicodeString; static;
    private
        fldWorkingDirectory: UnicodeString;
        fldProjectDirectory: UnicodeString;
        fldLibrariesDirectory: UnicodeString;
        fldLibraries: UnicodeString_Array1d;
        fldProgramme: AVTProgramme;
        procedure readSourcesFrom(const directory, path: UnicodeString);
        procedure realizeSources();
        procedure lexicalAnalyzer();
        procedure loadLibraries();
        procedure printTypeList();
        procedure printType(typ: AVTType);
        procedure printTree(code: AVTCode; ordered: boolean);
        procedure printNode(margin: int; node: AVTNode);
        function operandToString(asc: _Object): AnsiString;
        function buildProgramme(): UnicodeString;
    public
        constructor create();
        destructor destroy; override;
        procedure run(const args: UnicodeString_Array1d);
    end;
{%endregion}

implementation

{%region AVTLibrarySource }
    constructor AVTLibrarySource.create(parentProgramme: AVTProgramme; const directory, fileName: UnicodeString);
    begin
        inherited create(parentProgramme, fileName);
        self.fldDirectory := directory;
    end;

    procedure AVTLibrarySource.realize();
    begin
        realize(LocalFileSystem.getInstance(), fldDirectory);
    end;
{%endregion}

{%region AVTCompiler }
    class function AVTCompiler.asConsoleString(const str: AnsiString): AnsiString;
    var
        nst: RawByteString;
    begin
        nst := stringCopy(str);
        setCodePage(nst, 866, false);
        result := nst;
    end;

    class function AVTCompiler.toConsoleString(const str: AnsiString): AnsiString;
    begin
        result := toConsoleString(stringToUTF16(str));
    end;

    class function AVTCompiler.toConsoleString(const str: UnicodeString): AnsiString;
    var
        idx: int;
        len: int;
        buf: char_Array1d;
        enc: PUnicodeMap;
    begin
        len := length(str);
        buf := char_Array1d_create(len);
        enc := getMap(866);
        for idx := 0 to len - 1 do begin
            buf[idx] := getASCII(TUnicodeChar(str[idx + 1]), enc)[1];
        end;
        result := AnsiString_create(buf, 0, len);
    end;

    class function AVTCompiler.makeFullName(const path, workingDirectory: UnicodeString): UnicodeString;
    var
        c: wchar;
        npt: UnicodeString;
    begin
        npt := stringReplace(path, DIRECTORY_SEPARATOR, '/');
        if stringStartsWith(UnicodeString('/'), npt) then npt := stringCopy(npt, 2);
        if length(npt) <= 0 then begin
            result := workingDirectory;
            exit;
        end;
        if not stringEndsWith(UnicodeString('/'), npt) then npt := npt + '/';
        if length(npt) < 3 then begin
            result := workingDirectory + npt;
            exit;
        end;
        c := npt[1];
        if ((c >= 'A') and (c <= 'Z') or (c >= 'a') and (c <= 'z')) and (npt[2] = ':') and (npt[3] = '/') then begin
            result := '/' + npt;
            exit;
        end;
        result := workingDirectory + npt;
    end;

    procedure AVTCompiler.readSourcesFrom(const directory, path: UnicodeString);
    var
        e: FileEnumeration;
        app: AVTProgramme;
        nam: UnicodeString;
    begin
        app := fldProgramme;
        e := LocalFileSystem.getInstance().findFirst(directory + path);
        if e = nil then begin
            raise AVTGlobalException.create('"' + stringToUTF8(directory + path) + '" does not exists or is not readable');
        end;
        try
            repeat
                if e.isDirectory() then begin
                    readSourcesFrom(directory, path + e.getName() + '/');
                    continue;
                end;
                nam := e.getName();
                if stringEndsWith(UnicodeString('.avt'), nam) then begin
                    AVTLibrarySource.create(app, directory, path + nam);
                end;
            until not e.findNext();
        finally
            e.close();
        end;
    end;

    procedure AVTCompiler.realizeSources();
    begin
        with fldProgramme.sources() do while hasMoreElements() do begin
            (nextElement().objectValue() as AVTLibrarySource).realize();
        end;
    end;

    procedure AVTCompiler.lexicalAnalyzer();
    begin
        with AVTLexer.create() do begin
            try
                with fldProgramme.sources() do while hasMoreElements() do begin
                    split(nextElement().objectValue() as AVTSource, true);
                end;
            finally
                free();
            end;
        end;
    end;

    procedure AVTCompiler.loadLibraries();
    {var
        i: int;
        item: byte2;
        storage: AVTByte2Storage;}
    begin
        {item[0] := 0;
        item[1] := 0;
        storage := AVTByte2Storage.create();
        try
            for i := 0 to 9 do begin
                storage.indexAcquire(item);
                inc(item[0]);
            end;
            for i := 0 to storage.length - 1 do begin
                item := storage[i];
                writeln(intToString(item[0]) + ', ' + intToString(item[1]));
            end;
        finally
            storage.free();
        end;}
    end;

    procedure AVTCompiler.printTypeList();
    var
        app: AVTProgramme;
        typ: AVTType;
    begin
        app := fldProgramme;
        with app.types() do while hasMoreElements() do begin
            printType(nextElement().objectValue() as AVTType);
        end;
        with app.systemPackage.types() do while hasMoreElements() do begin
            typ := nextElement().objectValue() as AVTType;
            if typ is AVTTypePrimitive then printType(typ);
        end;
        with app.arrays() do while hasMoreElements() do begin
            printType(nextElement().objectValue() as AVTType);
        end;
    end;

    procedure AVTCompiler.printType(typ: AVTType);
    var
        idx: int;
        cod: AVTCode;
        mem: AVTItem;
        ovr: AVTOverriddable;
        ext: AVTTypeStructured;
        str: AnsiString;
    begin
        str := typ.fullName;
        if typ is AVTTypeStructured then with AVTTypeStructured(typ) do begin
            ext := extends();
            if ext <> nil then begin
                str := str + '(' + ext.fullName;
                with implements() do while hasMoreElements() do begin
                    ext := nextElement().objectValue() as AVTTypeStructured;
                    str := str + ', ' + ext.fullName;
                end;
                str := str + ')';
            end;
            writeln(asConsoleString(toConsoleString(str)));
            str := '    fasm: ' + fasmFullName;
            writeln(asConsoleString(toConsoleString(str)));
            with members() do while hasMoreElements() do begin
                mem := nextElement().objectValue() as AVTItem;
                str := '    ' + mem.fullName + ' : ';
                if mem is AVTField then with AVTField(mem) do begin
                    str := str + valueType.fullName;
                end else
                if mem is AVTProperty then with AVTProperty(mem) do begin
                    str := str + valueType.fullName + ' { ';
                    if readSynthetic = nil then begin
                        str := str + 'write';
                    end else
                    if writeSynthetic = nil then begin
                        str := str + 'read';
                    end else begin
                        str := str + 'read, write';
                    end;
                    str := str + ' }';
                end else
                if mem is AVTMethod then with AVTMethod(mem) do begin
                    str := str + returnType.fullName;
                    str := str + (LINE_ENDING + '        fasm full  : ') + fasmFullName;
                    str := str + (LINE_ENDING + '        fasm short : ') + fasmShortName;
                    idx := virtualIndex;
                    if idx >= 0 then begin
                        str := str + (LINE_ENDING + '        virt. index: ') + intToString(idx);
                    end;
                    idx := serviceIndex;
                    if idx >= 0 then begin
                        str := str + (LINE_ENDING + '        serv. index: ') + intToString(idx);
                    end;
                end;
                writeln(asConsoleString(toConsoleString(str)));
                if mem is AVTOverriddable then begin
                    with AVTOverriddable(mem).overriddenMembers() do while hasMoreElements() do begin
                        ovr := nextElement().objectValue() as AVTOverriddable;
                        writeln(asConsoleString(toConsoleString('        overrides ' + ovr.fullName)));
                    end;
                end;
                if mem is AVTMethod then begin
                    cod := AVTMethod(mem).code;
                    if cod <> nil then printTree(cod, false);
                end;
            end;
        end else with typ do begin
            writeln(asConsoleString(toConsoleString(str)));
            str := '    fasm: ' + fasmFullName;
            writeln(asConsoleString(toConsoleString(str)));
        end;
    end;

    procedure AVTCompiler.printTree(code: AVTCode; ordered: boolean);
    var
        margin: int;
        index: int;
        oldLineIndex: int;
        newLineIndex: int;
        child: AVTNode;
        node: AVTNode;
        source: AVTSource;
    begin
        if ordered then begin
            oldLineIndex := -1;
            source := code.parentMethod.source;
            with code.instructions() do while hasMoreElements() do begin
                node := nextElement().objectValue() as AVTNode;
                newLineIndex := node.lineIndex;
                if (newLineIndex >= 0) and (newLineIndex <> oldLineIndex) then begin
                    writeln(asConsoleString(toConsoleString('        ' + stringTrim(stringToUTF8(source[newLineIndex])))));
                    oldLineIndex := newLineIndex;
                end;
                printNode(6, node);
            end;
            exit;
        end;
        margin := 6;
        index := 0;
        node := code.root;
        printNode(margin, node);
        if node.length <= 0 then exit;
        inc(margin);
        repeat
            child := node[index];
            printNode(margin, child);
            if child.length > 0 then begin
                node := child;
                index := 0;
                inc(margin);
                continue;
            end;
            inc(index);
            while index >= node.length do begin
                index := node.index + 1;
                node := node.parent;
                dec(margin);
                if node = nil then exit;
            end;
        until false;
    end;

    procedure AVTCompiler.printNode(margin: int; node: AVTNode);
    var
        i: int;
        str: AnsiString;
        ins: AnsiString;
        opr: _Object;
        jnd: AVTNode;
    begin
        case node.instruction of
        AVT_CLASS:             ins := 'class';                  (* ---- null class(AVTTypeStructured)                                                                                   *)
        AVT_INSTANCEOF:        ins := 'instanceof';             (*      boolean instanceof(AVTTypeStructured)                                                                           *)
        AVT_WITH:              ins := 'with';                   (* xxxx void with()                                                                                                     *)
        AVT_IF:                ins := 'if';                     (* xxxx void if()                                                                                                       *)
        AVT_SWITCH:            ins := 'switch';                 (*      void switch()                                                                                                   *)
        AVT_CASE:              ins := 'case';                   (*      void case(AVTConstant)                                                                                          *)
        AVT_DEFAULT:           ins := 'default';                (*      void default()                                                                                                  *)
        AVT_LABEL:             ins := 'label';                  (* xxxx void label(AVTConstant{value.asString <> ''})                                                                   *)
        AVT_DO:                ins := 'do';                     (* xxxx void do()                                                                                                       *)
        AVT_FOR:               ins := 'for';                    (* xxxx void for()                                                                                                      *)
        AVT_WHILE:             ins := 'while';                  (* xxxx void while()                                                                                                    *)
        AVT_BLOCK:             ins := '{...}';                  (* xxxx void {…}()                                                                                                      *)
        AVT_BREAK:             ins := 'break';                  (* ---- null break(AVTNode{instruction in [AVT_SWITCH, AVT_LABEL, AVT_DO, AVT_FOR, AVT_WHILE]})                         *)
        AVT_CONTINUE:          ins := 'continue';               (* ---- null continue(AVTNode{instruction in [AVT_DO, AVT_FOR, AVT_WHILE]})                                             *)
        AVT_RETURN:            ins := 'return';                 (* ???? void return()                                                                                                   *)
        AVT_THROW:             ins := 'throw';                  (*      void throw()                                                                                                    *)
        AVT_TRY_BEGIN:         ins := 'tryBegin';               (*      void tryBegin()                                                                                                 *)
        AVT_TRY_END:           ins := 'tryEnd';                 (*      void tryEnd()                                                                                                   *)
        AVT_CATCH:             ins := 'catch';                  (*      void catch(AVTVariable) (аналогично storeVariable)                                                              *)
        AVT_FINALLY:           ins := 'finally';                (*      void finally()                                                                                                  *)
        AVT_FINALLY_INVOKE:    ins := 'invokeFinally';          (*      void invokeFinally(AVTNode{instruction = AVT_FINALLY})                                                          *)
        AVT_FINALLY_RETURN:    ins := 'leaveFinally';           (*      void leaveFinally()                                                                                             *)
        AVT_MONITOR_ENTER:     ins := 'enterMonitor';           (*      void enterMonitor()                                                                                             *)
        AVT_MONITOR_LEAVE:     ins := 'leaveMonitor';           (*      void leaveMonitor()                                                                                             *)
        AVT_ENTER:             ins := 'enter';                  (*      void enter()                                                                                                    *)
        AVT_LEAVE:             ins := 'leave';                  (*      void leave(AVTType)                                                                                             *)
        AVT_CLINIT_TRY_LOCK:   ins := 'tryLockClinit';          (*      boolean tryLockClinit(AVTTypeStructured)                                                                        *)
        AVT_CLINIT_UNLOCK:     ins := 'unlockClinit';           (*      void unlockClinit()                                                                                             *)
        LOAD_VARIABLE:         ins := 'loadVariable';           (*      T loadVariable(AVTVariable)                                                                                     *)
        LOAD_STATIC:           ins := 'loadStatic';             (*      T loadStatic(AVTField{isStatic() = true})                                                                       *)
        LOAD_CLASS:            ins := 'loadClass';              (* xxxx avt.lang.Class loadClass(AVTType) { НЕ ИСПОЛЬЗУЕТСЯ! ИСПОЛЬЗУЙ LOAD_CONST ВМЕСТО ЭТОЙ ИНСТРУКЦИИ. }             *)
        LOAD_CONST:            ins := 'loadConstant';           (*      T loadConstant(AVTConstant)                                                                                     *)
        GET_FIELD:             ins := 'getField';               (*      T getField(AVTField{isStatic() = false})                                                                        *)
        GET_PROPERTY:          ins := 'getProperty';            (*      T getProperty(AVTProperty)                                                                                      *)
        GET_ARRAY_ELEMENT:     ins := 'getArrayElement';        (*      T getArrayElement(AVTType/*тип элементов массива*/)                                                             *)
        GET_VECTOR_ELEMENT:    ins := 'getVectorElement';       (*      T getVectorElement(AVTTypePrimitive/*тип вектора*/)                                                             *)
        DECLARE_VARIABLE:      ins := 'declareVariable';        (*      void declareVariable(AVTVariable) (аналогично storeVariable)                                                    *)
        DUP1:                  ins := 'dup1';                   (*      void dup1()                                                                                                     *)
        DUP2:                  ins := 'dup2';                   (*      void dup2()                                                                                                     *)
        DUP1X1:                ins := 'dup1x1';                 (*      void dup1x1()                                                                                                   *)
        DUP1X2:                ins := 'dup1x2';                 (*      void dup1x2()                                                                                                   *)
        POP1:                  ins := 'pop1';                   (*      void pop1()                                                                                                     *)
        JUMP:                  ins := 'jump';                   (*      void jump()                                                                                                     *)
        INVOKE_STATIC:         ins := 'invokeStatic';           (*      void|T invokeStatic(AVTMethod{isStatic() = true})                                                               *)
        INVOKE_SPECIAL:        ins := 'invokeSpecial';          (*      void|T invokeSpecial(AVTMethod{isStatic() = false})                                                             *)
        INVOKE_VIRTUAL:        ins := 'invokeVirtual';          (*      void|T invokeVirtual(AVTMethod{isStatic() = false, visibility > AVT_PRIVATE, parentType.isClass() = true})      *)
        INVOKE_SERVICE:        ins := 'invokeService';          (*      void|T invokeService(AVTMethod{isStatic() = false, visibility > AVT_PRIVATE, parentType.isService() = true})    *)
        NEW_ARRAY_BY_LENGTH:   ins := 'newArrayByLength';       (*      T[] newArrayByLength(AVTTypeArray)                                                                              *)
        NEW_MULTI_ARRAY:       ins := 'newMultiArray';          (*      T[] newMultiArray(AVTTypeArray)                                                                                 *)
        NEW_ARRAY_BY_ELEMENTS: ins := 'newArrayByElements';     (*      T[] newArrayByElements(AVTTypeArray, AVTConstant{valueType in [byte, short, int]}/*длина массива*/)             *)
        NEW_VECTOR:            ins := 'newVector';              (*      T newVector(AVTTypePrimitive)                                                                                   *)
        NEW_CLASS:             ins := 'newClass';               (*      T newClass(AVTTypeStructured)                                                                                   *)
        NEW_STRUCT:            ins := 'newStruct';              (*      T newStruct(AVTTypeStructured)                                                                                  *)
        NEW_SERVICE:           ins := 'newService';             (*      T newService(AVTTypeStructured)                                                                                 *)
        OPER_TYPE_CAST:        ins := 'cast';                   (*      T cast(AVTType/*новый тип*/, AVTType/*старый тип*/)                                                             *)
        OPER_INCREMENT:        ins := 'operator ++';            (*      void operator ++(AVTVariable)                                                                                   *)
        OPER_DECREMENT:        ins := 'operator --';            (*      void operator --(AVTVariable)                                                                                   *)
        OPER_INC_POST:         ins := 'operator x++';           (*      T operator x++(AVTVariable)                                                                                     *)
        OPER_DEC_POST:         ins := 'operator x--';           (*      T operator x--(AVTVariable)                                                                                     *)
        OPER_INC_PRED:         ins := 'operator ++x';           (*      T operator ++x(AVTVariable)                                                                                     *)
        OPER_DEC_PRED:         ins := 'operator --x';           (*      T operator --x(AVTVariable)                                                                                     *)
        OPER_BOOL_NOT:         ins := 'operator !';             (* xxxx boolean operator !()                                                                                            *)
        OPER_BOOL_AND:         ins := 'operator &&';            (* xxxx boolean operator &&()                                                                                           *)
        OPER_BOOL_OR:          ins := 'operator ||';            (* xxxx boolean operator ||()                                                                                           *)
        OPER_BOOL_COND:        ins := 'operator ?:';            (* xxxx T operator ?:()                                                                                                 *)
        OPER_BIT_NOT:          ins := 'operator ~';             (*      T operator ~(AVTTypePrimitive)                                                                                  *)
        OPER_BIT_AND:          ins := 'operator &';             (*      T operator &(AVTTypePrimitive)                                                                                  *)
        OPER_BIT_OR:           ins := 'operator |';             (*      T operator |(AVTTypePrimitive)                                                                                  *)
        OPER_BIT_XOR:          ins := 'operator ^';             (*      T operator ^(AVTTypePrimitive)                                                                                  *)
        OPER_SCAL_PLUS:        ins := 'operator +/*unary*/';    (* xxxx T operator +/*unary*/(AVTTypePrimitive)                                                                         *)
        OPER_SCAL_MINUS:       ins := 'operator -/*unary*/';    (*      T operator -/*unary*/(AVTTypePrimitive)                                                                         *)
        OPER_SCAL_MUL:         ins := 'operator *';             (*      T operator *(AVTTypePrimitive)                                                                                  *)
        OPER_SCAL_DIV:         ins := 'operator /';             (*      T operator /(AVTTypePrimitive)                                                                                  *)
        OPER_SCAL_DIVU:        ins := 'operator //';            (*      T operator //(AVTTypePrimitive)                                                                                 *)
        OPER_SCAL_REM:         ins := 'operator %';             (*      T operator %(AVTTypePrimitive)                                                                                  *)
        OPER_SCAL_REMU:        ins := 'operator %%';            (*      T operator %%(AVTTypePrimitive)                                                                                 *)
        OPER_SCAL_ADD:         ins := 'operator +';             (*      T operator +(AVTTypePrimitive)                                                                                  *)
        OPER_SCAL_SUB:         ins := 'operator -';             (*      T operator -(AVTTypePrimitive)                                                                                  *)
        OPER_SCAL_SAR:         ins := 'operator >>';            (*      T operator >>(AVTTypePrimitive)                                                                                 *)
        OPER_SCAL_SAL:         ins := 'operator <<';            (*      T operator <<(AVTTypePrimitive)                                                                                 *)
        OPER_SCAL_SHR:         ins := 'operator >>>';           (*      T operator >>>(AVTTypePrimitive)                                                                                *)
        OPER_SCAL_G:           ins := 'operator >';             (*      boolean operator >(AVTTypePrimitive)                                                                            *)
        OPER_SCAL_GE:          ins := 'operator >=';            (*      boolean operator >=(AVTTypePrimitive)                                                                           *)
        OPER_SCAL_L:           ins := 'operator <';             (*      boolean operator <(AVTTypePrimitive)                                                                            *)
        OPER_SCAL_LE:          ins := 'operator <=';            (*      boolean operator <=(AVTTypePrimitive)                                                                           *)
        OPER_SCAL_E:           ins := 'operator ==';            (*      boolean operator ==(AVTType)                                                                                    *)
        OPER_SCAL_NE:          ins := 'operator !=';            (*      boolean operator !=(AVTType)                                                                                    *)
        OPER_VECT_PACK:        ins := 'operator @@@@';          (*      T operator @@@@(AVTTypePrimitive)                                                                               *)
        OPER_VECT_UNPCKL:      ins := 'operator ####';          (*      T operator ####(AVTTypePrimitive)                                                                               *)
        OPER_VECT_UNPCKU:      ins := 'operator ^^^^';          (*      T operator ^^^^(AVTTypePrimitive)                                                                               *)
        OPER_VECT_PLUS:        ins := 'operator ++++/*unary*/'; (* xxxx T operator ++++/*unary*/(AVTTypePrimitive)                                                                      *)
        OPER_VECT_MINUS:       ins := 'operator ----/*unary*/'; (*      T operator ----/*unary*/(AVTTypePrimitive)                                                                      *)
        OPER_VECT_MUL:         ins := 'operator ****';          (*      T operator ****(AVTTypePrimitive)                                                                               *)
        OPER_VECT_DIV:         ins := 'operator ////';          (*      T operator ////(AVTTypePrimitive)                                                                               *)
        OPER_VECT_ADD:         ins := 'operator ++++';          (*      T operator ++++(AVTTypePrimitive)                                                                               *)
        OPER_VECT_SUB:         ins := 'operator ----';          (*      T operator ----(AVTTypePrimitive)                                                                               *)
        OPER_VECT_SAR:         ins := 'operator >>>>';          (*      T operator >>>>(AVTTypePrimitive)                                                                               *)
        OPER_VECT_SAL:         ins := 'operator <<<<';          (*      T operator <<<<(AVTTypePrimitive)                                                                               *)
        OPER_VECT_SHR:         ins := 'operator >>>>>';         (*      T operator >>>>>(AVTTypePrimitive)                                                                              *)
        OPER_VECT_G:           ins := 'operator |>>|';          (*      T operator |>>|(AVTTypePrimitive)                                                                               *)
        OPER_VECT_GE:          ins := 'operator |>=|';          (*      T operator |>=|(AVTTypePrimitive)                                                                               *)
        OPER_VECT_L:           ins := 'operator |<<|';          (*      T operator |<<|(AVTTypePrimitive)                                                                               *)
        OPER_VECT_LE:          ins := 'operator |<=|';          (*      T operator |<=|(AVTTypePrimitive)                                                                               *)
        OPER_VECT_E:           ins := 'operator |==|';          (*      T operator |==|(AVTTypePrimitive)                                                                               *)
        OPER_VECT_NE:          ins := 'operator |!=|';          (*      T operator |!=|(AVTTypePrimitive)                                                                               *)
        OPER_VECT_MULS:        ins := 'operator |**|';          (*      T operator |**|(AVTTypePrimitive)                                                                               *)
        OPER_VECT_ADDS:        ins := 'operator |++|';          (*      T operator |++|(AVTTypePrimitive)                                                                               *)
        OPER_VECT_SUBS:        ins := 'operator |--|';          (*      T operator |--|(AVTTypePrimitive)                                                                               *)
        OPER_VECT_MULU:        ins := 'operator #**#';          (*      T operator #**#(AVTTypePrimitive)                                                                               *)
        OPER_VECT_ADDU:        ins := 'operator #++#';          (*      T operator #++#(AVTTypePrimitive)                                                                               *)
        OPER_VECT_SUBU:        ins := 'operator #--#';          (*      T operator #--#(AVTTypePrimitive)                                                                               *)
        STORE_VARIABLE:        ins := 'storeVariable';          (*      void|T storeVariable(AVTVariable)                                                                               *)
        STORE_STATIC:          ins := 'storeStatic';            (*      void|T storeStatic(AVTField{isStatic() = true})                                                                 *)
        SET_FIELD:             ins := 'setField';               (*      void|T setField(AVTField{isStatic() = false})                                                                   *)
        SET_PROPERTY:          ins := 'setProperty';            (*      void|T setProperty(AVTProperty)                                                                                 *)
        SET_ARRAY_ELEMENT:     ins := 'setArrayElement';        (*      void|T setArrayElement(AVTType/*тип элементов массива*/)                                                        *)
        else                   ins := '<invalid>'
        end;                                                    (* xxxx – служебный (некомпилируемый) узел *)
        str := '';                                              (* ---- – промежуточный (уничтожаемый) узел *)
        for i := margin - 1 downto 0 do begin                   (* ???? – не всегда компилируемый узел *)
            str := str + '  ';
        end;
        str := str + longToHexString(pointerToLongBits(node)) + ' ';
        i := node.lineIndex + 1;
        if i > 0 then begin
            str := str + '[' + intToString(i) + '] ';
        end;
        i := node.labelNumber;
        if i >= 0 then begin
            str := str + '.L.' + intToString(i) + ': ';
        end;
        str := str + AVTTableBuilder.itemToString(node.dataType) + ' ' + ins + '(';
        opr := node.operand1;
        if opr <> nil then begin
            str := str + operandToString(opr);
            opr := node.operand2;
            if opr <> nil then begin
                str := str + ', ' + operandToString(opr);
            end;
        end;
        str := str + ')';
        jnd := node.jumpDefault;
        if jnd <> nil then begin
            str := str + ' { default=>' + longToHexString(pointerToLongBits(jnd));
            with node.jumpCaseValues() do while hasMoreElements() do begin
                i := nextElement().intValue();
                jnd := node.jumpCaseGetNode(i);
                str := str + ', ' + intToString(i) + '=>' + longToHexString(pointerToLongBits(jnd));
            end;
            str := str + ' }';
        end;
        writeln(asConsoleString(toConsoleString(str)));
    end;

    function AVTCompiler.operandToString(asc: _Object): AnsiString;
    var
        i: int;
        l: int;
        c: wchar;
        s: AnsiString;
        v: UnicodeString;
        typ: AVTType;
    begin
        s := '<invalid>';
        if asc = nil then begin
            s := '<null>';
        end else
        if asc is AVTNode then begin
            s := longToHexString(pointerToLongBits(asc));
        end else
        if asc is AVTItem then begin
            s := AVTItem(asc).fullName;
        end else
        if asc is AVTConstant then with AVTConstant(asc).value do begin
            typ := AVTConstant(asc).valueType;
            if (typ = nil) or (typ is AVTTypeStructured) then begin
                typ := asClass;
                if isNull then begin
                    s := 'null'
                end else
                if typ <> nil then begin
                    s := typ.fullName + '.class';
                end else begin
                    s := '"';
                    v := asString;
                    for i := 1 to length(v) do begin
                        if i > 16 then begin
                            s := s + '...';
                            break;
                        end;
                        c := v[i];
                        if (c >= #$0020) and (c <= #$007e) then begin
                            s := s + char(c);
                        end else begin
                            s := s + '\u' + intToHexString((int(c) shr 12) and $0f) + intToHexString((int(c) shr 8) and $0f) + intToHexString((int(c) shr 4) and $0f) + intToHexString(int(c) and $0f);
                        end;
                    end;
                    s := s + '"';
                end;
            end else
            if typ is AVTTypePrimitive then with AVTTypePrimitive(typ) do begin
                case compoundBase of
                AVT_BOOLEAN: begin
                    if asBoolean then begin
                        s := 'true';
                    end else begin
                        s := 'false';
                    end;
                end;
                AVT_CHAR: begin
                    i := int(asChar);
                    s := '''\u' + intToHexString((i shr 12) and $0f) + intToHexString((i shr 8) and $0f) + intToHexString((i shr 4) and $0f) + intToHexString(i and $0f) + '''';
                end;
                AVT_REAL: begin
                    s := realToString(asReal);
                end;
                AVT_BYTE: begin
                    l := compoundLength;
                    if l = 1 then begin
                        s := intToString(asByte);
                    end else begin
                        s := 'new byte' + char(l + int('0')) + ' { ';
                        dec(l);
                        for i := 0 to l do begin
                            s := s + intToString(asByte8[i]);
                            if i < l then s := s + ', ';
                        end;
                        s := s + ' }';
                    end;
                end;
                AVT_SHORT: begin
                    l := compoundLength;
                    if l = 1 then begin
                        s := intToString(asShort);
                    end else begin
                        s := 'new short' + char(l + int('0')) + ' { ';
                        dec(l);
                        for i := 0 to l do begin
                            s := s + intToString(asShort8[i]);
                            if i < l then s := s + ', ';
                        end;
                        s := s + ' }';
                    end;
                end;
                AVT_INT: begin
                    l := compoundLength;
                    if l = 1 then begin
                        s := intToString(asInt);
                    end else begin
                        s := 'new int' + char(l + int('0')) + ' { ';
                        dec(l);
                        for i := 0 to l do begin
                            s := s + intToString(asInt8[i]);
                            if i < l then s := s + ', ';
                        end;
                        s := s + ' }';
                    end;
                end;
                AVT_LONG: begin
                    l := compoundLength;
                    if l = 1 then begin
                        s := longToString(asLong) + 'L';
                    end else begin
                        s := 'new long' + char(l + int('0')) + ' { ';
                        dec(l);
                        for i := 0 to l do begin
                            s := s + longToString(asLong8[i]);
                            if i < l then s := s + 'L, ';
                        end;
                        s := s + 'L }';
                    end;
                end;
                AVT_FLOAT: begin
                    l := compoundLength;
                    if l = 1 then begin
                        s := floatToString(asFloat) + 'f';
                    end else begin
                        s := 'new float' + char(l + int('0')) + ' { ';
                        dec(l);
                        for i := 0 to l do begin
                            s := s + floatToString(asFloat8[i]);
                            if i < l then s := s + 'f, ';
                        end;
                        s := s + 'f }';
                    end;
                end;
                AVT_DOUBLE: begin
                    l := compoundLength;
                    if l = 1 then begin
                        s := doubleToString(asDouble) + 'd';
                    end else begin
                        s := 'new double' + char(l + int('0')) + ' { ';
                        dec(l);
                        for i := 0 to l do begin
                            s := s + doubleToString(asDouble8[i]);
                            if i < l then s := s + 'd, ';
                        end;
                        s := s + 'd }';
                    end;
                end;
                end;
            end;
        end;
        result := s;
    end;

    function AVTCompiler.buildProgramme(): UnicodeString;
    var
        src: AVTSource;
        typ: AVTTypeStructured;
        app: AVTProgramme;
    begin
        app := fldProgramme;
        with AVTCodeGenerator.create(app) do begin
            try
                { Будущий алгоритм компиляции:
                 1. Создать пакеты из исходного кода
                 2. Создать типы из исходного кода
                 3. Создать основные типы массивов
                 4. Прочитать раздел импортов
                 5. Определить реализуемые типы для:
                     А. Типов из исходного кода
                     Б. Основных типов массивов
                 6. Проверить реализуемые типы и добавить недостающие
                 7. Отсортировать типы из исходного кода
                 8. Создать члены типов из исходного кода. (Параллельно будут созданы дополнительные типы массивов, а также определены и проверены их реализуемые типы и добавлены недостающие реализуемые типы.)
                 9. Создать члены основных типов массивов
                10. Проверить члены, добавить недостающие члены, найти перекрытые члены для:
                     А. Типов из исходного кода
                     Б. Основных типов массивов
                     В. Дополнительных типов массивов
                11. Работа с членами всех типов:
                     А. Чтение начальных значений полей
                     Б. Чтение реализации свойств
                     В. Определение смещений полей, индексов виртуальных и сервисных методов
                     Г. Построение деревьев разбора кода методов и работа с ними
                     (Параллельно будут созданы дополнительные типы массивов, а также определены и проверены их реализуемые типы и добавлены недостающие реализуемые типы.)
                12. Сохранение (запись) результата на диск

                1.
                with app.sources() do while hasMoreElements() do begin
                    src := nextElement().objectValue() as AVTSource;
                    parsePackage(src);
                end;

                2.
                with app.sources() do while hasMoreElements() do begin
                    src := nextElement().objectValue() as AVTSource;
                    parseTypes(src);
                end;

                3.
                app.createArrays();

                4, 5.
                with app.sources() do while hasMoreElements() do begin
                    src := nextElement().objectValue() as AVTSource;
                    parseImports(src);
                    parseSuperTypes(src);
                end;
                app.realizeArrays();

                6, 7.
                app.prefetchTypes();

                8.
                with app.types() do while hasMoreElements() do begin
                    typ := nextElement().objectValue() as AVTTypeStructured;
                    parseMembers(typ);
                end;

                9.
                app.prefetchArrays();

                10.
                with app.types() do while hasMoreElements() do begin
                    (nextElement().objectValue() as AVTTypeStructured).prefetchMembers();
                end;
                with app.arrays() do while hasMoreElements() do begin
                    (nextElement().objectValue() as AVTTypeStructured).prefetchMembers();
                end;

                11.
                with app.types() do while hasMoreElements() do begin
                    typ := nextElement().objectValue() as AVTTypeStructured;
                    parseFields(typ);
                    parseProperties(typ);
                end;
                with app.types() do while hasMoreElements() do begin
                    typ := nextElement().objectValue() as AVTTypeStructured;
                    parseMethods(typ);
                end;

                12.
                storeProgramme();
                }
                with app.sources() do while hasMoreElements() do begin
                    src := nextElement().objectValue() as AVTSource;
                    parsePackage(src);
                end;
                with app.sources() do while hasMoreElements() do begin
                    src := nextElement().objectValue() as AVTSource;
                    parseTypes(src);
                end;
                with app.sources() do while hasMoreElements() do begin
                    src := nextElement().objectValue() as AVTSource;
                    parseImport(src);
                    parseSuperTypes(src);
                end;
                app.prefetchTypes();
                with app.types() do while hasMoreElements() do begin
                    typ := nextElement().objectValue() as AVTTypeStructured;
                    parseMembers(typ);
                end;
                with app.types() do while hasMoreElements() do begin
                    typ := nextElement().objectValue() as AVTTypeStructured;
                    parseFields(typ);
                    typ.prefetchMembers();
                    parseProperties(typ);
                end;
                app.prefetchArrays();
                with app.types() do while hasMoreElements() do begin
                    typ := nextElement().objectValue() as AVTTypeStructured;
                    typ.prefetchIndices();
                end;
                with app.types() do while hasMoreElements() do begin
                    typ := nextElement().objectValue() as AVTTypeStructured;
                    parseMethods(typ);
                end;
                with app.arrays() do while hasMoreElements() do begin
                    typ := nextElement().objectValue() as AVTTypeStructured;
                    parseMethods(typ);
                end;
                with app.arrays() do while hasMoreElements() do begin
                    typ := nextElement().objectValue() as AVTTypeStructured;
                    typ.prefetchIndices();
                end;
                result := generate(LocalFileSystem.getInstance(), fldProjectDirectory);
            finally
                free();
            end;
        end;
    end;

    constructor AVTCompiler.create();
    begin
        inherited create();
        self.fldProgramme := AVTProgramme.create();
    end;

    destructor AVTCompiler.destroy;
    begin
        fldProgramme.free();
        inherited destroy;
    end;

    procedure AVTCompiler.run(const args: UnicodeString_Array1d);
    var
        len: int;
        time: long;
        programmeFile: AnsiString;
        consoleMessage: AnsiString;
        workingDirectory: UnicodeString;
        projectDirectory: UnicodeString;
        librariesDirectory: UnicodeString;
        libraries: UnicodeString_Array1d;
    begin
        writeln(asConsoleString('Advanced Vector Translator (object-oriented)  version ' + AVTC_VERSION));
        if not AVTProgramme.isSupportedAVX512ByCPU() then begin
            writeln(asConsoleString('Launching of this programme is allowed only on the CPUs with AVX, AVX2 and AVX-512 (F, CD, DQ, BW) supported.'));
            exit;
        end;
        if not AVTProgramme.isSupportedAVX512ByOS() then begin
            writeln(asConsoleString('Launching of this programme is allowed only in OSes with CPUs with AVX, AVX2 and AVX-512 (F, CD, DQ, BW) supported.'));
            exit;
        end;
        len := length(args);
        if len <= 1 then begin
            writeln(asConsoleString('The project directory is not specified in command line argument.' + LINE_ENDING +
                'Please specify the project directory in command line argument.' + LINE_ENDING +
                'The project directory must have the src.asm and src.avt subdirectories.'));
            exit;
        end;
        try
            time := systemGetTickCount();
            workingDirectory := stringReplace(systemGetCurrentDirectory(), DIRECTORY_SEPARATOR, '/');
            if not stringEndsWith(UnicodeString('/'), workingDirectory) then workingDirectory := workingDirectory + '/';
            if not stringStartsWith(UnicodeString('/'), workingDirectory) then workingDirectory := '/' + workingDirectory;
            projectDirectory := makeFullName(args[1], workingDirectory);
            librariesDirectory := '/' + stringReplace(args[0], DIRECTORY_SEPARATOR, '/');
            librariesDirectory := stringCopy(librariesDirectory, 1, stringLastIndexOf(UnicodeString('/'), librariesDirectory) + 1) + 'libs/';
            dec(len, 2);
            libraries := UnicodeString_Array1d_create(len);
            arraycopyUnicodeStrings(args, 2, libraries, 0, len);
            fldWorkingDirectory := workingDirectory;
            fldProjectDirectory := projectDirectory;
            fldLibrariesDirectory := librariesDirectory;
            fldLibraries := libraries;
            readSourcesFrom(projectDirectory + 'src.avt', '/');
            realizeSources();
            lexicalAnalyzer();
            loadLibraries();
            programmeFile := stringToUTF8(buildProgramme());
            time := (systemGetTickCount() - time) div 100;
            writeln(asConsoleString(longToString(time div 10) + '.' + char(int(time mod 10) + int('0')) + ' seconds, ' + stringReplace(stringCopy(programmeFile, 2), '/', '\') + ' generated.'));
            { printTypeList(); }
        except
            on e: AVTCompilerException do begin
                consoleMessage := asConsoleString
                (
                    e.message + LINE_ENDING +
                    'File: ' + toConsoleString(e.sourceFileName) + LINE_ENDING +
                    'Line: ' + intToString(e.lineIndex + 1) + LINE_ENDING +
                    'Char: ' + intToString(e.charIndex + 1) + LINE_ENDING
                );
                writeln(consoleMessage);
            end;
            on e: AVTGlobalException do begin
                consoleMessage := asConsoleString
                (
                    e.message + LINE_ENDING
                );
                writeln(consoleMessage);
            end;
            on e: Throwable do begin
                e.printStackTrace();
            end;
        end;
    end;
{%endregion}

end.