ru.malik.elaborarer.avt.tree.pas

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

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

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

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

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

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

unit ru.malik.elaborarer.avt.tree;

{$MODE DELPHI}

interface

uses
    pascalx.lang,
    pascalx.utils,
    ru.malik.elaborarer.avt.programme,
    ru.malik.elaborarer.avt.lexer,
    ru.malik.elaborarer.avt.constant,
    ru.malik.elaborarer.avt.table;

{$ASMMODE INTEL,CALLING REGISTER,TYPEINFO ON}

{%region pulic }
type
    AVTCodeBuilder = class;

    AVTCodeBuilder = class(AVTTableBuilder)
    private
        class procedure defineSubnodesJumps(parentNode: AVTNode; code: AVTCode); static; overload;
        class procedure defineSubnodesJumps(parentNode: AVTNode; code: AVTCode; jumpIsFalse, jumpIsTrue: AVTNode); static; overload;
        class function getStartSubnode(code: AVTCode; parentNode, ifEmptyNode: AVTNode): AVTNode; static;
        class function defineSubnodesOrder(parentNode: AVTNode; code: AVTCode; startFromOrder: int): int; static;
        class function isRecursiveConstructorInvokation(constructorRef: AVTInstInit): boolean; static;
        class function getCatchNode(currentNode: AVTNode; exceptionType: AVTTypeStructured): AVTNode; static;
        class function getVariable(const simpleName: AnsiString; parentNode: AVTNode; methodRef: AVTMethod): AVTVariable; static;
    private
        fldResolvedVariable: AVTVariable;
        fldTypeObjectRef: AVTTypeStructured;
        fldTypeStructRef: AVTTypeStructured;
        fldTypeThrowableRef: AVTTypeStructured;
        procedure buildCode(methodRef: AVTMethod);
        procedure needValue(currentNode: AVTNode; code: AVTCode);
        procedure discardValue(currentNode: AVTNode; code: AVTCode);
        procedure insertAfterConstructionInvoke(parentNode: AVTNode; code: AVTCode; pos, lineIndex: int);
        procedure insertClinitInvoke(parentNode: AVTNode; code: AVTCode; typeRef: AVTTypeStructured; memberRef: AVTMember; lineIndex: int);
        function insertClinitTryLockNode(rootNode: AVTNode; code: AVTCode; typeRef: AVTTypeStructured): AVTNode;
        function insertSynchronizedNode(rootNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured): AVTNode;
        function parsePostfix(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers, isUseSuper, isImplicitPeriod: boolean): int;
        function parsePrimary(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
        function parsePrefix(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
        function parseMultiplicative(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
        function parseAdditive(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
        function parseShift(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
        function parseRelational(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
        function parseEquality(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
        function parseBitAnd(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
        function parseBitXor(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
        function parseBitOr(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
        function parseBoolAnd(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
        function parseBoolOr(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
        function parseConditional(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
        function parseExpression(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean = false): int;
        function parseLocal(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; variableAllowed: boolean = true): int;
        function parseBlock(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
        function parseDo(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
        function parseIf(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
        function parseFor(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
        function parseTry(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
        function parseWith(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
        function parseBreak(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
        function parseThrow(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
        function parseWhile(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
        function parseReturn(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
        function parseSwitch(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
        function parseContinue(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
        function parseSynchronized(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
        function parseStatement(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
        function parseType(parentNode: AVTNode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): AVTType; overload;
        function tryParseType(parentNode: AVTNode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): AVTType; overload;
        function resolveName(const simpleName: AnsiString; parentNode: AVTNode; methodRef: AVTMethod; typeRef: AVTTypeStructured; pos: int): AVTItem; overload;
        function insertIncrementCode(parentNode: AVTNode; code: AVTCode; typeOperandRef: AVTTypePrimitive; isIncrement: boolean; lineIndex: int): AVTNode;
        function cast(currentNode: AVTNode; code: AVTCode; typeNewRef: AVTType): AVTNode; overload;
        function getPrimitiveTypeForIntValue(value: int): AVTTypePrimitive;
    public
        procedure parseMethods(typeRef: AVTTypeStructured);
        function getThrowableType(): AVTTypeStructured;
        function getStructType(): AVTTypeStructured;
        function getObjectType(): AVTTypeStructured;
    end;
{%endregion}

implementation

{%region AVTCodeBuilder }
    class procedure AVTCodeBuilder.defineSubnodesJumps(parentNode: AVTNode; code: AVTCode);
    var
        i: int;
        len: int;
        order: int;
        instruction: int;
        nextNode: AVTNode;
        childNode0: AVTNode;
        childNode1: AVTNode;
        childNode2: AVTNode;
        childNode3: AVTNode;
        childNode4: AVTNode;
    begin
        instruction := parentNode.instruction;
        case instruction of
        AVT_IF, OPER_BOOL_COND: begin
            len := parentNode.length;
            if len > 2 then begin
                childNode2 := parentNode[2];
                if childNode2.order < 0 then exit;
            end else begin
                childNode2 := nil;
            end;
            nextNode := code[code.maxInstructionOrder(parentNode) + 1];
            if len <= 2 then begin
                defineSubnodesJumps(parentNode[0], code, nextNode, getStartSubnode(code, parentNode[1], nextNode));
            end else begin
                defineSubnodesJumps(parentNode[0], code, getStartSubnode(code, parentNode[3], nextNode), getStartSubnode(code, parentNode[1], nextNode));
                childNode2.jumpDefault := nextNode;
            end;
        end;
        AVT_DO: begin
            childNode1 := parentNode[1];
            nextNode := code[code.maxInstructionOrder(parentNode) + 1];
            defineSubnodesJumps(childNode1, code, nextNode, getStartSubnode(code, parentNode[0], code[code.minInstructionOrder(childNode1)]));
        end;
        AVT_FOR: begin
            len := parentNode.length;
            childNode0 := parentNode[len - 4];
            childNode1 := parentNode[len - 3];
            childNode2 := parentNode[len - 2];
            childNode3 := parentNode[len - 1];
            nextNode := code[code.maxInstructionOrder(parentNode) + 1];
            childNode0.jumpDefault := code[code.minInstructionOrder(childNode3)];
            defineSubnodesJumps(childNode3, code, nextNode, getStartSubnode(code, childNode1, getStartSubnode(code, childNode2, childNode0.jumpDefault)));
        end;
        AVT_WHILE: begin
            childNode0 := parentNode[0];
            childNode1 := parentNode[1];
            childNode2 := parentNode[2];
            nextNode := code[code.maxInstructionOrder(parentNode) + 1];
            childNode0.jumpDefault := code[code.minInstructionOrder(childNode2)];
            defineSubnodesJumps(childNode2, code, nextNode, getStartSubnode(code, childNode1, childNode0.jumpDefault));
        end;
        AVT_SWITCH: begin
            for i := 1 to parentNode.length - 1 do begin
                childNode0 := parentNode[i];
                case childNode0.instruction of
                AVT_CASE: begin
                    parentNode.jumpCaseSetNode((childNode0.operand1 as AVTConstant).value.asInt, childNode0);
                end;
                AVT_DEFAULT: begin
                    parentNode.jumpDefault := childNode0;
                end;
                end;
            end;
        end;
        AVT_BREAK, AVT_CONTINUE, AVT_RETURN: begin
            len := parentNode.length;
            childNode0 := parentNode.operand1 as AVTNode;
            case instruction of
            AVT_CONTINUE: begin
                instruction := JUMP;
                if childNode0.instruction = AVT_FOR then begin
                    childNode1 := childNode0[childNode0.length - 2];
                    childNode2 := childNode0.lastChild();
                    nextNode := getStartSubnode(code, childNode1, code[code.minInstructionOrder(childNode2)]);
                end else begin
                    childNode1 := childNode0.lastChild();
                    nextNode := code[code.minInstructionOrder(childNode1)];
                end;
            end;
            AVT_BREAK: begin
                instruction := JUMP;
                nextNode := code[code.maxInstructionOrder(childNode0) + 1];
            end
            else
                childNode0 := code.root;
                nextNode := childNode0.lastChild();
            end;
            childNode1 := parentNode;
            repeat
                childNode1 := childNode1.parent;
                if childNode1.instruction <> AVT_TRY_BEGIN then continue;
                childNode2 := childNode1.lastChild();
                if childNode2.instruction <> AVT_FINALLY then continue;
                if len = 0 then begin
                    childNode3 := code.insertNode(parentNode.parent, parentNode.index, parentNode.lineIndex, parentNode.dataType, instruction);
                    code.assignInstructionOrder(childNode3, parentNode.order + 1);
                    code.moveNode(parentNode, childNode3, 0);
                    parentNode.instruction := AVT_FINALLY_INVOKE;
                    parentNode.operand1 := childNode2;
                    parentNode := childNode3;
                end else begin
                    childNode3 := parentNode.lastChild();
                    childNode4 := code.appendNode(parentNode, parentNode.lineIndex, parentNode.dataType, AVT_FINALLY_INVOKE, childNode2);
                    code.assignInstructionOrder(childNode4, code.maxInstructionOrder(childNode3) + 1);
                end;
                inc(len);
            until childNode1 = childNode0;
            parentNode.instruction := instruction;
            parentNode.operand1 := nil;
            parentNode.jumpDefault := nextNode;
            if len > 0 then begin
                childNode0 := parentNode[0];
                childNode0.jumpDefault := code[childNode0.order + 1];
            end;
        end;
        AVT_TRY_BEGIN: begin
            parentNode[2].jumpDefault := code[code.maxInstructionOrder(parentNode) + 1];
        end;
        AVT_CATCH: begin
            if parentNode.length > 0 then begin
                childNode0 := parentNode.lastChild();
                if childNode0.instruction = JUMP then begin
                    childNode0.jumpDefault := code[code.maxInstructionOrder(parentNode.parent) + 1];
                end;
            end;
            parentNode.jumpDefault := code[parentNode.order + 1];
        end;
        AVT_THROW, AVT_FINALLY_RETURN: begin
            { нет переходов с throw и finallyReturn }
        end
        else
            order := parentNode.order;
            if order >= 0 then begin
                parentNode.jumpDefault := code[order + 1];
            end;
        end;
    end;

    class procedure AVTCodeBuilder.defineSubnodesJumps(parentNode: AVTNode; code: AVTCode; jumpIsFalse, jumpIsTrue: AVTNode);
    var
        node: AVTNode;
    begin
        case parentNode.instruction of
        OPER_BOOL_OR: begin
            node := parentNode[1];
            defineSubnodesJumps(parentNode[0], code, code[code.minInstructionOrder(node)], jumpIsTrue);
            defineSubnodesJumps(node, code, jumpIsFalse, jumpIsTrue);
        end;
        OPER_BOOL_AND: begin
            node := parentNode[1];
            defineSubnodesJumps(parentNode[0], code, jumpIsFalse, code[code.minInstructionOrder(node)]);
            defineSubnodesJumps(node, code, jumpIsFalse, jumpIsTrue);
        end;
        OPER_BOOL_NOT: begin
            defineSubnodesJumps(parentNode[0], code, jumpIsTrue, jumpIsFalse);
        end;
        OPER_BOOL_COND: begin
            code.clearInstructionOrder(parentNode[2]);
            defineSubnodesJumps(parentNode[0], code, code[code.minInstructionOrder(parentNode[3])], code[code.minInstructionOrder(parentNode[1])]);
            defineSubnodesJumps(parentNode[1], code, jumpIsFalse, jumpIsTrue);
            defineSubnodesJumps(parentNode[3], code, jumpIsFalse, jumpIsTrue);
        end
        else
            parentNode.setBooleanJump(jumpIsFalse, jumpIsTrue);
        end;
    end;

    class function AVTCodeBuilder.getStartSubnode(code: AVTCode; parentNode, ifEmptyNode: AVTNode): AVTNode;
    var
        order: int;
    begin
        order := code.minInstructionOrder(parentNode);
        if order < 0 then begin
            result := ifEmptyNode;
            exit;
        end;
        result := code[order];
    end;

    class function AVTCodeBuilder.defineSubnodesOrder(parentNode: AVTNode; code: AVTCode; startFromOrder: int): int;
    var
        i: int;
        len: int;
    begin
        case parentNode.instruction of
        AVT_WITH, AVT_IF, AVT_LABEL, AVT_DO, AVT_FOR, AVT_WHILE, AVT_BLOCK, OPER_BOOL_NOT, OPER_BOOL_AND, OPER_BOOL_OR, OPER_BOOL_COND, OPER_SCAL_PLUS, OPER_VECT_PLUS: begin
            { нумеруются только дочерние узлы, родительский узел НЕ нумеруется }
            for i := 0 to parentNode.length - 1 do begin
                startFromOrder := defineSubnodesOrder(parentNode[i], code, startFromOrder);
            end;
        end;
        AVT_TRY_BEGIN, AVT_CATCH, AVT_FINALLY, AVT_ENTER, NEW_ARRAY_BY_ELEMENTS, NEW_CLASS, NEW_SERVICE, NEW_STRUCT: begin
            { узлы нумеруются как в управляющей конструкции: сначала – родительский узел, затем – дочерние узлы }
            code.assignInstructionOrder(parentNode, startFromOrder);
            inc(startFromOrder);
            for i := 0 to parentNode.length - 1 do begin
                startFromOrder := defineSubnodesOrder(parentNode[i], code, startFromOrder);
            end;
        end;
        AVT_SWITCH, AVT_MONITOR_ENTER: begin
            { узлы нумеруются в следующем порядке: нулевой дочерний узел, родительский узел, остальные дочерние узлы }
            len := parentNode.length;
            if len <= 0 then begin
                code.assignInstructionOrder(parentNode, startFromOrder);
                inc(startFromOrder);
            end else begin
                startFromOrder := defineSubnodesOrder(parentNode[0], code, startFromOrder);
                code.assignInstructionOrder(parentNode, startFromOrder);
                inc(startFromOrder);
                for i := 1 to parentNode.length - 1 do begin
                    startFromOrder := defineSubnodesOrder(parentNode[i], code, startFromOrder);
                end;
            end;
        end
        else
            { узлы нумеруются как в выражении: сначала – дочерние узлы, затем – родительский узел }
            for i := 0 to parentNode.length - 1 do begin
                startFromOrder := defineSubnodesOrder(parentNode[i], code, startFromOrder);
            end;
            code.assignInstructionOrder(parentNode, startFromOrder);
            inc(startFromOrder);
        end;
        result := startFromOrder;
    end;

    class function AVTCodeBuilder.isRecursiveConstructorInvokation(constructorRef: AVTInstInit): boolean;
    var
        code: AVTCode;
        node: AVTNode;
        operand: _Object;
        anotherConstructorRef: AVTInstInit;
    begin
        anotherConstructorRef := constructorRef;
        repeat
            code := anotherConstructorRef.code;
            if code = nil then break;
            node := code.root;
            if node.length <= 0 then break;
            node := node.firstChild();
            if node.instruction <> INVOKE_SPECIAL then break;
            operand := node.operand1;
            if not(operand is AVTInstInit) then break;
            anotherConstructorRef := AVTInstInit(operand);
            if constructorRef = anotherConstructorRef then begin
                result := true;
                exit;
            end;
        until false;
        result := false;
    end;

    class function AVTCodeBuilder.getCatchNode(currentNode: AVTNode; exceptionType: AVTTypeStructured): AVTNode;
    var
        i: int;
        node: AVTNode;
        child: AVTNode;
    begin
        node := currentNode.parent;
        while node <> nil do begin
            if node.instruction = AVT_TRY_BEGIN then for i := 3 to node.length - 1 do begin
                child := node[i];
                if (child.instruction = AVT_CATCH) and (child.operand1 as AVTVariable).valueType.isAssignableFrom(exceptionType) then begin
                    result := child;
                    exit;
                end;
            end;
            node := node.parent;
        end;
        result := nil;
    end;

    class function AVTCodeBuilder.getVariable(const simpleName: AnsiString; parentNode: AVTNode; methodRef: AVTMethod): AVTVariable;
    var
        childNode: AVTNode;
        associate: _Object;
    begin
        repeat
            with parentNode.childs() do while hasMoreElements() do begin
                childNode := nextElement().objectValue() as AVTNode;
                case childNode.instruction of
                DECLARE_VARIABLE, AVT_CATCH: begin
                    associate := childNode.operand1;
                    if (associate is AVTVariable) and (AVTVariable(associate).simpleName = simpleName) then begin
                        result := AVTVariable(associate);
                        exit;
                    end;
                end;
                end;
            end;
            parentNode := parentNode.parent;
        until parentNode = nil;
        result := methodRef.getArgument(simpleName);
    end;

    procedure AVTCodeBuilder.buildCode(methodRef: AVTMethod);
    label
        label0,
        label1;
    var
        condition: boolean;
        labelNeeded: boolean;
        pos: int;
        index: int;
        order: int;
        lineIndex: int;
        labelNumber: int;
        code: AVTCode;
        root: AVTNode;
        node: AVTNode;
        child0: AVTNode;
        child1: AVTNode;
        child2: AVTNode;
        expNode: AVTNode;
        condNode: AVTNode;
        source: AVTSource;
        constant: AVTConstant;
        argumentTypes: Vector;
        foundInit: AVTMethod;
        typeVoidRef: AVTType;
        typeBooleanRef: AVTType;
        typeRef: AVTTypeStructured;
        typeDereferenceRef: AVTTypeStructured;
    begin
        code := methodRef.code;
        if code = nil then exit;
        root := code.root;
        source := methodRef.source;
        typeRef := methodRef.parentType;
        pos := methodRef.implementationPosition;
        typeVoidRef := getPrimitiveType(AVT_VOID);
        typeBooleanRef := getPrimitiveType(AVT_BOOLEAN);
        if not methodRef.isSynthetic() then begin
            if pos < 0 then begin
                if methodRef is AVTClassInit then begin
                    insertClinitTryLockNode(root, code, typeRef);
                    code.appendNode(root).setData(-1, typeVoidRef, AVT_LEAVE, methodRef.returnType);
                end;
            end else begin
                root.setData(source.getLexemeLineIndex(pos), typeVoidRef, AVT_ENTER);
                if methodRef is AVTInstInit then begin
                    { вставка вызова конструктора }
                    lineIndex := source.getLexemeLineIndex(pos);
                    if source.getLexemeType(pos) = CHAR_COLON then begin
                        inc(pos);
                        if source.getLexemeType(pos) = AVT_SUPER then begin
                            typeDereferenceRef := typeRef.extends();
                        end else begin
                            typeDereferenceRef := typeRef;
                        end;
                        if typeDereferenceRef = nil then begin
                            raise AVTCompilerException.create('super can not be used in ' + itemToString(typeRef), source, pos);
                        end;
                        node := code.appendNode(root, lineIndex, typeVoidRef, INVOKE_SPECIAL, nil);
                        code.appendNode(node).setData(lineIndex, typeRef, LOAD_VARIABLE, methodRef.argumentThis);
                        inc(pos, 2); { переход через открывающую круглую скобку }
                        argumentTypes := Vector.create();
                        try
                            if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then repeat
                                pos := parseExpression(node, code, methodRef, typeRef, source, pos, true);
                                expNode := node.lastChild();
                                needValue(expNode, code);
                                argumentTypes.append(ValueOfObject.create(expNode.dataType, false));
                                case source.getLexemeType(pos) of
                                CHAR_COMMA: begin
                                    inc(pos);
                                end;
                                CHAR_PARENTH_CLOSED: begin
                                    break;
                                end
                                else
                                    raise AVTCompilerException.create('")" expected', source, pos);
                                end;
                            until false;
                            foundInit := typeDereferenceRef.findMethod(SPECNAME_INST_INIT, argumentTypes, typeRef, pos);
                            if not foundInit.isConvertableArgumentTypes(argumentTypes) then begin
                                raise AVTCompilerException.create('The constructor ' + foundInit.parentType.simpleName + foundInit.argumentsToString() + ' is not applicable for the arguments ' + argumentTypes.toString(), source, pos);
                            end;
                        finally
                            argumentTypes.free();
                        end;
                        if not foundInit.isVisible(typeRef, typeRef) then begin
                            raise AVTCompilerException.create('The constructor ' + foundInit.parentType.simpleName + foundInit.argumentsToString() + ' is not visible', source, pos);
                        end;
                        for index := 0 to foundInit.getArgumentsCount() - 1 do begin
                            cast(node[index + 1], code, foundInit.getArgumentAt(index).valueType);
                        end;
                        node.operand1 := foundInit;
                        inc(pos); { переход через закрывающую круглую скобку }
                        if isRecursiveConstructorInvokation(AVTInstInit(methodRef)) then begin
                            raise AVTCompilerException.create('Recursive constructor invokation ' + foundInit.parentType.simpleName + foundInit.argumentsToString(), source, pos);
                        end;
                    end else begin
                        typeDereferenceRef := typeRef.extends();
                        if typeDereferenceRef <> nil then begin
                            foundInit := typeDereferenceRef.findMethod(SPECNAME_INST_INIT, nil, typeRef, pos);
                            if not foundInit.isConvertableArgumentTypes(nil) then begin
                                raise AVTCompilerException.create('Implicit super constructor ' + foundInit.parentType.simpleName + '() is undefined. Must explicitly invoke another constructor', source, pos);
                            end;
                            if not foundInit.isVisible(typeRef, typeRef) then begin
                                raise AVTCompilerException.create('Implicit super constructor ' + foundInit.parentType.simpleName + '() is not visible. Must explicitly invoke another constructor', source, pos);
                            end;
                            node := code.appendNode(root, lineIndex, typeVoidRef, INVOKE_SPECIAL, foundInit);
                            code.appendNode(node).setData(lineIndex, typeRef, LOAD_VARIABLE, methodRef.argumentThis);
                        end;
                    end;
                end;
                inc(pos); { переход через открывающую фигурную скобку }
                if methodRef is AVTClassInit then begin
                    child0 := insertClinitTryLockNode(root, code, typeRef);
                end else
                if (methodRef.flags and FLAG_SYNCHRONIZED) <> 0 then begin
                    child0 := insertSynchronizedNode(root, code, methodRef, typeRef);
                end else begin
                    child0 := root;
                end;
                repeat
                    case source.getLexemeType(pos) of
                    CHAR_CURLY_CLOSED: begin
                        code.appendNode(root).setData(source.getLexemeLineIndex(pos), typeVoidRef, AVT_LEAVE, methodRef.returnType);
                        break;
                    end;
                    AVT_END: begin
                        raise AVTCompilerException.create('"}" expected', source, pos);
                    end
                    else
                        pos := parseStatement(child0, code, methodRef, typeRef, source, pos);
                    end;
                until false;
            end;
        end;
        { добавление узлов }
        with code.nodes() do while hasMoreElements() do begin
            node := nextElement().objectValue() as AVTNode;
            case node.instruction of
            OPER_BOOL_NOT, OPER_BOOL_AND, OPER_BOOL_OR: begin
                index := node.index;
                expNode := node.parent;
                case expNode.instruction of
                OPER_BOOL_COND, OPER_BOOL_NOT, OPER_BOOL_AND, OPER_BOOL_OR: begin
                    continue;
                end;
                AVT_DO, AVT_FOR, AVT_WHILE: begin
                    if index >= expNode.length - 1 then continue;
                end;
                AVT_IF: begin
                    if index <= 0 then continue;
                end;
                end;
                lineIndex := node.lineIndex;
                condNode := code.insertNode(expNode, index, lineIndex, typeBooleanRef, OPER_BOOL_COND);
                code.moveNode(node, condNode, 0);
                constant := AVTConstant.create(typeBooleanRef);
                constant.value.asBoolean := true;
                code.appendNode(condNode).setData(lineIndex, typeBooleanRef, LOAD_CONST, constant);
                code.appendNode(condNode).setData(lineIndex, typeVoidRef, JUMP);
                constant := AVTConstant.create(typeBooleanRef);
                constant.value.asBoolean := false;
                code.appendNode(condNode).setData(lineIndex, typeBooleanRef, LOAD_CONST, constant);
            end;
            AVT_ENTER: begin
                insertClinitInvoke(node, code, typeRef, methodRef, node.lineIndex);
            end;
            LOAD_STATIC: begin
                insertClinitInvoke(node, code, typeRef, node.operand1 as AVTMember, node.lineIndex);
            end;
            end;
        end;
        { нумерация узлов }
        defineSubnodesOrder(root, code, 0);
        for index := code.length - 2 downto 0 do begin
            node := code[index];
            case node.instruction of
            OPER_SCAL_E, OPER_SCAL_NE: begin
                if (node.operand1 is AVTTypeStructured) and (node.length = 2) then begin
                    child1 := node[0];
                    child2 := node[1];
                    if (child1.order >= 0) and child1.isLoadNull() then begin
                        code.clearInstructionOrder(child1);
                        continue;
                    end;
                    if (child2.order >= 0) and child2.isLoadNull() then begin
                        code.clearInstructionOrder(child2);
                        continue;
                    end;
                end;
            end;
            end;
        end;
        { расстановка переходов }
        index := 0;
        node := root;
        defineSubnodesJumps(node, code);
        if node.length > 0 then repeat
            child0 := node[index];
            order := child0.order;
            if (order < 0) or (order < code.length - 1) and (child0.jumpDefault = nil) then begin
                defineSubnodesJumps(child0, code);
            end;
            if child0.length > 0 then begin
                index := 0;
                node := child0;
                continue;
            end;
            inc(index);
            while index >= node.length do begin
                index := node.index + 1;
                node := node.parent;
                if node = nil then goto label0;
            end;
        until false;
        label0:
        { оптимизация переходов }
        { --- не реализовано в этой версии, но обязательно должно быть реализовано в одной из следующих --- }
        { оптимизация переходов в try…finally }
        repeat
            condition := true;
            with code.nodes() do while hasMoreElements() do with nextElement().objectValue() as AVTNode do if (instruction = AVT_TRY_BEGIN) and (child[3].instruction = AVT_FINALLY) then begin
                child1 := child[1];  { instruction = AVT_TRY_END }
                child0 := child1[0]; { instruction = AVT_FINALLY_INVOKE }
                if (child0.order >= 0) and (child0.order > order + 1) and not code.isHasJumpsTo(child0) then begin
                    child2 := child[2];  { instruction = JUMP }
                    code.clearInstructionOrder(child0);
                    code.clearInstructionOrder(child2);
                    child0.jumpDefault := nil;
                    child1.jumpDefault := nil;
                    child2.jumpDefault := nil;
                    condition := false;
                    break;
                end;
            end;
        until condition;
        { проверка обязательного возвращения значения }
        if not methodRef.returnType.isVoid() then with code.instructions() do while hasMoreElements() do begin
            node := nextElement().objectValue() as AVTNode;
            if node.instruction = AVT_RETURN then begin
                child0 := code[node.order + 1];
                if child0.instruction = AVT_LEAVE then begin
                    code.clearInstructionOrder(node);
                    code.replaceNode(node, child0);
                    break;
                end;
                continue;
            end;
            child0 := node.jumpDefault;
            if (child0 <> nil) and (child0.instruction = AVT_LEAVE) then begin
                raise AVTCompilerException.create('Missing return statement', source, pos);
            end;
            with node.jumpCaseValues() do while hasMoreElements() do begin
                child0 := node.jumpCaseGetNode(nextElement().intValue());
                if (child0 <> nil) and (child0.instruction = AVT_LEAVE) then begin
                    raise AVTCompilerException.create('Missing return statement', source, pos);
                end;
            end;
        end;
        { проверка генерации исключений }
        with code.instructions() do while hasMoreElements() do begin
            child0 := nextElement().objectValue() as AVTNode;
            typeDereferenceRef := nil;
            case child0.instruction of
            AVT_THROW: begin
                typeDereferenceRef := child0[0].dataType as AVTTypeStructured;
                node := getCatchNode(child0, typeDereferenceRef);
                if node <> nil then begin
                    child0.jumpDefault := node;
                    continue;
                end;
                if methodRef.mightThrown(typeDereferenceRef) then continue;
            end;
            INVOKE_STATIC, INVOKE_SPECIAL, INVOKE_VIRTUAL, INVOKE_SERVICE: begin
                with (child0.operand1 as AVTMethod).throws() do while hasMoreElements() do begin
                    typeDereferenceRef := nextElement().objectValue() as AVTTypeStructured;
                    if (getCatchNode(child0, typeDereferenceRef) = nil) and not methodRef.mightThrown(typeDereferenceRef) then goto label1;
                end;
                continue;
            end;
            end;
            label1:
            if typeDereferenceRef <> nil then begin
                raise AVTCompilerException.create('Unhandled exception type ' + itemToString(typeDereferenceRef), source.fileName, child0.lineIndex, 0);
            end;
        end;
        { расстановка меток }
        labelNumber := 0;
        with code.instructions() do while hasMoreElements() do begin
            child0 := nextElement().objectValue() as AVTNode;
            case child0.instruction of
            AVT_CASE, AVT_DEFAULT, AVT_TRY_BEGIN, AVT_TRY_END, AVT_CATCH, AVT_FINALLY:
                labelNeeded := true
            else
                labelNeeded := false;
                order := child0.order - 1;
                with code.instructions() do while hasMoreElements() do begin
                    child1 := nextElement().objectValue() as AVTNode;
                    condition := order = child1.order;
                    (* if(order == child1.order ? child1.instruction == AVT_SWITCH : child1.isJumpTo(child0)) { … } *)
                    if condition and (child1.instruction = AVT_SWITCH) or not condition and child1.isJumpTo(child0) then begin
                        labelNeeded := true;
                        break;
                    end;
                end;
            end;
            if labelNeeded then begin
                child0.labelNumber := labelNumber;
                inc(labelNumber);
            end;
        end;
    end;

    procedure AVTCodeBuilder.needValue(currentNode: AVTNode; code: AVTCode);
    var
        lastNode: AVTNode;
        typeReturnRef: AVTType;
        foundMethod: AVTMethod;
        foundProperty: AVTProperty;
    begin
        typeReturnRef := currentNode.dataType;
        if (typeReturnRef = nil) or not typeReturnRef.isVoid() then exit;
        case currentNode.instruction of
        STORE_VARIABLE: begin
            lastNode := currentNode.lastChild();
            currentNode.dataType := (currentNode.operand1 as AVTVariable).valueType;
            code.appendNode(currentNode).setData(lastNode.lineIndex, getPrimitiveType(AVT_VOID), DUP1);
        end;
        STORE_STATIC: begin
            lastNode := currentNode.lastChild();
            currentNode.dataType := (currentNode.operand1 as AVTField).valueType;
            code.appendNode(currentNode).setData(lastNode.lineIndex, getPrimitiveType(AVT_VOID), DUP1);
        end;
        SET_FIELD: begin
            lastNode := currentNode.lastChild();
            currentNode.dataType := (currentNode.operand1 as AVTField).valueType;
            code.appendNode(currentNode).setData(lastNode.lineIndex, getPrimitiveType(AVT_VOID), DUP1X1);
        end;
        SET_PROPERTY: begin
            lastNode := currentNode.lastChild();
            currentNode.dataType := (currentNode.operand1 as AVTProperty).valueType;
            code.appendNode(currentNode).setData(lastNode.lineIndex, getPrimitiveType(AVT_VOID), DUP1X1);
        end;
        SET_ARRAY_ELEMENT: begin
            lastNode := currentNode.lastChild();
            currentNode.dataType := currentNode.operand1 as AVTType;
            code.appendNode(currentNode).setData(lastNode.lineIndex, getPrimitiveType(AVT_VOID), DUP1X2);
        end;
        INVOKE_SPECIAL, INVOKE_VIRTUAL, INVOKE_SERVICE: begin
            foundMethod := currentNode.operand1 as AVTMethod;
            if (foundMethod is AVTOperator) and (AVTOperator(foundMethod).operatorKind = SET_ARRAY_ELEMENT) then begin
                lastNode := currentNode.lastChild();
                currentNode.dataType := foundMethod.getArgumentAt(1).valueType;
                code.appendNode(currentNode).setData(lastNode.lineIndex, getPrimitiveType(AVT_VOID), DUP1X2);
            end else begin
                foundProperty := foundMethod.linkedProperty;
                if (foundProperty <> nil) and (foundProperty.writeSynthetic = foundMethod) then begin
                    lastNode := currentNode.lastChild();
                    currentNode.dataType := foundMethod.getArgumentAt(0).valueType;
                    code.appendNode(currentNode).setData(lastNode.lineIndex, getPrimitiveType(AVT_VOID), DUP1X1);
                end;
            end;
        end;
        end;
    end;

    procedure AVTCodeBuilder.discardValue(currentNode: AVTNode; code: AVTCode);
    var
        instruction: int;
        lastNode: AVTNode;
        checkNode: AVTNode;
        deleteNode: AVTNode;
        parentNode: AVTNode;
        typeVoidRef: AVTType;
        typeReturnRef: AVTType;
        foundMethod: AVTMethod;
        foundProperty: AVTProperty;
    begin
        typeReturnRef := currentNode.dataType;
        if (typeReturnRef <> nil) and typeReturnRef.isVoid() then exit;
        typeVoidRef := getPrimitiveType(AVT_VOID);
        case currentNode.instruction of
        OPER_INC_POST, OPER_INC_PRED: begin
            currentNode.instruction := OPER_INCREMENT;
            currentNode.dataType := typeVoidRef;
            exit;
        end;
        OPER_DEC_POST, OPER_DEC_PRED: begin
            currentNode.instruction := OPER_DECREMENT;
            currentNode.dataType := typeVoidRef;
            exit;
        end;
        STORE_VARIABLE, STORE_STATIC: begin
            lastNode := currentNode.lastChild();
            if lastNode.instruction = DUP1 then begin
                code.removeNode(lastNode);
                currentNode.dataType := typeVoidRef;
                exit;
            end;
            if currentNode.length = 2 then begin
                checkNode := currentNode[0];
                lastNode := currentNode.lastChild();
                if lastNode.instruction = OPER_TYPE_CAST then begin
                    lastNode := lastNode.firstChild();
                end;
                instruction := lastNode.instruction;
                if (instruction = OPER_VECT_ADD) or (instruction = OPER_SCAL_ADD) then begin
                    deleteNode := lastNode.firstChild();
                    if deleteNode.instruction = DUP1 then begin
                        code.removeNode(deleteNode);
                        code.moveNode(checkNode, lastNode, 0);
                        currentNode.dataType := typeVoidRef;
                        exit;
                    end;
                end;
            end;
        end;
        SET_FIELD, SET_PROPERTY: begin
            lastNode := currentNode.lastChild();
            if lastNode.instruction = DUP1X1 then begin
                code.removeNode(lastNode);
                currentNode.dataType := typeVoidRef;
                exit;
            end;
            if currentNode.length = 3 then begin
                checkNode := currentNode[1];
                lastNode := currentNode.lastChild();
                if lastNode.instruction = OPER_TYPE_CAST then begin
                    lastNode := lastNode.firstChild();
                end;
                instruction := lastNode.instruction;
                if (instruction = OPER_VECT_ADD) or (instruction = OPER_SCAL_ADD) then begin
                    deleteNode := lastNode.firstChild();
                    if deleteNode.instruction = DUP1X1 then begin
                        code.removeNode(deleteNode);
                        code.moveNode(checkNode, lastNode, 0);
                        currentNode.dataType := typeVoidRef;
                        exit;
                    end;
                end;
            end;
        end;
        SET_ARRAY_ELEMENT: begin
            lastNode := currentNode.lastChild();
            if lastNode.instruction = DUP1X2 then begin
                code.removeNode(lastNode);
                currentNode.dataType := typeVoidRef;
                exit;
            end;
            if currentNode.length = 4 then begin
                checkNode := currentNode[2];
                lastNode := currentNode.lastChild();
                if lastNode.instruction = OPER_TYPE_CAST then begin
                    lastNode := lastNode.firstChild();
                end;
                instruction := lastNode.instruction;
                if (instruction = OPER_VECT_ADD) or (instruction = OPER_SCAL_ADD) then begin
                    deleteNode := lastNode.firstChild();
                    if deleteNode.instruction = DUP1X2 then begin
                        code.removeNode(deleteNode);
                        code.moveNode(checkNode, lastNode, 0);
                        currentNode.dataType := typeVoidRef;
                        exit;
                    end;
                end;
            end;
        end;
        INVOKE_SPECIAL, INVOKE_VIRTUAL, INVOKE_SERVICE: begin
            foundMethod := currentNode.operand1 as AVTMethod;
            if (foundMethod is AVTOperator) and (AVTOperator(foundMethod).operatorKind = SET_ARRAY_ELEMENT) then begin
                lastNode := currentNode.lastChild();
                if lastNode.instruction = DUP1X2 then begin
                    code.removeNode(lastNode);
                    currentNode.dataType := typeVoidRef;
                    exit;
                end;
                if currentNode.length = 4 then begin
                    checkNode := currentNode[2];
                    lastNode := currentNode.lastChild();
                    if lastNode.instruction = OPER_TYPE_CAST then begin
                        lastNode := lastNode.firstChild();
                    end;
                    instruction := lastNode.instruction;
                    if (instruction = OPER_VECT_ADD) or (instruction = OPER_SCAL_ADD) then begin
                        deleteNode := lastNode.firstChild();
                        if deleteNode.instruction = DUP1X2 then begin
                            code.removeNode(deleteNode);
                            code.moveNode(checkNode, lastNode, 0);
                            currentNode.dataType := typeVoidRef;
                            exit;
                        end;
                    end;
                end;
            end else begin
                foundProperty := foundMethod.linkedProperty;
                if (foundProperty <> nil) and (foundProperty.writeSynthetic = foundMethod) then begin
                    lastNode := currentNode.lastChild();
                    if lastNode.instruction = DUP1X1 then begin
                        code.removeNode(lastNode);
                        currentNode.dataType := typeVoidRef;
                        exit;
                    end;
                    if currentNode.length = 3 then begin
                        checkNode := currentNode[1];
                        lastNode := currentNode.lastChild();
                        if lastNode.instruction = OPER_TYPE_CAST then begin
                            lastNode := lastNode.firstChild();
                        end;
                        instruction := lastNode.instruction;
                        if (instruction = OPER_VECT_ADD) or (instruction = OPER_SCAL_ADD) then begin
                            deleteNode := lastNode.firstChild();
                            if deleteNode.instruction = DUP1X1 then begin
                                code.removeNode(deleteNode);
                                code.moveNode(checkNode, lastNode, 0);
                                currentNode.dataType := typeVoidRef;
                                exit;
                            end;
                        end;
                    end;
                end;
            end;
        end
        end;
        parentNode := code.insertNode(currentNode.parent, currentNode.index, currentNode.lineIndex, typeVoidRef, POP1);
        code.moveNode(currentNode, parentNode, 0);
    end;

    procedure AVTCodeBuilder.insertAfterConstructionInvoke(parentNode: AVTNode; code: AVTCode; pos, lineIndex: int);
    var
        currentNode: AVTNode;
        foundMethod: AVTMethod;
        typeStructuredRef: AVTTypeStructured;
    begin
        typeStructuredRef := getObjectType();
        foundMethod := typeStructuredRef.findMethod('afterConstruction', nil, typeStructuredRef, pos);
        if foundMethod <> nil then begin
            currentNode := code.appendNode(parentNode, lineIndex, foundMethod.returnType, INVOKE_VIRTUAL, foundMethod);
            code.appendNode(currentNode).setData(lineIndex, getPrimitiveType(AVT_VOID), DUP1);
        end;
    end;

    procedure AVTCodeBuilder.insertClinitInvoke(parentNode: AVTNode; code: AVTCode; typeRef: AVTTypeStructured; memberRef: AVTMember; lineIndex: int);
    var
        memberType: TClass;
        staticMethod: AVTClassInit;
        typeTargetRef: AVTTypeStructured;
    begin
        memberType := memberRef.classType();
        typeTargetRef := memberRef.parentType;
        if (memberType = AVTMethod) and memberRef.isStatic() or (memberType = AVTInstInit) or (memberType = AVTField) and (typeRef <> typeTargetRef) then begin
            with typeTargetRef.members(SPECNAME_CLASS_INIT) do if hasMoreElements() then begin
                staticMethod := nextElement().objectValue() as AVTClassInit;
                code.insertNode(parentNode, 0).setData(lineIndex, getPrimitiveType(AVT_VOID), INVOKE_STATIC, staticMethod);
            end;
        end;
    end;

    function AVTCodeBuilder.insertClinitTryLockNode(rootNode: AVTNode; code: AVTCode; typeRef: AVTTypeStructured): AVTNode;
    var
        i: int;
        child0: AVTNode;
        child1: AVTNode;
        child2: AVTNode;
        child3: AVTNode;
        child4: AVTNode;
        child5: AVTNode;
        childResult: AVTNode;
        typeVoidRef: AVTType;
        typeBooleanRef: AVTType;
    begin
        (*
            root
                void if  <== child0
                    boolean clinitTryLock(typeRef)
                    void {…}  <== child1
                        void tryBegin  <== child2
                            void {…}  <== childResult
                            void tryEnd  <== child3
                                void finallyInvoke(child5)  <== child4
                            void jump
                            void finally  <== child5
                                void clinitUnlock
                                void finallyReturn
        *)
        typeVoidRef := getPrimitiveType(AVT_VOID);
        typeBooleanRef := getPrimitiveType(AVT_BOOLEAN);
        child0 := code.appendNode(rootNode, -1, typeVoidRef, AVT_IF);
        code.appendNode(child0).setData(-1, typeBooleanRef, AVT_CLINIT_TRY_LOCK, typeRef);
        child1 := code.appendNode(child0, -1, typeVoidRef, AVT_BLOCK);
        child2 := code.appendNode(child1, -1, typeVoidRef, AVT_TRY_BEGIN);
        child3 := code.appendNode(child2, -1, typeVoidRef, AVT_TRY_END);
        child4 := code.appendNode(child3, -1, typeVoidRef, AVT_FINALLY_INVOKE, nil);
        code.appendNode(child2).setData(-1, typeVoidRef, JUMP);
        child5 := code.appendNode(child2, -1, typeVoidRef, AVT_FINALLY);
        code.appendNode(child5).setData(-1, typeVoidRef, AVT_CLINIT_UNLOCK);
        code.appendNode(child5).setData(-1, typeVoidRef, AVT_FINALLY_RETURN);
        child4.operand1 := child5;
        childResult := code.insertNode(child2, 0, -1, typeVoidRef, AVT_BLOCK);
        for i := rootNode.length - 2 downto 0 do begin
            code.moveNode(rootNode[i], childResult, 0);
        end;
        result := childResult;
    end;

    function AVTCodeBuilder.insertSynchronizedNode(rootNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured): AVTNode;
    var
        isStatic: boolean;
        child0: AVTNode;
        child1: AVTNode;
        child2: AVTNode;
        child3: AVTNode;
        syncVar: AVTVariable;
        typeVoidRef: AVTType;
        typeClassRef: AVTTypeStructured;
        constant: AVTConstant;
    begin
        isStatic := methodRef.isStatic();
        if isStatic then begin
            typeClassRef := getClassType();
            constant := AVTConstant.create(typeClassRef);
            constant.value.asClass := typeRef;
            syncVar := methodRef.createMonitorVariable(typeClassRef);
        end else begin
            constant := nil;
            syncVar := methodRef.createMonitorVariable(typeRef);
        end;
        typeVoidRef := getPrimitiveType(AVT_VOID);
        child0 := code.appendNode(rootNode, -1, typeVoidRef, AVT_MONITOR_ENTER);
        child1 := code.appendNode(child0, -1, typeVoidRef, DECLARE_VARIABLE, syncVar);
        if isStatic then begin
            code.appendNode(child1).setData(-1, constant.valueType, LOAD_CONST, constant);
        end else begin
            code.appendNode(child1).setData(-1, typeRef, LOAD_VARIABLE, methodRef.argumentThis);
        end;
        code.appendNode(child1).setData(-1, typeVoidRef, DUP1);
        child1 := code.appendNode(child0, -1, typeVoidRef, AVT_TRY_BEGIN);
        child2 := code.appendNode(child1, -1, typeVoidRef, AVT_TRY_END);
        child3 := code.appendNode(child2, -1, typeVoidRef, AVT_FINALLY_INVOKE, nil);
        code.appendNode(child1).setData(-1, typeVoidRef, JUMP);
        child2 := code.appendNode(child1, -1, typeVoidRef, AVT_FINALLY);
        child3.operand1 := child2;
        child3 := code.appendNode(child2, -1, typeVoidRef, AVT_MONITOR_LEAVE);
        code.appendNode(child3).setData(-1, syncVar.valueType, LOAD_VARIABLE, syncVar);
        code.appendNode(child2).setData(-1, typeVoidRef, AVT_FINALLY_RETURN);
        result := code.insertNode(child1, 0, -1, typeVoidRef, AVT_BLOCK);
    end;

    function AVTCodeBuilder.parsePostfix(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers, isUseSuper, isImplicitPeriod: boolean): int;
    var
        isPeriod: boolean;
        isWriteOnly: boolean;
        i: int;
        base: int;
        lineIndex: int;
        lexemeType: int;
        operatorPos: int;
        instruction: int;
        staticContext: int;
        simpleName: AnsiString;
        operand: _Object;
        argumentTypes: Vector;
        childNode: AVTNode;
        currentNode: AVTNode;
        compoundNode: AVTNode;
        expressionNode: AVTNode;
        oldConstant: AVTConstant;
        newConstant: AVTConstant;
        foundClinit: AVTClassInit;
        foundMember: AVTMember;
        foundField: AVTField;
        foundProperty: AVTProperty;
        foundOperator: AVTOperator;
        foundMethod: AVTMethod;
        typeParsedRef: AVTType;
        typeReturnRef: AVTType;
        typeElementRef: AVTType;
        typeIntRef: AVTTypePrimitive;
        typeVoidRef: AVTTypePrimitive;
        typeDereferenceRef: AVTTypeStructured;
    begin
        repeat
            lexemeType := source.getLexemeType(pos);
            if isUseSuper and (lexemeType <> CHAR_PERIOD) and (lexemeType <> CHAR_PARENTH_OPENED) and (lexemeType <> CHAR_BRACKET_OPENED) then begin
                raise AVTCompilerException.create('Syntax error on "super", error in expression', source, pos);
            end;
            isPeriod := false;
            if isImplicitPeriod then begin
                isPeriod := true;
            end else
            if lexemeType = CHAR_PERIOD then begin
                isPeriod := true;
                inc(pos);
            end;
            operatorPos := pos;
            childNode := parentNode.lastChild();
            typeReturnRef := childNode.dataType;
            if isPeriod then begin
                if (typeReturnRef <> nil) and not(typeReturnRef is AVTTypeStructured) then begin
                    raise AVTCompilerException.create('The type ' + typeReturnRef.fullName + ' can not be dereferenced', source, pos);
                end;
                if childNode.instruction = AVT_CLASS then begin
                    typeDereferenceRef := childNode.operand1 as AVTTypeStructured;
                    staticContext := -1; { это точно статичный контекст }
                end else begin
                    typeDereferenceRef := AVTTypeStructured(typeReturnRef);
                    if isImplicitPeriod then begin
                        staticContext := 1; { неопределённый контекст }
                    end else begin
                        staticContext := 0; { это точно инстанционный контекст }
                    end;
                end;
                if typeDereferenceRef = nil then begin
                    raise AVTCompilerException.create('The type null can not be dereferenced', source, pos);
                end;
                case source.getLexemeType(pos) of
                AVT_OPERATOR: begin
                    simpleName := AVTOperator.operatorToSpecName(parseOperator(source, pos + 1));
                    pos := source.position - 1;
                end;
                LITR_NAME: begin
                    simpleName := source.getLexemeAnsiString(pos);
                end
                else
                    raise AVTCompilerException.create('Member name expected', source, pos);
                end;
                foundMember := resolveMember(typeDereferenceRef, simpleName, typeRef, operatorPos);
                if foundMember is AVTField then begin
                    foundField := AVTField(foundMember);
                    case staticContext of
                    -1: begin
                        if not foundField.isStatic() then begin
                            raise AVTCompilerException.create('Can not make a static reference to the non-static field ' + foundMember.simpleName + ' from the type ' + foundMember.parentType.fullName, source, pos);
                        end;
                        oldConstant := foundField.valueConst;
                        if ((foundField.flags and (FLAG_STATIC or FLAG_FINAL)) = (FLAG_STATIC or FLAG_FINAL)) and (oldConstant <> nil) then begin
                            newConstant := AVTConstant.create();
                            newConstant.assign(oldConstant);
                            childNode.setData(childNode.lineIndex, newConstant.valueType, LOAD_CONST, newConstant);
                        end else begin
                            childNode.setData(childNode.lineIndex, foundField.valueType, LOAD_STATIC, foundField);

                        end;
                    end;
                     0: begin
                        if foundField.isStatic() then begin
                            raise AVTCompilerException.create('The static field ' + foundField.parentType.fullName + '.' + foundField.simpleName + ' should be accessed in a static way', source, pos);
                        end;
                        currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), foundField.valueType, GET_FIELD, foundField);
                        code.moveNode(childNode, currentNode, 0);
                    end;
                     1: begin
                        if foundField.isStatic() then begin
                            oldConstant := foundField.valueConst;
                            if ((foundField.flags and FLAG_FINAL) = FLAG_FINAL) and (oldConstant <> nil) then begin
                                newConstant := AVTConstant.create();
                                newConstant.assign(oldConstant);
                                childNode.setData(childNode.lineIndex, newConstant.valueType, LOAD_CONST, newConstant);
                            end else begin
                                childNode.setData(childNode.lineIndex, foundField.valueType, LOAD_STATIC, foundField);
                            end;
                        end else begin
                            currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), foundField.valueType, GET_FIELD, foundField);
                            code.moveNode(childNode, currentNode, 0);
                        end;
                    end;
                    end;
                end else
                if foundMember is AVTProperty then begin
                    foundProperty := AVTProperty(foundMember);
                    if staticContext = -1 then begin
                        raise AVTCompilerException.create('Can not make a static reference to the property ' + foundMember.simpleName + ' from the type ' + foundMember.parentType.fullName, source, pos);
                    end;
                    foundMethod := foundProperty.readSynthetic;
                    if foundMethod = nil then begin
                        if source.getLexemeType(pos + 1) <> CHAR_EQUALS then begin
                            raise AVTCompilerException.create('The write-only property ' + foundProperty.simpleName + ' can not be accessed', source, pos);
                        end;
                        foundMethod := foundProperty.writeSynthetic;
                        if isUseSuper then begin
                            if foundMethod.isAbstract() then begin
                                raise AVTCompilerException.create('Can not directly write abstract property ' + foundMember.simpleName + ' from the type ' + foundMember.parentType.fullName, source, pos);
                            end;
                            currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), foundMethod.returnType, INVOKE_SPECIAL, foundMethod);
                        end else begin
                            currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), SET_PROPERTY, foundProperty);
                        end;
                    end else begin
                        if isUseSuper then begin
                            if foundMethod.isAbstract() then begin
                                raise AVTCompilerException.create('Can not directly read abstract property ' + foundMember.simpleName + ' from the type ' + foundMember.parentType.fullName, source, pos);
                            end;
                            currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), foundMethod.returnType, INVOKE_SPECIAL, foundMethod);
                        end else begin
                            currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), foundProperty.valueType, GET_PROPERTY, foundProperty);
                        end;
                    end;
                    code.moveNode(childNode, currentNode, 0);
                end else
                if foundMember is AVTOperator then begin
                    inc(pos);
                    if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
                        raise AVTCompilerException.create('"(" expected', source, pos);
                    end;
                    inc(pos);
                    currentNode := code.appendNode(parentNode);
                    argumentTypes := Vector.create();
                    try
                        if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then repeat
                            pos := parseExpression(currentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
                            expressionNode := currentNode.lastChild();
                            needValue(expressionNode, code);
                            argumentTypes.append(ValueOfObject.create(expressionNode.dataType, false));
                            case source.getLexemeType(pos) of
                            CHAR_COMMA: begin
                                inc(pos);
                            end;
                            CHAR_PARENTH_CLOSED: begin
                                break;
                            end
                            else
                                raise AVTCompilerException.create('")" expected', source, pos);
                            end;
                        until false;
                        foundOperator := typeDereferenceRef.findMethod(simpleName, argumentTypes, typeRef, pos) as AVTOperator;
                        if not foundOperator.isConvertableArgumentTypes(argumentTypes) then begin
                            raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(foundOperator.operatorKind) + foundOperator.argumentsToString() + ' in the type ' + foundOperator.parentType.fullName + ' is not applicable for the arguments ' + argumentTypes.toString(), source, operatorPos);
                        end;
                    finally
                        argumentTypes.free();
                    end;
                    if isUseSuper and not foundOperator.isVisible(typeRef, typeRef) or not isUseSuper and not foundOperator.isVisible(typeDereferenceRef, typeRef) then begin
                        raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(foundOperator.operatorKind) + foundOperator.argumentsToString() + ' in the type ' + foundOperator.parentType.fullName + ' is not visible', source, operatorPos);
                    end;
                    if isUseSuper and foundOperator.isAbstract() then begin
                        raise AVTCompilerException.create('Can not directly invoke abstract operator ' + AVTOperator.operatorToChar(foundOperator.operatorKind) + foundOperator.argumentsToString() + ' from the type ' + foundOperator.parentType.fullName, source, operatorPos);
                    end;
                    for i := foundOperator.getArgumentsCount() - 1 downto 0 do begin
                        cast(currentNode[i], code, foundOperator.getArgumentAt(i).valueType);
                    end;
                    if staticContext = -1 then begin
                        raise AVTCompilerException.create('Can not make a static reference to the operator ' + AVTOperator.operatorToChar(foundOperator.operatorKind) + foundOperator.argumentsToString() + ' from the type ' + foundOperator.parentType.fullName, source, operatorPos);
                    end;
                    if isUseSuper or (foundOperator.visibility = AVT_PRIVATE) then begin
                        instruction := INVOKE_SPECIAL;
                    end else
                    if foundOperator.parentType.isService() then begin
                        instruction := INVOKE_SERVICE;
                    end else begin
                        instruction := INVOKE_VIRTUAL;
                    end;
                    code.moveNode(childNode, currentNode, 0);
                    currentNode.setData(source.getLexemeLineIndex(operatorPos), foundOperator.returnType, instruction, foundOperator);
                end else
                if foundMember is AVTMethod then begin
                    inc(pos);
                    { СДЕЛАТЬ: if (foundMember.flags and FLAG_INTERRUPT) <> 0 then … }
                    if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
                        raise AVTCompilerException.create('"(" expected', source, pos);
                    end;
                    inc(pos);
                    currentNode := code.appendNode(parentNode);
                    argumentTypes := Vector.create();
                    try
                        if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then repeat
                            pos := parseExpression(currentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
                            expressionNode := currentNode.lastChild();
                            needValue(expressionNode, code);
                            argumentTypes.append(ValueOfObject.create(expressionNode.dataType, false));
                            case source.getLexemeType(pos) of
                            CHAR_COMMA: begin
                                inc(pos);
                            end;
                            CHAR_PARENTH_CLOSED: begin
                                break;
                            end
                            else
                                raise AVTCompilerException.create('")" expected', source, pos);
                            end;
                        until false;
                        foundMethod := typeDereferenceRef.findMethod(simpleName, argumentTypes, typeRef, pos);
                        if not foundMethod.isConvertableArgumentTypes(argumentTypes) then begin
                            raise AVTCompilerException.create('The method ' + foundMethod.simpleName + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not applicable for the arguments ' + argumentTypes.toString(), source, operatorPos);
                        end;
                    finally
                        argumentTypes.free();
                    end;
                    if isUseSuper and not foundMethod.isVisible(typeRef, typeRef) or not isUseSuper and not foundMethod.isVisible(typeDereferenceRef, typeRef) then begin
                        raise AVTCompilerException.create('The method ' + foundMethod.simpleName + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
                    end;
                    if isUseSuper and foundMethod.isAbstract() then begin
                        raise AVTCompilerException.create('Can not directly invoke abstract method ' + foundMethod.simpleName + foundMethod.argumentsToString() + ' from the type ' + foundMethod.parentType.fullName, source, operatorPos);
                    end;
                    for i := foundMethod.getArgumentsCount() - 1 downto 0 do begin
                        cast(currentNode[i], code, foundMethod.getArgumentAt(i).valueType);
                    end;
                    case staticContext of
                    -1: begin
                        if not foundMethod.isStatic() then begin
                            raise AVTCompilerException.create('Can not make a static reference to the method ' + foundMethod.simpleName + foundMethod.argumentsToString() + ' from the type ' + foundMethod.parentType.fullName, source, operatorPos);
                        end;
                        code.removeNode(childNode);
                        currentNode.setData(source.getLexemeLineIndex(operatorPos), foundMethod.returnType, INVOKE_STATIC, foundMethod);
                    end;
                     0: begin
                        if foundMethod.isStatic() then begin
                            raise AVTCompilerException.create('The static method ' + foundMethod.simpleName + foundMethod.argumentsToString() + ' from the type ' + foundMethod.parentType.fullName + ' should be accessed in a static way', source, operatorPos);
                        end;
                        if isUseSuper or (foundMethod.visibility = AVT_PRIVATE) then begin
                            instruction := INVOKE_SPECIAL;
                        end else
                        if foundMethod.parentType.isService() then begin
                            instruction := INVOKE_SERVICE;
                        end else begin
                            instruction := INVOKE_VIRTUAL;
                        end;
                        code.moveNode(childNode, currentNode, 0);
                        currentNode.setData(source.getLexemeLineIndex(operatorPos), foundMethod.returnType, instruction, foundMethod);
                    end;
                     1: begin
                        if foundMethod.isStatic() then begin
                            code.removeNode(childNode);
                            currentNode.setData(source.getLexemeLineIndex(operatorPos), foundMethod.returnType, INVOKE_STATIC, foundMethod);
                        end else begin
                           if isUseSuper or (foundMethod.visibility = AVT_PRIVATE) then begin
                               instruction := INVOKE_SPECIAL;
                           end else
                           if foundMethod.parentType.isService() then begin
                               instruction := INVOKE_SERVICE;
                           end else begin
                               instruction := INVOKE_VIRTUAL;
                           end;
                           code.moveNode(childNode, currentNode, 0);
                           currentNode.setData(source.getLexemeLineIndex(operatorPos), foundMethod.returnType, instruction, foundMethod);
                        end;
                    end;
                    end;
                end else begin
                    raise AVTCompilerException.create(simpleName + ' can not be resolved or is not a field', source, operatorPos);
                end;
            end else
            case lexemeType of
            CHAR_PARENTH_OPENED: begin
                if not(typeReturnRef is AVTTypeStructured) then begin
                    raise AVTCompilerException.create('The operator () is not applicable for the type ' + itemToString(typeReturnRef), source, pos);
                end;
                typeDereferenceRef := AVTTypeStructured(typeReturnRef);
                inc(pos);
                currentNode := code.appendNode(parentNode);
                argumentTypes := Vector.create();
                try
                    if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then repeat
                        pos := parseExpression(currentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
                        expressionNode := currentNode.lastChild();
                        needValue(expressionNode, code);
                        argumentTypes.append(ValueOfObject.create(expressionNode.dataType, false));
                        case source.getLexemeType(pos) of
                        CHAR_COMMA: begin
                            inc(pos);
                        end;
                        CHAR_PARENTH_CLOSED: begin
                            break;
                        end
                        else
                            raise AVTCompilerException.create('")" expected', source, pos);
                        end;
                    until false;
                    foundMethod := typeDereferenceRef.findMethod(AVTOperator.operatorToSpecName(INVOKE_VIRTUAL), argumentTypes, typeRef, pos);
                    if foundMethod = nil then begin
                        raise AVTCompilerException.create('The operator () is not applicable for the type ' + typeDereferenceRef.fullName, source, operatorPos);
                    end;
                    if not foundMethod.isConvertableArgumentTypes(argumentTypes) then begin
                        raise AVTCompilerException.create('The operator ()' + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not applicable for the arguments ' + argumentTypes.toString(), source, pos);
                    end;
                finally
                    argumentTypes.free();
                end;
                if isUseSuper and not foundMethod.isVisible(typeRef, typeRef) or not isUseSuper and not foundMethod.isVisible(typeDereferenceRef, typeRef) then begin
                    raise AVTCompilerException.create('The operator ()' + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
                end;
                if isUseSuper and foundMethod.isAbstract() then begin
                    raise AVTCompilerException.create('Can not directly invoke abstract operator ()' + foundMethod.argumentsToString() + ' from the type ' + foundMethod.parentType.fullName, source, operatorPos);
                end;
                for i := foundMethod.getArgumentsCount() - 1 downto 0 do begin
                    cast(currentNode[i], code, foundMethod.getArgumentAt(i).valueType);
                end;
                if isUseSuper or (foundMethod.visibility = AVT_PRIVATE) then begin
                    instruction := INVOKE_SPECIAL;
                end else
                if foundMethod.parentType.isService() then begin
                    instruction := INVOKE_SERVICE;
                end else begin
                    instruction := INVOKE_VIRTUAL;
                end;
                code.moveNode(childNode, currentNode, 0);
                currentNode.setData(source.getLexemeLineIndex(operatorPos), foundMethod.returnType, instruction, foundMethod);
            end;
            CHAR_BRACKET_OPENED: begin
                if typeReturnRef = nil then begin
                    raise AVTCompilerException.create('The operator [] is not applicable for the type null', source, pos);
                end;
                typeIntRef := getPrimitiveType(AVT_INT);
                if typeReturnRef.isCompound() then begin
                    base := (typeReturnRef as AVTTypePrimitive).compoundBase;
                    typeElementRef := getPrimitiveType(base);
                    currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), typeElementRef, GET_VECTOR_ELEMENT, typeReturnRef);
                    code.moveNode(childNode, currentNode, 0);
                    pos := parseExpression(currentNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
                    if source.getLexemeType(pos) <> CHAR_BRACKET_CLOSED then begin
                        raise AVTCompilerException.create('"]" expected', source, pos);
                    end;
                    expressionNode := currentNode.lastChild();
                    needValue(expressionNode, code);
                    typeParsedRef := expressionNode.dataType;
                    if not typeIntRef.isConvertableFrom(typeParsedRef) then begin
                        raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeParsedRef) + ' to int', source, operatorPos);
                    end;
                    expressionNode := cast(expressionNode, code, typeIntRef);
                    if expressionNode.instruction = LOAD_CONST then begin
                        oldConstant := expressionNode.operand1 as AVTConstant;
                        i := oldConstant.value.asInt;
                        if (i < 0) or (i >= AVTTypePrimitive(typeReturnRef).compoundLength) then begin
                            raise AVTCompilerException.create('Index [' + intToString(i) + '] out of bounds', source, pos);
                        end;
                        compoundNode := currentNode.firstChild();
                        if compoundNode.instruction = LOAD_CONST then begin
                            oldConstant := compoundNode.operand1 as AVTConstant;
                            newConstant := AVTConstant.create(typeElementRef);
                            case base of
                            AVT_BYTE:
                                newConstant.value.asByte := oldConstant.value.asByte8[i];
                            AVT_SHORT:
                                newConstant.value.asShort := oldConstant.value.asShort8[i];
                            AVT_INT, AVT_FLOAT:
                                newConstant.value.asInt := oldConstant.value.asInt8[i];
                            AVT_LONG, AVT_DOUBLE:
                                newConstant.value.asLong := oldConstant.value.asLong8[i];
                            end;
                            currentNode.setData(expressionNode.lineIndex, typeElementRef, LOAD_CONST, newConstant);
                            code.removeNode(expressionNode);
                            code.removeNode(compoundNode);
                        end;
                    end;
                end else
                if typeReturnRef is AVTTypeArray then begin
                    typeElementRef := AVTTypeArray(typeReturnRef).elementType;
                    currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), typeElementRef, GET_ARRAY_ELEMENT, typeElementRef);
                    code.moveNode(childNode, currentNode, 0);
                    pos := parseExpression(currentNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
                    if source.getLexemeType(pos) <> CHAR_BRACKET_CLOSED then begin
                        raise AVTCompilerException.create('"]" expected', source, pos);
                    end;
                    expressionNode := currentNode.lastChild();
                    needValue(expressionNode, code);
                    typeParsedRef := expressionNode.dataType;
                    if not typeIntRef.isConvertableFrom(typeParsedRef) then begin
                        raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeParsedRef) + ' to int', source, pos);
                    end;
                    cast(expressionNode, code, typeIntRef);
                end else
                if typeReturnRef is AVTTypeStructured then begin
                    typeDereferenceRef := AVTTypeStructured(typeReturnRef);
                    currentNode := code.appendNode(parentNode);
                    code.moveNode(childNode, currentNode, 0);
                    pos := parseExpression(currentNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
                    if source.getLexemeType(pos) <> CHAR_BRACKET_CLOSED then begin
                        raise AVTCompilerException.create('"]" expected', source, pos);
                    end;
                    isWriteOnly := false;
                    expressionNode := currentNode.lastChild();
                    needValue(expressionNode, code);
                    typeParsedRef := expressionNode.dataType;
                    argumentTypes := Vector.create();
                    try
                        argumentTypes.append(ValueOfObject.create(typeParsedRef, false));
                        foundMethod := typeDereferenceRef.findMethod(AVTOperator.operatorToSpecName(GET_ARRAY_ELEMENT), argumentTypes, typeRef, pos);
                        if foundMethod = nil then begin
                            foundMethod := typeDereferenceRef.findMethod(AVTOperator.operatorToSpecName(SET_ARRAY_ELEMENT), nil, typeRef, pos);
                            if foundMethod = nil then begin
                                raise AVTCompilerException.create('The operator [] is not applicable for the type ' + typeDereferenceRef.fullName, source, operatorPos);
                            end;
                            if source.getLexemeType(pos + 1) <> CHAR_EQUALS then begin
                                raise AVTCompilerException.create('The operator [] is undefined in the type ' + foundMethod.parentType.fullName, source, operatorPos);
                            end;
                            currentNode.setData(source.getLexemeLineIndex(pos + 1), foundMethod.returnType, INVOKE_VIRTUAL, foundMethod);
                            isWriteOnly := true;
                        end else
                        if not foundMethod.isConvertableArgumentTypes(argumentTypes) then begin
                            raise AVTCompilerException.create('The operator []' + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not applicable for the arguments ' + argumentTypes.toString(), source, pos);
                        end;
                    finally
                        argumentTypes.free();
                    end;
                    if not isWriteOnly then begin
                        if isUseSuper and not foundMethod.isVisible(typeRef, typeRef) or not isUseSuper and not foundMethod.isVisible(typeDereferenceRef, typeRef) then begin
                            raise AVTCompilerException.create('The operator []' + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
                        end;
                        if isUseSuper and foundMethod.isAbstract() then begin
                            raise AVTCompilerException.create('Can not directly invoke abstract operator []' + foundMethod.argumentsToString() + ' from the type ' + foundMethod.parentType.fullName, source, operatorPos);
                        end;
                        for i := foundMethod.getArgumentsCount() - 1 downto 0 do begin
                            cast(currentNode[i + 1], code, foundMethod.getArgumentAt(i).valueType);
                        end;
                        if isUseSuper or (foundMethod.visibility = AVT_PRIVATE) then begin
                            instruction := INVOKE_SPECIAL;
                        end else
                        if foundMethod.parentType.isService() then begin
                            instruction := INVOKE_SERVICE;
                        end else begin
                            instruction := INVOKE_VIRTUAL;
                        end;
                        currentNode.setData(source.getLexemeLineIndex(operatorPos), foundMethod.returnType, instruction, foundMethod);
                    end;
                end else begin
                    raise AVTCompilerException.create('The operator [] is not applicable for the type ' + itemToString(typeReturnRef), source, pos);
                end;
            end;
            OPER_INCREMENT, OPER_DECREMENT: begin
                typeVoidRef := getPrimitiveType(AVT_VOID);
                instruction := childNode.instruction;
                lineIndex := childNode.lineIndex;
                case instruction of
                LOAD_VARIABLE: begin
                    typeParsedRef := (childNode.operand1 as AVTVariable).valueType;
                    if not typeParsedRef.isNumeric() then begin
                        if lexemeType = OPER_INCREMENT then begin
                            raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
                        end else begin
                            raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
                        end;
                    end;
                    if lexemeType = OPER_INCREMENT then begin
                        childNode.instruction := OPER_INC_POST;
                    end else begin
                        childNode.instruction := OPER_DEC_POST;
                    end;
                end;
                LOAD_STATIC: begin
                    foundField := childNode.operand1 as AVTField;
                    if foundField.isFinal() then begin
                        raise AVTCompilerException.create('The final field ' + foundField.fullName + ' can not be assigned', source, pos);
                    end;
                    typeParsedRef := foundField.valueType;
                    if not typeParsedRef.isNumeric() then begin
                        if lexemeType = OPER_INCREMENT then begin
                            raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
                        end else begin
                            raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
                        end;
                    end;
                    code.appendNode(childNode).setData(lineIndex, typeParsedRef, LOAD_STATIC, foundField);
                    currentNode := insertIncrementCode(childNode, code, typeParsedRef as AVTTypePrimitive, lexemeType = OPER_INCREMENT, lineIndex);
                    code.insertNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
                    childNode.instruction := STORE_STATIC;
                end;
                GET_FIELD: begin
                    foundField := childNode.operand1 as AVTField;
                    if foundField.isFinal() then begin
                        raise AVTCompilerException.create('The final field ' + foundField.fullName + ' can not be assigned', source, pos);
                    end;
                    typeParsedRef := foundField.valueType;
                    if not typeParsedRef.isNumeric() then begin
                        if lexemeType = OPER_INCREMENT then begin
                            raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
                        end else begin
                            raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
                        end;
                    end;
                    currentNode := code.appendNode(childNode, lineIndex, typeParsedRef, GET_FIELD, foundField);
                    code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
                    currentNode := insertIncrementCode(childNode, code, typeParsedRef as AVTTypePrimitive, lexemeType = OPER_INCREMENT, lineIndex);
                    code.insertNode(currentNode).setData(lineIndex, typeVoidRef, DUP1X1);
                    childNode.instruction := SET_FIELD;
                end;
                GET_PROPERTY: begin
                    foundProperty := childNode.operand1 as AVTProperty;
                    if foundProperty.writeSynthetic = nil then begin
                        raise AVTCompilerException.create('The read-only property ' + foundProperty.simpleName + ' can not be assigned', source, pos);
                    end;
                    typeParsedRef := foundProperty.valueType;
                    if not typeParsedRef.isNumeric() then begin
                        if lexemeType = OPER_INCREMENT then begin
                            raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
                        end else begin
                            raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
                        end;
                    end;
                    currentNode := code.appendNode(childNode, lineIndex, typeParsedRef, GET_PROPERTY, foundProperty);
                    code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
                    currentNode := insertIncrementCode(childNode, code, typeParsedRef as AVTTypePrimitive, lexemeType = OPER_INCREMENT, lineIndex);
                    code.insertNode(currentNode).setData(lineIndex, typeVoidRef, DUP1X1);
                    childNode.instruction := SET_PROPERTY;
                end;
                GET_ARRAY_ELEMENT: begin
                    typeParsedRef := childNode.operand1 as AVTType;
                    if not typeParsedRef.isNumeric() then begin
                        if lexemeType = OPER_INCREMENT then begin
                            raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
                        end else begin
                            raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
                        end;
                    end;
                    currentNode := code.appendNode(childNode, lineIndex, typeParsedRef, GET_ARRAY_ELEMENT, typeParsedRef);
                    code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP2);
                    currentNode := insertIncrementCode(childNode, code, typeParsedRef as AVTTypePrimitive, lexemeType = OPER_INCREMENT, lineIndex);
                    code.insertNode(currentNode).setData(lineIndex, typeVoidRef, DUP1X2);
                    childNode.instruction := SET_ARRAY_ELEMENT;
                end;
                INVOKE_SPECIAL, INVOKE_VIRTUAL, INVOKE_SERVICE: begin
                    operand := childNode.operand1;
                    if (operand is AVTOperator) and (AVTOperator(operand).operatorKind = GET_ARRAY_ELEMENT) then begin
                        typeParsedRef := AVTMethod(operand).returnType;
                        if not typeParsedRef.isNumeric() then begin
                            if lexemeType = OPER_INCREMENT then begin
                                raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
                            end else begin
                                raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
                            end;
                        end;
                        typeDereferenceRef := childNode[0].dataType as AVTTypeStructured;
                        argumentTypes := Vector.create();
                        try
                            argumentTypes.append(ValueOfObject.create(AVTMethod(operand).getArgumentAt(0).valueType, false));
                            argumentTypes.append(ValueOfObject.create(typeParsedRef, false));
                            foundMethod := typeDereferenceRef.findMethod(AVTOperator.operatorToSpecName(SET_ARRAY_ELEMENT), argumentTypes, typeRef, pos);
                            if (foundMethod = nil) or not foundMethod.isIdentityArgumentTypes(argumentTypes) then begin
                                raise AVTCompilerException.create('The operator []=' + argumentTypes.toString() + ' is undefined for the type ' + typeDereferenceRef.fullName, source, pos);
                            end;
                        finally
                            argumentTypes.free();
                        end;
                        if isUseSuper and not foundMethod.isVisible(typeRef, typeRef) or not isUseSuper and not foundMethod.isVisible(typeDereferenceRef, typeRef) then begin
                            raise AVTCompilerException.create('The operator []=' + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
                        end;
                        currentNode := code.appendNode(childNode, lineIndex, typeParsedRef, instruction, operand);
                        code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP2);
                        currentNode := insertIncrementCode(childNode, code, typeParsedRef as AVTTypePrimitive, lexemeType = OPER_INCREMENT, lineIndex);
                        code.insertNode(currentNode).setData(lineIndex, typeVoidRef, DUP1X2);
                        if (instruction <> INVOKE_SPECIAL) or foundMethod.isAbstract() then begin
                            if foundMethod.parentType.isService() then begin
                                instruction := INVOKE_SERVICE;
                            end else begin
                                instruction := INVOKE_VIRTUAL;
                            end;
                        end;
                        childNode.setData(lineIndex, typeParsedRef, instruction, foundMethod);
                    end else begin
                        foundProperty := (operand as AVTMethod).linkedProperty;
                        if (foundProperty = nil) or (foundProperty.readSynthetic <> operand) then begin
                            raise AVTCompilerException.create('The operator ++/-- applicable only to variables, properties and array elements', source, pos);
                        end;
                        typeParsedRef := foundProperty.valueType;
                        if not typeParsedRef.isNumeric() then begin
                            if lexemeType = OPER_INCREMENT then begin
                                raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
                            end else begin
                                raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
                            end;
                        end;
                        foundMethod := foundProperty.writeSynthetic;
                        if foundMethod = nil then begin
                            raise AVTCompilerException.create('The read-only property ' + foundProperty.simpleName + ' can not be assigned', source, pos);
                        end;
                        currentNode := code.appendNode(childNode, lineIndex, typeParsedRef, instruction, operand);
                        code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
                        currentNode := insertIncrementCode(childNode, code, typeParsedRef as AVTTypePrimitive, lexemeType = OPER_INCREMENT, lineIndex);
                        code.insertNode(currentNode).setData(lineIndex, typeVoidRef, DUP1X1);
                        childNode.operand1 := foundMethod;
                    end;
                end
                else
                    raise AVTCompilerException.create('The operator ++/-- applicable only to variables, properties and array elements', source, pos);
                end;
            end
            else
                break;
            end;
            isImplicitPeriod := false;
            isUseSuper := false;
            inc(pos);
        until false;
        result := pos;
    end;

    function AVTCodeBuilder.parsePrimary(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
    var
        isConstant: boolean;
        isUseSuper: boolean;
        isImplicitPeriod: boolean;
        i: int;
        kind: int;
        index: int;
        lineIndex: int;
        dimensions: int;
        lexemeType: int;
        operatorPos: int;
        simpleName: AnsiString;
        argumentTypes: Vector;
        constant: AVTConstant;
        variable: AVTVariable;
        typeResultRef: AVTType;
        typeParsedRef: AVTType;
        typeElementRef: AVTType;
        typeIntRef: AVTTypePrimitive;
        typeVoidRef: AVTTypePrimitive;
        typeStructuredRef: AVTTypeStructured;
        typeIntArray1dRef: AVTTypeArray;
        arrayNode: AVTNode;
        valueNode: AVTNode;
        childNode: AVTNode;
        currentNode: AVTNode;
        expressionNode: AVTNode;
        foundMethod: AVTMethod;
        foundMember: AVTMember;
        foundItem: AVTItem;
        app: AVTProgramme;
    begin
        isUseSuper := false;
        isImplicitPeriod := false;
        lexemeType := source.getLexemeType(pos);
        case lexemeType of
        AVT_SUPER: begin
            if ignoreInstanceMembers then begin
                raise AVTCompilerException.create('Can not refer to "this" nor "super" while explicitly invoking a constructor', source, pos);
            end;
            if methodRef.isStatic() then begin
                raise AVTCompilerException.create('Can not use "super" in static context', source, pos);
            end;
            typeResultRef := typeRef.extends();
            if typeResultRef = nil then begin
                raise AVTCompilerException.create('super can not be used in ' + itemToString(typeRef), source, pos);
            end;
            variable := methodRef.argumentThis;
            code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_VARIABLE, variable);
            isUseSuper := true;
            inc(pos);
        end;
        AVT_THIS: begin
            if ignoreInstanceMembers then begin
                raise AVTCompilerException.create('Can not refer to "this" nor "super" while explicitly invoking a constructor', source, pos);
            end;
            if methodRef.isStatic() then begin
                raise AVTCompilerException.create('Can not use "this" in static context', source, pos);
            end;
            variable := methodRef.argumentThis;
            typeResultRef := variable.valueType;
            code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_VARIABLE, variable);
            inc(pos);
        end;
        AVT_NEW: begin
            typeResultRef := parseType(parentNode, methodRef, typeRef, source, pos + 1);
            operatorPos := source.position;
            typeVoidRef := getPrimitiveType(AVT_VOID);
            if typeResultRef.isArray() then begin
                if source.getLexemeType(operatorPos) <> CHAR_CURLY_OPENED then begin
                    raise AVTCompilerException.create('"{" expected', source, operatorPos);
                end;
                inc(operatorPos);
                with typeResultRef as AVTTypeArray do begin
                    typeElementRef := elementType;
                    makeCompilable();
                end;
                childNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), typeResultRef, NEW_ARRAY_BY_ELEMENTS, typeResultRef, nil);
                index := 0;
                if source.getLexemeType(operatorPos) <> CHAR_CURLY_CLOSED then repeat
                    lineIndex := source.getLexemeLineIndex(operatorPos);
                    constant := AVTConstant.create(getPrimitiveTypeForIntValue(index));
                    constant.value.asInt := index;
                    currentNode := code.appendNode(childNode);
                    currentNode.setData(lineIndex, typeVoidRef, SET_ARRAY_ELEMENT, typeElementRef);
                    code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
                    code.appendNode(currentNode).setData(lineIndex, constant.valueType, LOAD_CONST, constant);
                    operatorPos := parseExpression(currentNode, code, methodRef, typeRef, source, operatorPos, ignoreInstanceMembers);
                    expressionNode := currentNode.lastChild();
                    needValue(expressionNode, code);
                    typeParsedRef := expressionNode.dataType;
                    if not typeElementRef.isConvertableFrom(typeParsedRef) then begin
                        raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeParsedRef) + ' to ' + itemToString(typeElementRef), source, operatorPos);
                    end;
                    cast(expressionNode, code, typeElementRef);
                    case source.getLexemeType(operatorPos) of
                    CHAR_COMMA: begin
                        inc(operatorPos);
                    end;
                    CHAR_CURLY_CLOSED: begin
                        break;
                    end
                    else
                        raise AVTCompilerException.create('"}" expected', source, operatorPos);
                    end;
                    inc(index);
                until false;
                index := childNode.length;
                constant := AVTConstant.create(getPrimitiveTypeForIntValue(index));
                constant.value.asInt := index;
                childNode.operand2 := constant;
                repeat
                    dec(index);
                    currentNode := childNode[index];
                    expressionNode := currentNode.lastChild();
                    if (expressionNode.instruction = LOAD_CONST) and (expressionNode.operand1 as AVTConstant).isDefaultValue() then begin
                        for i := currentNode.length - 1 downto 0 do begin
                            code.removeNode(currentNode[i]);
                        end;
                        code.removeNode(currentNode);
                    end;
                until index = 0;
            end else
            if source.getLexemeType(operatorPos) = CHAR_BRACKET_OPENED then begin
                if typeResultRef.isVoid() then begin
                    raise AVTCompilerException.create('The type void is an invalid type for array elements', source, operatorPos);
                end;
                index := 0;
                app := programme;
                typeIntRef := getPrimitiveType(AVT_INT);
                childNode := code.appendNode(parentNode);
                repeat
                    inc(index);
                    typeResultRef := app.getArrayOf(typeResultRef);
                    operatorPos := parseExpression(childNode, code, methodRef, typeRef, source, operatorPos + 1, ignoreInstanceMembers);
                    if source.getLexemeType(operatorPos) <> CHAR_BRACKET_CLOSED then begin
                        raise AVTCompilerException.create('"]" expected', source, operatorPos);
                    end;
                    expressionNode := childNode.lastChild();
                    needValue(expressionNode, code);
                    typeParsedRef := expressionNode.dataType;
                    if not typeIntRef.isConvertableFrom(typeParsedRef) then begin
                        raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeParsedRef) + ' to int', source, operatorPos);
                    end;
                    cast(expressionNode, code, typeIntRef);
                    inc(operatorPos);
                until (index >= 99) or (source.getLexemeType(operatorPos) <> CHAR_BRACKET_OPENED) or (source.getLexemeType(operatorPos + 1) = CHAR_BRACKET_CLOSED);
                dimensions := index;
                while (dimensions < 99) and (source.getLexemeType(operatorPos) = CHAR_BRACKET_OPENED) and (source.getLexemeType(operatorPos + 1) = CHAR_BRACKET_CLOSED) do begin
                    typeResultRef := app.getArrayOf(typeResultRef);
                    inc(operatorPos, 2);
                    inc(dimensions);
                end;
                (typeResultRef as AVTTypeArray).makeCompilable();
                lineIndex := source.getLexemeLineIndex(pos);
                if index = 1 then begin
                    childNode.setData(lineIndex, typeResultRef, NEW_ARRAY_BY_LENGTH, typeResultRef);
                end else begin
                    childNode.setData(lineIndex, typeResultRef, NEW_MULTI_ARRAY, typeResultRef);
                    typeIntArray1dRef := app.getArrayOf(typeIntRef);
                    typeIntArray1dRef.makeCompilable();
                    constant := AVTConstant.create(getPrimitiveTypeForIntValue(index));
                    constant.value.asInt := index;
                    arrayNode := code.appendNode(childNode, lineIndex, typeIntArray1dRef, NEW_ARRAY_BY_ELEMENTS, typeIntArray1dRef, constant);
                    for i := index - 1 downto 0 do begin
                        valueNode := childNode[i];
                        currentNode := code.insertNode(arrayNode, 0, lineIndex, typeVoidRef, SET_ARRAY_ELEMENT, typeIntRef);
                        code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
                        constant := AVTConstant.create(typeIntRef);
                        constant.value.asInt := i;
                        code.appendNode(currentNode).setData(lineIndex, typeIntRef, LOAD_CONST, constant);
                        code.moveNode(valueNode, currentNode, 2);
                    end;
                end;
                dec(operatorPos);
            end else
            if typeResultRef.isCompound() then begin
                if source.getLexemeType(operatorPos) <> CHAR_CURLY_OPENED then begin
                    raise AVTCompilerException.create('"{" expected', source, operatorPos);
                end;
                inc(operatorPos);
                with typeResultRef as AVTTypePrimitive do begin
                    index := compoundLength - 1;
                    kind := compoundBase;
                end;
                isConstant := true;
                typeElementRef := getPrimitiveType(kind);
                childNode := code.appendNode(parentNode);
                childNode.setData(source.getLexemeLineIndex(pos), typeResultRef, NEW_VECTOR, typeResultRef);
                for i := 0 to index do begin
                    operatorPos := parseExpression(childNode, code, methodRef, typeRef, source, operatorPos, ignoreInstanceMembers);
                    expressionNode := childNode.lastChild();
                    needValue(expressionNode, code);
                    typeParsedRef := expressionNode.dataType;
                    if not typeElementRef.isConvertableFrom(typeParsedRef) then begin
                        raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeParsedRef) + ' to ' + itemToString(typeElementRef), source, operatorPos);
                    end;
                    expressionNode := cast(expressionNode, code, typeElementRef);
                    isConstant := isConstant and (expressionNode.instruction = LOAD_CONST);
                    if i < index then begin
                        if source.getLexemeType(operatorPos) <> CHAR_COMMA then begin
                            raise AVTCompilerException.create('"," expected', source, operatorPos);
                        end;
                        inc(operatorPos);
                    end;
                end;
                if source.getLexemeType(operatorPos) <> CHAR_CURLY_CLOSED then begin
                    raise AVTCompilerException.create('"}" expected', source, operatorPos);
                end;
                if isConstant then begin
                    constant := AVTConstant.create(typeResultRef);
                    for i := index downto 0 do begin
                        currentNode := childNode[i];
                        case kind of
                        AVT_BYTE:
                            constant.value.asByte8[i] := (currentNode.operand1 as AVTConstant).value.asByte;
                        AVT_SHORT:
                            constant.value.asShort8[i] := (currentNode.operand1 as AVTConstant).value.asShort;
                        AVT_INT, AVT_FLOAT:
                            constant.value.asInt8[i] := (currentNode.operand1 as AVTConstant).value.asInt;
                        AVT_LONG, AVT_DOUBLE:
                            constant.value.asLong8[i] := (currentNode.operand1 as AVTConstant).value.asLong;
                        end;
                        code.removeNode(currentNode);
                    end;
                    childNode.setData(childNode.lineIndex, childNode.dataType, LOAD_CONST, constant);
                end;
            end else
            if typeResultRef.isAbstract() then begin
                raise AVTCompilerException.create('Can not instantiate abstract type ' + typeResultRef.fullName, source, pos + 1);
            end else
            if typeResultRef.isStruct() then begin
                typeStructuredRef := typeResultRef as AVTTypeStructured;
                if source.getLexemeType(operatorPos) <> CHAR_PARENTH_OPENED then begin
                    raise AVTCompilerException.create('"(" expected', source, operatorPos);
                end;
                inc(operatorPos);
                lineIndex := source.getLexemeLineIndex(pos);
                childNode := code.appendNode(parentNode);
                childNode.setData(lineIndex, typeStructuredRef, NEW_STRUCT, typeStructuredRef);
                currentNode := code.appendNode(childNode);
                code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
                argumentTypes := Vector.create();
                try
                    if source.getLexemeType(operatorPos) <> CHAR_PARENTH_CLOSED then repeat
                        operatorPos := parseExpression(currentNode, code, methodRef, typeRef, source, operatorPos, ignoreInstanceMembers);
                        expressionNode := currentNode.lastChild();
                        needValue(expressionNode, code);
                        argumentTypes.append(ValueOfObject.create(expressionNode.dataType, false));
                        case source.getLexemeType(operatorPos) of
                        CHAR_COMMA: begin
                            inc(operatorPos);
                        end;
                        CHAR_PARENTH_CLOSED: begin
                            break;
                        end
                        else
                            raise AVTCompilerException.create('")" expected', source, operatorPos);
                        end;
                    until false;
                    foundMethod := getStructType().findMethod(SPECNAME_INST_INIT, argumentTypes, typeRef, operatorPos);
                    if not foundMethod.isConvertableArgumentTypes(argumentTypes) then begin
                        raise AVTCompilerException.create('The constructor ' + foundMethod.parentType.simpleName + foundMethod.argumentsToString() + ' is not applicable for the arguments ' + argumentTypes.toString(), source, operatorPos);
                    end;
                finally
                    argumentTypes.free();
                end;
                if not foundMethod.isVisible(typeStructuredRef, typeRef) then begin
                    raise AVTCompilerException.create('The constructor ' + foundMethod.parentType.simpleName + foundMethod.argumentsToString() + ' is not visible', source, operatorPos);
                end;
                index := 0;
                for i := 1 to currentNode.length - 1 do begin
                    cast(currentNode[i], code, foundMethod.getArgumentAt(index).valueType);
                    inc(index);
                end;
                currentNode.setData(lineIndex, foundMethod.returnType, INVOKE_SPECIAL, foundMethod);
                insertAfterConstructionInvoke(childNode, code, pos, lineIndex);
            end else
            if typeResultRef.isService() then begin
                typeStructuredRef := typeResultRef as AVTTypeStructured;
                if source.getLexemeType(operatorPos) <> CHAR_PARENTH_OPENED then begin
                    raise AVTCompilerException.create('"(" expected', source, operatorPos);
                end;
                inc(operatorPos);
                lineIndex := source.getLexemeLineIndex(pos);
                childNode := code.appendNode(parentNode);
                childNode.setData(lineIndex, typeStructuredRef, NEW_SERVICE, typeStructuredRef);
                currentNode := code.appendNode(childNode);
                code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
                argumentTypes := Vector.create();
                try
                    if source.getLexemeType(operatorPos) <> CHAR_PARENTH_CLOSED then repeat
                        operatorPos := parseExpression(currentNode, code, methodRef, typeRef, source, operatorPos, ignoreInstanceMembers);
                        expressionNode := currentNode.lastChild();
                        needValue(expressionNode, code);
                        argumentTypes.append(ValueOfObject.create(expressionNode.dataType, false));
                        case source.getLexemeType(operatorPos) of
                        CHAR_COMMA: begin
                            inc(operatorPos);
                        end;
                        CHAR_PARENTH_CLOSED: begin
                            break;
                        end
                        else
                            raise AVTCompilerException.create('")" expected', source, operatorPos);
                        end;
                    until false;
                    foundMethod := typeStructuredRef.extends().findMethod(SPECNAME_INST_INIT, argumentTypes, typeRef, operatorPos);
                    if not foundMethod.isConvertableArgumentTypes(argumentTypes) then begin
                        raise AVTCompilerException.create('The constructor ' + foundMethod.parentType.simpleName + foundMethod.argumentsToString() + ' is not applicable for the arguments ' + argumentTypes.toString(), source, operatorPos);
                    end;
                finally
                    argumentTypes.free();
                end;
                if not foundMethod.isVisible(typeStructuredRef, typeRef) then begin
                    raise AVTCompilerException.create('The constructor ' + foundMethod.parentType.simpleName + foundMethod.argumentsToString() + ' is not visible', source, operatorPos);
                end;
                index := 0;
                for i := 1 to currentNode.length - 1 do begin
                    cast(currentNode[i], code, foundMethod.getArgumentAt(index).valueType);
                    inc(index);
                end;
                currentNode.setData(lineIndex, foundMethod.returnType, INVOKE_SPECIAL, foundMethod);
                insertAfterConstructionInvoke(childNode, code, pos, lineIndex);
            end else
            if typeResultRef.isClass() then begin
                typeStructuredRef := typeResultRef as AVTTypeStructured;
                if source.getLexemeType(operatorPos) <> CHAR_PARENTH_OPENED then begin
                    raise AVTCompilerException.create('"(" expected', source, operatorPos);
                end;
                inc(operatorPos);
                lineIndex := source.getLexemeLineIndex(pos);
                childNode := code.appendNode(parentNode);
                childNode.setData(lineIndex, typeStructuredRef, NEW_CLASS, typeStructuredRef);
                currentNode := code.appendNode(childNode);
                code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
                argumentTypes := Vector.create();
                try
                    if source.getLexemeType(operatorPos) <> CHAR_PARENTH_CLOSED then repeat
                        operatorPos := parseExpression(currentNode, code, methodRef, typeRef, source, operatorPos, ignoreInstanceMembers);
                        expressionNode := currentNode.lastChild();
                        needValue(expressionNode, code);
                        argumentTypes.append(ValueOfObject.create(expressionNode.dataType, false));
                        case source.getLexemeType(operatorPos) of
                        CHAR_COMMA: begin
                            inc(operatorPos);
                        end;
                        CHAR_PARENTH_CLOSED: begin
                            break;
                        end
                        else
                            raise AVTCompilerException.create('")" expected', source, operatorPos);
                        end;
                    until false;
                    foundMethod := typeStructuredRef.findMethod(SPECNAME_INST_INIT, argumentTypes, typeRef, operatorPos);
                    if not foundMethod.isConvertableArgumentTypes(argumentTypes) then begin
                        raise AVTCompilerException.create('The constructor ' + foundMethod.parentType.simpleName + foundMethod.argumentsToString() + ' is not applicable for the arguments ' + argumentTypes.toString(), source, operatorPos);
                    end;
                finally
                    argumentTypes.free();
                end;
                if not foundMethod.isVisible(typeStructuredRef, typeRef) then begin
                    raise AVTCompilerException.create('The constructor ' + foundMethod.parentType.simpleName + foundMethod.argumentsToString() + ' is not visible', source, operatorPos);
                end;
                index := 0;
                for i := 1 to currentNode.length - 1 do begin
                    cast(currentNode[i], code, foundMethod.getArgumentAt(index).valueType);
                    inc(index);
                end;
                currentNode.setData(lineIndex, foundMethod.returnType, INVOKE_SPECIAL, foundMethod);
                insertAfterConstructionInvoke(childNode, code, pos, lineIndex);
            end else begin
                raise AVTCompilerException.create('Can not instantiate the type ' + typeResultRef.fullName, source, pos + 1);
            end;
            if (typeResultRef.classType() = AVTTypeStructured) and (source.getLexemeType(operatorPos + 1) = CHAR_CURLY_OPENED) then begin
                typeStructuredRef := AVTTypeStructured(typeResultRef);
                inc(operatorPos, 2);
                if source.getLexemeType(operatorPos) <> CHAR_CURLY_CLOSED then repeat
                    if source.getLexemeType(operatorPos) <> LITR_NAME then begin
                        raise AVTCompilerException.create('Field name expected', source, operatorPos);
                    end;
                    lineIndex := source.getLexemeLineIndex(operatorPos);
                    simpleName := source.getLexemeAnsiString(operatorPos);
                    foundMember := resolveMember(typeStructuredRef, simpleName, typeRef, operatorPos);
                    if foundMember is AVTField then begin
                        if foundMember.isStatic() or foundMember.isFinal() then begin
                            raise AVTCompilerException.create(simpleName + ' must be a non-static and non-final field', source, operatorPos);
                        end;
                        typeElementRef := AVTField(foundMember).valueType;
                        currentNode := code.appendNode(childNode);
                        currentNode.setData(lineIndex, typeVoidRef, SET_FIELD, foundMember);
                    end else
                    if foundMember is AVTProperty then begin
                        if AVTProperty(foundMember).writeSynthetic = nil then begin
                            raise AVTCompilerException.create(simpleName + ' must be a writable property', source, operatorPos);
                        end;
                        typeElementRef := AVTProperty(foundMember).valueType;
                        currentNode := code.appendNode(childNode);
                        currentNode.setData(lineIndex, typeVoidRef, SET_PROPERTY, foundMember);
                    end else begin
                        raise AVTCompilerException.create(simpleName + ' can not be resolved or is not a field', source, operatorPos);
                    end;
                    code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
                    inc(operatorPos);
                    if source.getLexemeType(operatorPos) <> CHAR_EQUALS then begin
                        raise AVTCompilerException.create('"=" expected', source, operatorPos);
                    end;
                    operatorPos := parseExpression(currentNode, code, methodRef, typeRef, source, operatorPos + 1, ignoreInstanceMembers);
                    expressionNode := currentNode.lastChild();
                    needValue(expressionNode, code);
                    typeParsedRef := expressionNode.dataType;
                    if not typeElementRef.isConvertableFrom(typeParsedRef) then begin
                        raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeParsedRef) + ' to ' + itemToString(typeElementRef), source, operatorPos);
                    end;
                    cast(expressionNode, code, typeElementRef);
                    case source.getLexemeType(operatorPos) of
                    CHAR_COMMA: begin
                        inc(operatorPos);
                    end;
                    CHAR_CURLY_CLOSED: begin
                        break;
                    end
                    else
                        raise AVTCompilerException.create('"}" expected', source, operatorPos);
                    end;
                until false;
            end;
            pos := operatorPos + 1;
        end;
        AVT_NULL: begin
            constant := AVTConstant.create(nil);
            constant.value.isNull := true;
            code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), nil, LOAD_CONST, constant);
            inc(pos);
        end;
        CHAR_PARENTH_OPENED: begin
            pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
            if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then begin
                raise AVTCompilerException.create('")" expected', source, pos);
            end;
            needValue(parentNode.lastChild(), code);
            inc(pos);
        end;
        LITR_NAME, AVT_VOID..AVT_DOUBLE8: begin
            if lexemeType <> LITR_NAME then begin
                foundItem := parseType(typeRef, pos);
                operatorPos := source.position;
            end else begin
                simpleName := source.getLexemeAnsiString(pos);
                foundItem := resolveName(simpleName, parentNode, methodRef, typeRef, pos);
                if foundItem = nil then begin
                    raise AVTCompilerException.create(simpleName + ' can not be resolved to a variable', source, pos);
                end;
                if (foundItem is AVTPackage) or (foundItem is AVTType) then begin
                    foundItem := parseType(typeRef, pos);
                    operatorPos := source.position;
                end else begin
                    operatorPos := pos + 1;
                end;
            end;
            if foundItem is AVTVariable then begin
                typeResultRef := AVTVariable(foundItem).valueType;
                code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_VARIABLE, foundItem);
                pos := operatorPos;
            end else
            if foundItem is AVTTypePrimitive then begin
                if source.getLexemeType(operatorPos) <> CHAR_PERIOD then begin
                    raise AVTCompilerException.create('"." expected', source, operatorPos);
                end;
                inc(operatorPos);
                if source.getLexemeType(operatorPos) <> AVT_CLASS then begin
                    raise AVTCompilerException.create('"class" expected', source, operatorPos);
                end;
                typeResultRef := getClassType();
                constant := AVTConstant.create(typeResultRef);
                constant.value.asClass := AVTTypePrimitive(foundItem);
                code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
                pos := operatorPos + 1;
            end else
            if foundItem is AVTTypeStructured then begin
                if source.getLexemeType(operatorPos) <> CHAR_PERIOD then begin
                    raise AVTCompilerException.create('"." expected', source, operatorPos);
                end;
                inc(operatorPos);
                case source.getLexemeType(operatorPos) of
                AVT_CLASS: begin
                    if foundItem is AVTTypeArray then begin
                        AVTTypeArray(foundItem).makeCompilable();
                    end;
                    typeResultRef := getClassType();
                    constant := AVTConstant.create(typeResultRef);
                    constant.value.asClass := AVTTypeStructured(foundItem);
                    code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
                    pos := operatorPos + 1;
                end;
                AVT_SUPER: begin
                    if ignoreInstanceMembers then begin
                        raise AVTCompilerException.create('Can not refer to "this" nor "super" while explicitly invoking a constructor', source, operatorPos);
                    end;
                    if methodRef.isStatic() then begin
                        raise AVTCompilerException.create('Can not use "super" in static context', source, operatorPos);
                    end;
                    typeStructuredRef := AVTTypeStructured(foundItem);
                    if typeRef.getImplements(typeStructuredRef) = nil then begin
                        raise AVTCompilerException.create('The type ' + itemToString(typeStructuredRef) + ' is not a supertype for ' + typeRef.simpleName, source, operatorPos);
                    end;
                    variable := methodRef.argumentThis;
                    code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeStructuredRef, LOAD_VARIABLE, variable);
                    isUseSuper := true;
                    pos := operatorPos + 1;
                end;
                LITR_NAME: begin
                    code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), nil, AVT_CLASS, foundItem);
                    pos := operatorPos - 1;
                end
                else
                    raise AVTCompilerException.create('Name of a static member expected', source, operatorPos);
                end;
            end else
            if foundItem is AVTMember then begin
                variable := fldResolvedVariable;
                if variable = nil then begin
                    code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), nil, AVT_CLASS, typeRef);
                end else begin
                    if ignoreInstanceMembers and (variable = methodRef.argumentThis) then begin
                        raise AVTCompilerException.create('Can not refer to "this" nor "super" while explicitly invoking a constructor', source, operatorPos);
                    end;
                    code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), variable.valueType, LOAD_VARIABLE, variable);
                end;
                isImplicitPeriod := true;
            end else begin
                raise AVTCompilerException.create(foundItem.simpleName + ' can not be resolved to a variable', source, operatorPos);
            end;
        end;
        AVT_OPERATOR: begin
            kind := parseOperator(source, pos + 1);
            foundItem := resolveName(AVTOperator.operatorToSpecName(kind), parentNode, methodRef, typeRef, pos);
            if foundItem = nil then begin
                raise AVTCompilerException.create('Operator ' + AVTOperator.operatorToChar(kind) + ' can not be resolved to an operator', source, pos);
            end;
            variable := fldResolvedVariable;
            if variable = nil then begin
                code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), nil, AVT_CLASS, typeRef);
            end else begin
                if ignoreInstanceMembers and (variable = methodRef.argumentThis) then begin
                    raise AVTCompilerException.create('Can not refer to "this" nor "super" while explicitly invoking a constructor', source, operatorPos);
                end;
                code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), variable.valueType, LOAD_VARIABLE, variable);
            end;
            isImplicitPeriod := true;
        end;
        LITR_STRING: begin
            typeResultRef := getStringType();
            constant := AVTConstant.create(typeResultRef);
            constant.value.asString := source.getLexemeUnicodeString(pos);
            code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
            inc(pos);
        end;
        LITR_BOOLEAN: begin
            typeResultRef := getPrimitiveType(AVT_BOOLEAN);
            constant := AVTConstant.create(typeResultRef);
            constant.value.asBoolean := source.getLexemeBoolean(pos);
            code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
            inc(pos);
        end;
        LITR_CHAR: begin
            typeResultRef := getPrimitiveType(AVT_CHAR);
            constant := AVTConstant.create(typeResultRef);
            constant.value.asChar := source.getLexemeChar(pos);
            code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
            inc(pos);
        end;
        LITR_REAL: begin
            typeResultRef := getPrimitiveType(AVT_REAL);
            constant := AVTConstant.create(typeResultRef);
            constant.value.asReal := source.getLexemeReal(pos);
            code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
            inc(pos);
        end;
        LITR_BYTE: begin
            typeResultRef := getPrimitiveType(AVT_BYTE);
            constant := AVTConstant.create(typeResultRef);
            constant.value.asByte := source.getLexemeByte(pos);
            code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
            inc(pos);
        end;
        LITR_SHORT: begin
            typeResultRef := getPrimitiveType(AVT_SHORT);
            constant := AVTConstant.create(typeResultRef);
            constant.value.asShort := source.getLexemeShort(pos);
            code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
            inc(pos);
        end;
        LITR_INT: begin
            typeResultRef := getPrimitiveType(AVT_INT);
            constant := AVTConstant.create(typeResultRef);
            constant.value.asInt := source.getLexemeInt(pos);
            code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
            inc(pos);
        end;
        LITR_LONG: begin
            typeResultRef := getPrimitiveType(AVT_LONG);
            constant := AVTConstant.create(typeResultRef);
            constant.value.asLong := source.getLexemeLong(pos);
            code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
            inc(pos);
        end;
        LITR_FLOAT: begin
            typeResultRef := getPrimitiveType(AVT_FLOAT);
            constant := AVTConstant.create(typeResultRef);
            constant.value.asFloat := source.getLexemeFloat(pos);
            code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
            inc(pos);
        end;
        LITR_DOUBLE: begin
            typeResultRef := getPrimitiveType(AVT_DOUBLE);
            constant := AVTConstant.create(typeResultRef);
            constant.value.asDouble := source.getLexemeDouble(pos);
            code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
            inc(pos);
        end
        else
            raise AVTCompilerException.create('Error in expression', source, pos);
        end;
        result := parsePostfix(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers, isUseSuper, isImplicitPeriod);
    end;

    function AVTCodeBuilder.parsePrefix(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
    label
        label0;
    var
        i: int;
        lineIndex: int;
        lexemeType: int;
        instruction: int;
        operatorPos: int;
        operatorKind: int;
        primitiveKind: int;
        argumentTypes: Vector;
        stack: Vector;
        dst: AVTConstant;
        operand: _Object;
        foundField: AVTField;
        foundMethod: AVTMethod;
        foundProperty: AVTProperty;
        typeVoidRef: AVTType;
        typeCastRef: AVTType;
        typeReturnRef: AVTType;
        typeOperandRef: AVTType;
        typeDereferenceRef: AVTTypeStructured;
        expressionNode: AVTNode;
        currentNode: AVTNode;
        item: AVTUnaryOperatorStackItem;
    begin
        stack := nil;
        try
            repeat
                lexemeType := source.getLexemeType(pos);
                case lexemeType of
                OPER_BOOL_NOT, OPER_BIT_NOT, OPER_VECT_PACK, OPER_VECT_UNPCKL, OPER_VECT_UNPCKU: begin
                    if stack = nil then stack := Vector.create();
                    stack.append(ValueOfObject.create(AVTUnaryOperatorStackItem.create(pos, lexemeType)));
                    inc(pos);
                end;
                OPER_SCAL_ADD: begin
                    if stack = nil then stack := Vector.create();
                    stack.append(ValueOfObject.create(AVTUnaryOperatorStackItem.create(pos, OPER_SCAL_PLUS)));
                    inc(pos);
                end;
                OPER_SCAL_SUB: begin
                    if stack = nil then stack := Vector.create();
                    stack.append(ValueOfObject.create(AVTUnaryOperatorStackItem.create(pos, OPER_SCAL_MINUS)));
                    inc(pos);
                end;
                OPER_VECT_ADD: begin
                    if stack = nil then stack := Vector.create();
                    stack.append(ValueOfObject.create(AVTUnaryOperatorStackItem.create(pos, OPER_VECT_PLUS)));
                    inc(pos);
                end;
                OPER_VECT_SUB: begin
                    if stack = nil then stack := Vector.create();
                    stack.append(ValueOfObject.create(AVTUnaryOperatorStackItem.create(pos, OPER_VECT_MINUS)));
                    inc(pos);
                end;
                OPER_INCREMENT: begin
                    if stack = nil then stack := Vector.create();
                    stack.append(ValueOfObject.create(AVTUnaryOperatorStackItem.create(pos, OPER_INC_PRED)));
                    inc(pos);
                end;
                OPER_DECREMENT: begin
                    if stack = nil then stack := Vector.create();
                    stack.append(ValueOfObject.create(AVTUnaryOperatorStackItem.create(pos, OPER_DEC_PRED)));
                    inc(pos);
                end;
                CHAR_PARENTH_OPENED: begin
                    operatorPos := pos;
                    typeCastRef := tryParseType(parentNode, methodRef, typeRef, source, pos + 1);
                    pos := source.position;
                    if (typeCastRef = nil) or (source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED) then begin
                        pos := operatorPos;
                        break;
                    end;
                    if stack = nil then stack := Vector.create();
                    stack.append(ValueOfObject.create(AVTUnaryOperatorStackItem.create(operatorPos, OPER_TYPE_CAST, typeCastRef)));
                    inc(pos);
                end
                else
                    break;
                end;
            until false;
            pos := parsePrimary(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
            if stack <> nil then begin
                expressionNode := parentNode.lastChild();
                for i := stack.size() - 1 downto 0 do begin
                    item := stack.elementAt(i).objectValue() as AVTUnaryOperatorStackItem;
                    operatorPos := item.position;
                    operatorKind := item.operatorKind;
                    typeOperandRef := expressionNode.dataType;
                    if typeOperandRef = nil then begin
                        if operatorKind = OPER_TYPE_CAST then begin
                            typeCastRef := item.typeCast;
                            if typeCastRef is AVTTypeStructured then begin
                                expressionNode.dataType := typeCastRef;
                                continue;
                            end;
                            raise AVTCompilerException.create('Can not cast from null to ' + typeCastRef.fullName, source, operatorPos);
                        end;
                    end else
                    if typeOperandRef is AVTTypePrimitive then begin
                        primitiveKind := AVTTypePrimitive(typeOperandRef).primitiveKind;
                        instruction := expressionNode.instruction;
                        if instruction = LOAD_CONST then begin
                            dst := expressionNode.operand1 as AVTConstant;
                            if primitiveKind = AVT_CHAR then begin
                                primitiveKind := AVT_INT;
                                typeOperandRef := getPrimitiveType(AVT_INT);
                                dst.value.asInt := int(dst.value.asChar);
                            end;
                            case operatorKind of
                            OPER_BOOL_NOT: begin
                                if primitiveKind = AVT_BOOLEAN then begin
                                    dst.value.asBoolean := not dst.value.asBoolean;
                                end else begin
                                    goto label0;
                                end;
                            end;
                            OPER_BIT_NOT: begin
                                case primitiveKind of
                                AVT_BYTE:
                                    byteBitNot(dst, dst);
                                AVT_BYTE2:
                                    byte2BitNot(dst, dst);
                                AVT_BYTE4:
                                    byte4BitNot(dst, dst);
                                AVT_BYTE8:
                                    byte8BitNot(dst, dst);
                                AVT_SHORT:
                                    shortBitNot(dst, dst);
                                AVT_SHORT2:
                                    short2BitNot(dst, dst);
                                AVT_SHORT4:
                                    short4BitNot(dst, dst);
                                AVT_SHORT8:
                                    short8BitNot(dst, dst);
                                AVT_INT:
                                    intBitNot(dst, dst);
                                AVT_INT2:
                                    int2BitNot(dst, dst);
                                AVT_INT4:
                                    int4BitNot(dst, dst);
                                AVT_INT8:
                                    int8BitNot(dst, dst);
                                AVT_LONG:
                                    longBitNot(dst, dst);
                                AVT_LONG2:
                                    long2BitNot(dst, dst);
                                AVT_LONG4:
                                    long4BitNot(dst, dst);
                                AVT_LONG8:
                                    long8BitNot(dst, dst);
                                else
                                    goto label0;
                                end;
                            end;
                            OPER_SCAL_PLUS: begin
                                case primitiveKind of
                                AVT_BYTE:
                                    byteScalPlus(dst, dst);
                                AVT_BYTE2:
                                    byte2ScalPlus(dst, dst);
                                AVT_BYTE4:
                                    byte4ScalPlus(dst, dst);
                                AVT_BYTE8:
                                    byte8ScalPlus(dst, dst);
                                AVT_SHORT:
                                    shortScalPlus(dst, dst);
                                AVT_SHORT2:
                                    short2ScalPlus(dst, dst);
                                AVT_SHORT4:
                                    short4ScalPlus(dst, dst);
                                AVT_SHORT8:
                                    short8ScalPlus(dst, dst);
                                AVT_INT:
                                    intScalPlus(dst, dst);
                                AVT_INT2:
                                    int2ScalPlus(dst, dst);
                                AVT_INT4:
                                    int4ScalPlus(dst, dst);
                                AVT_INT8:
                                    int8ScalPlus(dst, dst);
                                AVT_LONG:
                                    longScalPlus(dst, dst);
                                AVT_LONG2:
                                    long2ScalPlus(dst, dst);
                                AVT_LONG4:
                                    long4ScalPlus(dst, dst);
                                AVT_LONG8:
                                    long8ScalPlus(dst, dst);
                                AVT_FLOAT:
                                    floatScalPlus(dst, dst);
                                AVT_FLOAT2:
                                    float2ScalPlus(dst, dst);
                                AVT_FLOAT4:
                                    float4ScalPlus(dst, dst);
                                AVT_FLOAT8:
                                    float8ScalPlus(dst, dst);
                                AVT_DOUBLE:
                                    doubleScalPlus(dst, dst);
                                AVT_DOUBLE2:
                                    double2ScalPlus(dst, dst);
                                AVT_DOUBLE4:
                                    double4ScalPlus(dst, dst);
                                AVT_DOUBLE8:
                                    double8ScalPlus(dst, dst);
                                AVT_REAL:
                                    realScalPlus(dst, dst);
                                else
                                    goto label0;
                                end;
                            end;
                            OPER_SCAL_MINUS: begin
                                case primitiveKind of
                                AVT_BYTE:
                                    byteScalMinus(dst, dst);
                                AVT_BYTE2:
                                    byte2ScalMinus(dst, dst);
                                AVT_BYTE4:
                                    byte4ScalMinus(dst, dst);
                                AVT_BYTE8:
                                    byte8ScalMinus(dst, dst);
                                AVT_SHORT:
                                    shortScalMinus(dst, dst);
                                AVT_SHORT2:
                                    short2ScalMinus(dst, dst);
                                AVT_SHORT4:
                                    short4ScalMinus(dst, dst);
                                AVT_SHORT8:
                                    short8ScalMinus(dst, dst);
                                AVT_INT:
                                    intScalMinus(dst, dst);
                                AVT_INT2:
                                    int2ScalMinus(dst, dst);
                                AVT_INT4:
                                    int4ScalMinus(dst, dst);
                                AVT_INT8:
                                    int8ScalMinus(dst, dst);
                                AVT_LONG:
                                    longScalMinus(dst, dst);
                                AVT_LONG2:
                                    long2ScalMinus(dst, dst);
                                AVT_LONG4:
                                    long4ScalMinus(dst, dst);
                                AVT_LONG8:
                                    long8ScalMinus(dst, dst);
                                AVT_FLOAT:
                                    floatScalMinus(dst, dst);
                                AVT_FLOAT2:
                                    float2ScalMinus(dst, dst);
                                AVT_FLOAT4:
                                    float4ScalMinus(dst, dst);
                                AVT_FLOAT8:
                                    float8ScalMinus(dst, dst);
                                AVT_DOUBLE:
                                    doubleScalMinus(dst, dst);
                                AVT_DOUBLE2:
                                    double2ScalMinus(dst, dst);
                                AVT_DOUBLE4:
                                    double4ScalMinus(dst, dst);
                                AVT_DOUBLE8:
                                    double8ScalMinus(dst, dst);
                                AVT_REAL:
                                    realScalMinus(dst, dst);
                                else
                                    goto label0;
                                end;
                            end;
                            OPER_VECT_PACK: begin
                                if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_BYTE8) then begin
                                    inc(primitiveKind, 4);
                                    castByte8ToShort8(dst, dst, primitiveKind);
                                end;
                                case primitiveKind of
                                AVT_SHORT:
                                    shortVectPack(dst, dst);
                                AVT_SHORT2:
                                    short2VectPack(dst, dst);
                                AVT_SHORT4:
                                    short4VectPack(dst, dst);
                                AVT_SHORT8:
                                    short8VectPack(dst, dst);
                                AVT_INT:
                                    intVectPack(dst, dst);
                                AVT_INT2:
                                    int2VectPack(dst, dst);
                                AVT_INT4:
                                    int4VectPack(dst, dst);
                                AVT_INT8:
                                    int8VectPack(dst, dst);
                                AVT_LONG:
                                    longVectPack(dst, dst);
                                AVT_LONG2:
                                    long2VectPack(dst, dst);
                                AVT_LONG4:
                                    long4VectPack(dst, dst);
                                AVT_LONG8:
                                    long8VectPack(dst, dst);
                                else
                                    goto label0;
                                end;
                            end;
                            OPER_VECT_UNPCKL: begin
                                case primitiveKind of
                                AVT_BYTE:
                                    byteVectUnpckl(dst, dst);
                                AVT_BYTE2:
                                    byte2VectUnpckl(dst, dst);
                                AVT_BYTE4:
                                    byte4VectUnpckl(dst, dst);
                                AVT_BYTE8:
                                    byte8VectUnpckl(dst, dst);
                                AVT_SHORT:
                                    shortVectUnpckl(dst, dst);
                                AVT_SHORT2:
                                    short2VectUnpckl(dst, dst);
                                AVT_SHORT4:
                                    short4VectUnpckl(dst, dst);
                                AVT_SHORT8:
                                    short8VectUnpckl(dst, dst);
                                AVT_INT:
                                    intVectUnpckl(dst, dst);
                                AVT_INT2:
                                    int2VectUnpckl(dst, dst);
                                AVT_INT4:
                                    int4VectUnpckl(dst, dst);
                                AVT_INT8:
                                    int8VectUnpckl(dst, dst);
                                else
                                    goto label0;
                                end;
                            end;
                            OPER_VECT_UNPCKU: begin
                                case primitiveKind of
                                AVT_BYTE:
                                    byteVectUnpcku(dst, dst);
                                AVT_BYTE2:
                                    byte2VectUnpcku(dst, dst);
                                AVT_BYTE4:
                                    byte4VectUnpcku(dst, dst);
                                AVT_BYTE8:
                                    byte8VectUnpcku(dst, dst);
                                AVT_SHORT:
                                    shortVectUnpcku(dst, dst);
                                AVT_SHORT2:
                                    short2VectUnpcku(dst, dst);
                                AVT_SHORT4:
                                    short4VectUnpcku(dst, dst);
                                AVT_SHORT8:
                                    short8VectUnpcku(dst, dst);
                                AVT_INT:
                                    intVectUnpcku(dst, dst);
                                AVT_INT2:
                                    int2VectUnpcku(dst, dst);
                                AVT_INT4:
                                    int4VectUnpcku(dst, dst);
                                AVT_INT8:
                                    int8VectUnpcku(dst, dst);
                                else
                                    goto label0;
                                end;
                            end;
                            OPER_VECT_PLUS: begin
                                case primitiveKind of
                                AVT_BYTE:
                                    byteVectPlus(dst, dst);
                                AVT_BYTE2:
                                    byte2VectPlus(dst, dst);
                                AVT_BYTE4:
                                    byte4VectPlus(dst, dst);
                                AVT_BYTE8:
                                    byte8VectPlus(dst, dst);
                                AVT_SHORT:
                                    shortVectPlus(dst, dst);
                                AVT_SHORT2:
                                    short2VectPlus(dst, dst);
                                AVT_SHORT4:
                                    short4VectPlus(dst, dst);
                                AVT_SHORT8:
                                    short8VectPlus(dst, dst);
                                AVT_INT:
                                    intVectPlus(dst, dst);
                                AVT_INT2:
                                    int2VectPlus(dst, dst);
                                AVT_INT4:
                                    int4VectPlus(dst, dst);
                                AVT_INT8:
                                    int8VectPlus(dst, dst);
                                AVT_LONG:
                                    longVectPlus(dst, dst);
                                AVT_LONG2:
                                    long2VectPlus(dst, dst);
                                AVT_LONG4:
                                    long4VectPlus(dst, dst);
                                AVT_LONG8:
                                    long8VectPlus(dst, dst);
                                AVT_FLOAT:
                                    floatVectPlus(dst, dst);
                                AVT_FLOAT2:
                                    float2VectPlus(dst, dst);
                                AVT_FLOAT4:
                                    float4VectPlus(dst, dst);
                                AVT_FLOAT8:
                                    float8VectPlus(dst, dst);
                                AVT_DOUBLE:
                                    doubleVectPlus(dst, dst);
                                AVT_DOUBLE2:
                                    double2VectPlus(dst, dst);
                                AVT_DOUBLE4:
                                    double4VectPlus(dst, dst);
                                AVT_DOUBLE8:
                                    double8VectPlus(dst, dst);
                                else
                                    goto label0;
                                end;
                            end;
                            OPER_VECT_MINUS: begin
                                case primitiveKind of
                                AVT_BYTE:
                                    byteVectMinus(dst, dst);
                                AVT_BYTE2:
                                    byte2VectMinus(dst, dst);
                                AVT_BYTE4:
                                    byte4VectMinus(dst, dst);
                                AVT_BYTE8:
                                    byte8VectMinus(dst, dst);
                                AVT_SHORT:
                                    shortVectMinus(dst, dst);
                                AVT_SHORT2:
                                    short2VectMinus(dst, dst);
                                AVT_SHORT4:
                                    short4VectMinus(dst, dst);
                                AVT_SHORT8:
                                    short8VectMinus(dst, dst);
                                AVT_INT:
                                    intVectMinus(dst, dst);
                                AVT_INT2:
                                    int2VectMinus(dst, dst);
                                AVT_INT4:
                                    int4VectMinus(dst, dst);
                                AVT_INT8:
                                    int8VectMinus(dst, dst);
                                AVT_LONG:
                                    longVectMinus(dst, dst);
                                AVT_LONG2:
                                    long2VectMinus(dst, dst);
                                AVT_LONG4:
                                    long4VectMinus(dst, dst);
                                AVT_LONG8:
                                    long8VectMinus(dst, dst);
                                AVT_FLOAT:
                                    floatVectMinus(dst, dst);
                                AVT_FLOAT2:
                                    float2VectMinus(dst, dst);
                                AVT_FLOAT4:
                                    float4VectMinus(dst, dst);
                                AVT_FLOAT8:
                                    float8VectMinus(dst, dst);
                                AVT_DOUBLE:
                                    doubleVectMinus(dst, dst);
                                AVT_DOUBLE2:
                                    double2VectMinus(dst, dst);
                                AVT_DOUBLE4:
                                    double4VectMinus(dst, dst);
                                AVT_DOUBLE8:
                                    double8VectMinus(dst, dst);
                                else
                                    goto label0;
                                end;
                            end;
                            OPER_TYPE_CAST: begin
                                typeCastRef := item.typeCast;
                                if typeCastRef.isBoolean() and typeOperandRef.isBoolean() then begin
                                    continue;
                                end;
                                if typeCastRef.isNumeric() and typeOperandRef.isNumeric() then begin
                                    if typeOperandRef <> typeCastRef then begin
                                        cast(dst, dst, typeCastRef as AVTTypePrimitive);
                                        expressionNode.dataType := typeCastRef;
                                    end;
                                    continue;
                                end;
                                raise AVTCompilerException.create('Can not cast from ' + typeOperandRef.fullName + ' to ' + typeCastRef.fullName, source, operatorPos);
                            end
                            else
                                raise AVTCompilerException.create('The operator ++/-- applicable only to variables, properties and array elements', source, operatorPos);
                            end;
                            expressionNode.dataType := dst.valueType;
                            continue;
                        end;
                        if primitiveKind = AVT_CHAR then begin
                            primitiveKind := AVT_INT;
                            typeOperandRef := getPrimitiveType(AVT_INT);
                        end;
                        case operatorKind of
                        OPER_BOOL_NOT: begin
                            if primitiveKind = AVT_BOOLEAN then begin
                                typeReturnRef := typeOperandRef;
                            end else begin
                                goto label0;
                            end;
                        end;
                        OPER_BIT_NOT: begin
                            if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_LONG8) then begin
                                typeReturnRef := typeOperandRef;
                            end else begin
                                goto label0;
                            end;
                        end;
                        OPER_SCAL_PLUS: begin
                            if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_SHORT8) then begin
                                typeReturnRef := getPrimitiveType(AVT_INT + (primitiveKind and 3));
                                if (primitiveKind <> AVT_BYTE) and (primitiveKind <> AVT_SHORT) then begin
                                    currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(operatorPos), typeReturnRef, OPER_TYPE_CAST, typeReturnRef, typeOperandRef);
                                    code.moveNode(expressionNode, currentNode, 0);
                                    expressionNode := currentNode;
                                end;
                                continue;
                            end;
                            if (primitiveKind >= AVT_INT) and (primitiveKind <= AVT_DOUBLE8) or (primitiveKind = AVT_REAL) then begin
                                continue;
                            end;
                            goto label0;
                        end;
                        OPER_SCAL_MINUS: begin
                            if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_SHORT8) then begin
                                typeReturnRef := getPrimitiveType(AVT_INT + (primitiveKind and 3));
                            end else
                            if (primitiveKind >= AVT_INT) and (primitiveKind <= AVT_DOUBLE8) or (primitiveKind = AVT_REAL) then begin
                                typeReturnRef := typeOperandRef;
                            end else begin
                                goto label0;
                            end;
                        end;
                        OPER_VECT_PACK: begin
                            if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_BYTE8) then begin
                                inc(primitiveKind, 4);
                                typeReturnRef := getPrimitiveType(primitiveKind);
                                currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(operatorPos), typeReturnRef, OPER_TYPE_CAST, typeReturnRef, typeOperandRef);
                                code.moveNode(expressionNode, currentNode, 0);
                                expressionNode := currentNode;
                                typeOperandRef := typeReturnRef;
                            end;
                            if (primitiveKind >= AVT_SHORT) and (primitiveKind <= AVT_LONG8) then begin
                                typeReturnRef := getPrimitiveType(primitiveKind - 4);
                            end else begin
                                goto label0;
                            end;
                        end;
                        OPER_VECT_UNPCKL, OPER_VECT_UNPCKU: begin
                            if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_INT8) then begin
                                typeReturnRef := getPrimitiveType(primitiveKind + 4);
                            end else begin
                                goto label0;
                            end;
                        end;
                        OPER_VECT_PLUS: begin
                            if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_DOUBLE8) then begin
                                continue;
                            end;
                            goto label0;
                        end;
                        OPER_VECT_MINUS: begin
                            if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_DOUBLE8) then begin
                                typeReturnRef := typeOperandRef;
                            end else begin
                                goto label0;
                            end;
                        end;
                        OPER_TYPE_CAST: begin
                            typeCastRef := item.typeCast;
                            if typeOperandRef.isBoolean() and typeCastRef.isBoolean() then begin
                                continue;
                            end;
                            if typeOperandRef.isNumeric() and typeCastRef.isNumeric() then begin
                                if typeOperandRef = typeCastRef then begin
                                    expressionNode.dataType := typeCastRef;
                                end else begin
                                    currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(operatorPos), typeCastRef, OPER_TYPE_CAST, typeCastRef, typeOperandRef);
                                    code.moveNode(expressionNode, currentNode, 0);
                                    expressionNode := currentNode;
                                end;
                                continue;
                            end;
                            raise AVTCompilerException.create('Can not cast from ' + typeOperandRef.fullName + ' to ' + typeCastRef.fullName, source, operatorPos);
                        end
                        else { OPER_INC_PRED, OPER_DEC_PRED }
                            typeVoidRef := getPrimitiveType(AVT_VOID);
                            lineIndex := expressionNode.lineIndex;
                            case instruction of
                            LOAD_VARIABLE: begin
                                typeOperandRef := (expressionNode.operand1 as AVTVariable).valueType;
                                if not typeOperandRef.isNumeric() then begin
                                    if operatorKind = OPER_INC_PRED then begin
                                        raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                                    end else begin
                                        raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                                    end;
                                end;
                                if operatorKind = OPER_INC_PRED then begin
                                    expressionNode.instruction := OPER_INC_PRED;
                                end else begin
                                    expressionNode.instruction := OPER_DEC_PRED;
                                end;
                            end;
                            LOAD_STATIC: begin
                                foundField := expressionNode.operand1 as AVTField;
                                if foundField.isFinal() then begin
                                    raise AVTCompilerException.create('The final field ' + foundField.fullName + ' can not be assigned', source, operatorPos);
                                end;
                                typeOperandRef := foundField.valueType;
                                if not typeOperandRef.isNumeric() then begin
                                    if operatorKind = OPER_INC_PRED then begin
                                        raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                                    end else begin
                                        raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                                    end;
                                end;
                                currentNode := insertIncrementCode(expressionNode, code, typeOperandRef as AVTTypePrimitive, operatorKind = OPER_INC_PRED, lineIndex);
                                code.insertNode(currentNode).setData(lineIndex, typeOperandRef, LOAD_STATIC, foundField);
                                code.appendNode(expressionNode).setData(lineIndex, typeVoidRef, DUP1);
                                expressionNode.instruction := STORE_STATIC;
                            end;
                            GET_FIELD: begin
                                foundField := expressionNode.operand1 as AVTField;
                                if foundField.isFinal() then begin
                                    raise AVTCompilerException.create('The final field ' + foundField.fullName + ' can not be assigned', source, operatorPos);
                                end;
                                typeOperandRef := foundField.valueType;
                                if not typeOperandRef.isNumeric() then begin
                                    if operatorKind = OPER_INC_PRED then begin
                                        raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                                    end else begin
                                        raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                                    end;
                                end;
                                currentNode := insertIncrementCode(expressionNode, code, typeOperandRef as AVTTypePrimitive, operatorKind = OPER_INC_PRED, lineIndex);
                                currentNode := code.insertNode(currentNode, 0, lineIndex, typeOperandRef, GET_FIELD, foundField);
                                code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
                                code.appendNode(expressionNode).setData(lineIndex, typeVoidRef, DUP1X1);
                                expressionNode.instruction := SET_FIELD;
                            end;
                            GET_PROPERTY: begin
                                foundProperty := expressionNode.operand1 as AVTProperty;
                                if foundProperty.writeSynthetic = nil then begin
                                    raise AVTCompilerException.create('The read-only property ' + foundProperty.simpleName + ' can not be assigned', source, pos);
                                end;
                                typeOperandRef := foundProperty.valueType;
                                if not typeOperandRef.isNumeric() then begin
                                    if operatorKind = OPER_INC_PRED then begin
                                        raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                                    end else begin
                                        raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                                    end;
                                end;
                                currentNode := insertIncrementCode(expressionNode, code, typeOperandRef as AVTTypePrimitive, operatorKind = OPER_INC_PRED, lineIndex);
                                currentNode := code.insertNode(currentNode, 0, lineIndex, typeOperandRef, GET_PROPERTY, foundProperty);
                                code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
                                code.appendNode(expressionNode).setData(lineIndex, typeVoidRef, DUP1X1);
                                expressionNode.instruction := SET_PROPERTY;
                            end;
                            GET_ARRAY_ELEMENT: begin
                                typeOperandRef := expressionNode.operand1 as AVTType;
                                if not typeOperandRef.isNumeric() then begin
                                    if operatorKind = OPER_INC_PRED then begin
                                        raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                                    end else begin
                                        raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                                    end;
                                end;
                                currentNode := insertIncrementCode(expressionNode, code, typeOperandRef as AVTTypePrimitive, operatorKind = OPER_INC_PRED, lineIndex);
                                currentNode := code.insertNode(currentNode, 0, lineIndex, typeOperandRef, GET_ARRAY_ELEMENT, typeOperandRef);
                                code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP2);
                                code.appendNode(expressionNode).setData(lineIndex, typeVoidRef, DUP1X2);
                                expressionNode.instruction := SET_ARRAY_ELEMENT;
                            end;
                            INVOKE_SPECIAL, INVOKE_VIRTUAL, INVOKE_SERVICE: begin
                                operand := expressionNode.operand1;
                                if (operand is AVTOperator) and (AVTOperator(operand).operatorKind = GET_ARRAY_ELEMENT) then begin
                                    typeOperandRef := AVTMethod(operand).returnType;
                                    if not typeOperandRef.isNumeric() then begin
                                        if operatorKind = OPER_INC_PRED then begin
                                            raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                                        end else begin
                                            raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                                        end;
                                    end;
                                    typeDereferenceRef := expressionNode[0].dataType as AVTTypeStructured;
                                    argumentTypes := Vector.create();
                                    try
                                        argumentTypes.append(ValueOfObject.create(AVTMethod(operand).getArgumentAt(0).valueType, false));
                                        argumentTypes.append(ValueOfObject.create(typeOperandRef, false));
                                        foundMethod := typeDereferenceRef.findMethod(AVTOperator.operatorToSpecName(SET_ARRAY_ELEMENT), argumentTypes, typeRef, operatorPos);
                                        if (foundMethod = nil) or not foundMethod.isIdentityArgumentTypes(argumentTypes) then begin
                                            raise AVTCompilerException.create('The operator []=' + argumentTypes.toString() + ' is undefined for the type ' + typeDereferenceRef.fullName, source, operatorPos);
                                        end;
                                    finally
                                        argumentTypes.free();
                                    end;
                                    if not foundMethod.isVisible(typeDereferenceRef, typeRef) then begin
                                        raise AVTCompilerException.create('The operator []=' + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
                                    end;
                                    currentNode := insertIncrementCode(expressionNode, code, typeOperandRef as AVTTypePrimitive, operatorKind = OPER_INC_PRED, lineIndex);
                                    currentNode := code.insertNode(currentNode, 0, lineIndex, typeOperandRef, instruction, operand);
                                    code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP2);
                                    code.appendNode(expressionNode).setData(lineIndex, typeVoidRef, DUP1X2);
                                    if (instruction <> INVOKE_SPECIAL) or foundMethod.isAbstract() then begin
                                        if foundMethod.parentType.isService() then begin
                                            instruction := INVOKE_SERVICE;
                                        end else begin
                                            instruction := INVOKE_VIRTUAL;
                                        end;
                                    end;
                                    expressionNode.setData(lineIndex, typeOperandRef, instruction, foundMethod);
                                end else begin
                                    foundProperty := (operand as AVTMethod).linkedProperty;
                                    if (foundProperty = nil) or (foundProperty.readSynthetic <> operand) then begin
                                        raise AVTCompilerException.create('The operator ++/-- applicable only to variables, properties and array elements', source, operatorPos);
                                    end;
                                    typeOperandRef := foundProperty.valueType;
                                    if not typeOperandRef.isNumeric() then begin
                                        if operatorKind = OPER_INC_PRED then begin
                                            raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                                        end else begin
                                            raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                                        end;
                                    end;
                                    foundMethod := foundProperty.writeSynthetic;
                                    if foundMethod = nil then begin
                                        raise AVTCompilerException.create('The read-only property ' + foundProperty.simpleName + ' can not be assigned', source, operatorPos);
                                    end;
                                    currentNode := insertIncrementCode(expressionNode, code, typeOperandRef as AVTTypePrimitive, operatorKind = OPER_INC_PRED, lineIndex);
                                    currentNode := code.insertNode(currentNode, 0, lineIndex, typeOperandRef, instruction, operand);
                                    code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
                                    code.appendNode(expressionNode).setData(lineIndex, typeVoidRef, DUP1X1);
                                    expressionNode.operand1 := foundMethod;
                                end;
                            end
                            else
                                raise AVTCompilerException.create('The operator ++/-- applicable only to variables, properties and array elements', source, operatorPos);
                            end;
                            continue;
                        end;
                        currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(operatorPos), typeReturnRef, operatorKind, typeOperandRef);
                        code.moveNode(expressionNode, currentNode, 0);
                        expressionNode := currentNode;
                        continue;
                    end else
                    if typeOperandRef is AVTTypeStructured then begin
                        typeDereferenceRef := AVTTypeStructured(typeOperandRef);
                        case operatorKind of
                        OPER_BIT_NOT, OPER_SCAL_PLUS, OPER_SCAL_MINUS, OPER_VECT_PACK, OPER_VECT_UNPCKL, OPER_VECT_UNPCKU, OPER_VECT_PLUS, OPER_VECT_MINUS: begin
                            foundMethod := typeDereferenceRef.findMethod(AVTOperator.operatorToSpecName(operatorKind), nil, typeRef, operatorPos);
                            if (foundMethod <> nil) and foundMethod.isIdentityArgumentTypes(nil) then begin
                                if not foundMethod.isVisible(typeDereferenceRef, typeRef) then begin
                                    raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
                                end;
                                if foundMethod.parentType.isService() then begin
                                    instruction := INVOKE_SERVICE;
                                end else begin
                                    instruction := INVOKE_VIRTUAL;
                                end;
                                currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(operatorPos), foundMethod.returnType, instruction, foundMethod);
                                code.moveNode(expressionNode, currentNode, 0);
                                expressionNode := currentNode;
                                continue;
                            end;
                        end;
                        OPER_TYPE_CAST: begin
                            typeCastRef := item.typeCast;
                            if typeCastRef is AVTTypeStructured then begin
                                if typeCastRef is AVTTypeArray then begin
                                    AVTTypeArray(typeCastRef).makeCompilable();
                                end;
                                if typeCastRef = typeOperandRef then begin
                                    continue;
                                end;
                                if typeCastRef.isAssignableFrom(typeOperandRef) then begin
                                    expressionNode.dataType := typeCastRef;
                                    continue;
                                end;
                                if not typeOperandRef.isFinal() and (typeCastRef.isService() or typeOperandRef.isAssignableFrom(typeCastRef)) then begin
                                    currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(operatorPos), typeCastRef, OPER_TYPE_CAST, typeCastRef, typeOperandRef);
                                    code.moveNode(expressionNode, currentNode, 0);
                                    expressionNode := currentNode;
                                    continue;
                                end;
                            end;
                            raise AVTCompilerException.create('Can not cast from ' + typeOperandRef.fullName + ' to ' + typeCastRef.fullName, source, operatorPos);
                        end;
                        end;
                    end;
                    label0:
                    case operatorKind of
                    OPER_SCAL_PLUS:
                        raise AVTCompilerException.create('The operator + is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                    OPER_SCAL_MINUS:
                        raise AVTCompilerException.create('The operator - is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                    OPER_INC_PRED:
                        raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                    OPER_DEC_PRED:
                        raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                    OPER_VECT_PLUS:
                        raise AVTCompilerException.create('The operator ++++ is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                    OPER_VECT_MINUS:
                        raise AVTCompilerException.create('The operator ---- is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                    else
                        raise AVTCompilerException.create('The operator ' + AVTLexer.lexemeToString(operatorKind) + ' is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
                    end;
                end;
            end;
        finally
            stack.free();
        end;
        result := pos;
    end;

    function AVTCodeBuilder.parseMultiplicative(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
    label
        label0;
    var
        isRight: boolean;
        instruction: int;
        operatorPos: int;
        operatorKind: int;
        primitiveKind: int;
        dst: AVTConstant;
        op0: AVTConstant;
        op1: AVTConstant;
        argumentTypes: Vector;
        foundMethod: AVTMethod;
        typeReturnRef: AVTType;
        typeCommonRef: AVTType;
        typeOperand0Ref: AVTType;
        typeOperand1Ref: AVTType;
        expressionNode: AVTNode;
        operand0Node: AVTNode;
        operand1Node: AVTNode;
    begin
        pos := parsePrefix(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
        repeat
            operatorKind := source.getLexemeType(pos);
            case operatorKind of
            OPER_SCAL_MUL, OPER_SCAL_DIV, OPER_SCAL_DIVU, OPER_SCAL_REM, OPER_SCAL_REMU, OPER_VECT_MUL, OPER_VECT_MULS, OPER_VECT_MULU, OPER_VECT_DIV: begin
                operatorPos := pos;
                operand0Node := parentNode.lastChild();
                expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, operatorKind, nil);
                code.moveNode(operand0Node, expressionNode, 0);
                pos := parsePrefix(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
            end
            else
                break;
            end;
            dst := nil;
            operand1Node := expressionNode.lastChild();
            typeOperand0Ref := operand0Node.dataType;
            typeOperand1Ref := operand1Node.dataType;
            typeCommonRef := commonType(typeOperand0Ref, typeOperand1Ref);
            if typeCommonRef is AVTTypePrimitive then begin
                primitiveKind := AVTTypePrimitive(typeCommonRef).primitiveKind;
                if (operand0Node.instruction = LOAD_CONST) and (operand1Node.instruction = LOAD_CONST) then begin
                    op0 := operand0Node.operand1 as AVTConstant;
                    op1 := operand1Node.operand1 as AVTConstant;
                    cast(op0, op0, AVTTypePrimitive(typeCommonRef));
                    cast(op1, op1, AVTTypePrimitive(typeCommonRef));
                    dst := AVTConstant.create();
                    case operatorKind of
                    OPER_SCAL_MUL: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteScalMul(dst, op0, op1);
                        AVT_BYTE2:
                            byte2ScalMul(dst, op0, op1);
                        AVT_BYTE4:
                            byte4ScalMul(dst, op0, op1);
                        AVT_BYTE8:
                            byte8ScalMul(dst, op0, op1);
                        AVT_SHORT:
                            shortScalMul(dst, op0, op1);
                        AVT_SHORT2:
                            short2ScalMul(dst, op0, op1);
                        AVT_SHORT4:
                            short4ScalMul(dst, op0, op1);
                        AVT_SHORT8:
                            short8ScalMul(dst, op0, op1);
                        AVT_INT:
                            intScalMul(dst, op0, op1);
                        AVT_INT2:
                            int2ScalMul(dst, op0, op1);
                        AVT_INT4:
                            int4ScalMul(dst, op0, op1);
                        AVT_INT8:
                            int8ScalMul(dst, op0, op1);
                        AVT_LONG:
                            longScalMul(dst, op0, op1);
                        AVT_LONG2:
                            long2ScalMul(dst, op0, op1);
                        AVT_LONG4:
                            long4ScalMul(dst, op0, op1);
                        AVT_LONG8:
                            long8ScalMul(dst, op0, op1);
                        AVT_FLOAT:
                            floatScalMul(dst, op0, op1);
                        AVT_FLOAT2:
                            float2ScalMul(dst, op0, op1);
                        AVT_FLOAT4:
                            float4ScalMul(dst, op0, op1);
                        AVT_FLOAT8:
                            float8ScalMul(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleScalMul(dst, op0, op1);
                        AVT_DOUBLE2:
                            double2ScalMul(dst, op0, op1);
                        AVT_DOUBLE4:
                            double4ScalMul(dst, op0, op1);
                        AVT_DOUBLE8:
                            double8ScalMul(dst, op0, op1);
                        AVT_REAL:
                            realScalMul(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_SCAL_DIV: begin
                        if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_LONG8) and op1.isDefaultValue() then begin
                            dst.free();
                            raise AVTCompilerException.create('Integer constant division by zero error', source, operatorPos);
                        end;
                        case primitiveKind of
                        AVT_BYTE:
                            byteScalDiv(dst, op0, op1);
                        AVT_SHORT:
                            shortScalDiv(dst, op0, op1);
                        AVT_INT:
                            intScalDiv(dst, op0, op1);
                        AVT_LONG:
                            longScalDiv(dst, op0, op1);
                        AVT_FLOAT:
                            floatScalDiv(dst, op0, op1);
                        AVT_FLOAT2:
                            float2ScalDiv(dst, op0, op1);
                        AVT_FLOAT4:
                            float4ScalDiv(dst, op0, op1);
                        AVT_FLOAT8:
                            float8ScalDiv(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleScalDiv(dst, op0, op1);
                        AVT_DOUBLE2:
                            double2ScalDiv(dst, op0, op1);
                        AVT_DOUBLE4:
                            double4ScalDiv(dst, op0, op1);
                        AVT_DOUBLE8:
                            double8ScalDiv(dst, op0, op1);
                        AVT_REAL:
                            realScalDiv(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_SCAL_DIVU: begin
                        if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_LONG8) and op1.isDefaultValue() then begin
                            dst.free();
                            raise AVTCompilerException.create('Integer constant division by zero error', source, operatorPos);
                        end;
                        case primitiveKind of
                        AVT_BYTE:
                            byteScalDivu(dst, op0, op1);
                        AVT_SHORT:
                            shortScalDivu(dst, op0, op1);
                        AVT_INT:
                            intScalDivu(dst, op0, op1);
                        AVT_LONG:
                            longScalDivu(dst, op0, op1);
                        AVT_FLOAT:
                            floatScalDivu(dst, op0, op1);
                        AVT_FLOAT2:
                            float2ScalDivu(dst, op0, op1);
                        AVT_FLOAT4:
                            float4ScalDivu(dst, op0, op1);
                        AVT_FLOAT8:
                            float8ScalDivu(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleScalDivu(dst, op0, op1);
                        AVT_DOUBLE2:
                            double2ScalDivu(dst, op0, op1);
                        AVT_DOUBLE4:
                            double4ScalDivu(dst, op0, op1);
                        AVT_DOUBLE8:
                            double8ScalDivu(dst, op0, op1);
                        AVT_REAL:
                            realScalDivu(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_SCAL_REM: begin
                        if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_LONG8) and op1.isDefaultValue() then begin
                            dst.free();
                            raise AVTCompilerException.create('Integer constant division by zero error', source, operatorPos);
                        end;
                        case primitiveKind of
                        AVT_BYTE:
                            byteScalRem(dst, op0, op1);
                        AVT_SHORT:
                            shortScalRem(dst, op0, op1);
                        AVT_INT:
                            intScalRem(dst, op0, op1);
                        AVT_LONG:
                            longScalRem(dst, op0, op1);
                        AVT_FLOAT:
                            floatScalRem(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleScalRem(dst, op0, op1);
                        AVT_REAL:
                            realScalRem(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_SCAL_REMU: begin
                        if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_LONG8) and op1.isDefaultValue() then begin
                            dst.free();
                            raise AVTCompilerException.create('Integer constant division by zero error', source, operatorPos);
                        end;
                        case primitiveKind of
                        AVT_BYTE:
                            byteScalRemu(dst, op0, op1);
                        AVT_SHORT:
                            shortScalRemu(dst, op0, op1);
                        AVT_INT:
                            intScalRemu(dst, op0, op1);
                        AVT_LONG:
                            longScalRemu(dst, op0, op1);
                        AVT_FLOAT:
                            floatScalRemu(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleScalRemu(dst, op0, op1);
                        AVT_REAL:
                            realScalRemu(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_VECT_MUL: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteVectMul(dst, op0, op1);
                        AVT_BYTE2:
                            byte2VectMul(dst, op0, op1);
                        AVT_BYTE4:
                            byte4VectMul(dst, op0, op1);
                        AVT_BYTE8:
                            byte8VectMul(dst, op0, op1);
                        AVT_SHORT:
                            shortVectMul(dst, op0, op1);
                        AVT_SHORT2:
                            short2VectMul(dst, op0, op1);
                        AVT_SHORT4:
                            short4VectMul(dst, op0, op1);
                        AVT_SHORT8:
                            short8VectMul(dst, op0, op1);
                        AVT_INT:
                            intVectMul(dst, op0, op1);
                        AVT_INT2:
                            int2VectMul(dst, op0, op1);
                        AVT_INT4:
                            int4VectMul(dst, op0, op1);
                        AVT_INT8:
                            int8VectMul(dst, op0, op1);
                        AVT_LONG:
                            longVectMul(dst, op0, op1);
                        AVT_LONG2:
                            long2VectMul(dst, op0, op1);
                        AVT_LONG4:
                            long4VectMul(dst, op0, op1);
                        AVT_LONG8:
                            long8VectMul(dst, op0, op1);
                        AVT_FLOAT:
                            floatVectMul(dst, op0, op1);
                        AVT_FLOAT2:
                            float2VectMul(dst, op0, op1);
                        AVT_FLOAT4:
                            float4VectMul(dst, op0, op1);
                        AVT_FLOAT8:
                            float8VectMul(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleVectMul(dst, op0, op1);
                        AVT_DOUBLE2:
                            double2VectMul(dst, op0, op1);
                        AVT_DOUBLE4:
                            double4VectMul(dst, op0, op1);
                        AVT_DOUBLE8:
                            double8VectMul(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_VECT_MULS: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteVectMuls(dst, op0, op1);
                        AVT_BYTE2:
                            byte2VectMuls(dst, op0, op1);
                        AVT_BYTE4:
                            byte4VectMuls(dst, op0, op1);
                        AVT_BYTE8:
                            byte8VectMuls(dst, op0, op1);
                        AVT_SHORT:
                            shortVectMuls(dst, op0, op1);
                        AVT_SHORT2:
                            short2VectMuls(dst, op0, op1);
                        AVT_SHORT4:
                            short4VectMuls(dst, op0, op1);
                        AVT_SHORT8:
                            short8VectMuls(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_VECT_MULU: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteVectMulu(dst, op0, op1);
                        AVT_BYTE2:
                            byte2VectMulu(dst, op0, op1);
                        AVT_BYTE4:
                            byte4VectMulu(dst, op0, op1);
                        AVT_BYTE8:
                            byte8VectMulu(dst, op0, op1);
                        AVT_SHORT:
                            shortVectMulu(dst, op0, op1);
                        AVT_SHORT2:
                            short2VectMulu(dst, op0, op1);
                        AVT_SHORT4:
                            short4VectMulu(dst, op0, op1);
                        AVT_SHORT8:
                            short8VectMulU(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_VECT_DIV: begin
                        if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_BYTE8) then begin
                            primitiveKind := AVT_FLOAT + (primitiveKind and 3);
                            castByte8ToFloat8(op0, op0, primitiveKind);
                            castByte8ToFloat8(op1, op1, primitiveKind);
                        end else
                        if (primitiveKind >= AVT_SHORT) and (primitiveKind <= AVT_SHORT8) then begin
                            primitiveKind := AVT_FLOAT + (primitiveKind and 3);
                            castShort8ToFloat8(op0, op0, primitiveKind);
                            castShort8ToFloat8(op1, op1, primitiveKind);
                        end else
                        if (primitiveKind >= AVT_INT) and (primitiveKind <= AVT_INT8) then begin
                            primitiveKind := AVT_DOUBLE + (primitiveKind and 3);
                            castInt8ToDouble8(op0, op0, primitiveKind);
                            castInt8ToDouble8(op1, op1, primitiveKind);
                        end;
                        case primitiveKind of
                        AVT_FLOAT:
                            floatVectDiv(dst, op0, op1);
                        AVT_FLOAT2:
                            float2VectDiv(dst, op0, op1);
                        AVT_FLOAT4:
                            float4VectDiv(dst, op0, op1);
                        AVT_FLOAT8:
                            float8VectDiv(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleVectDiv(dst, op0, op1);
                        AVT_DOUBLE2:
                            double2VectDiv(dst, op0, op1);
                        AVT_DOUBLE4:
                            double4VectDiv(dst, op0, op1);
                        AVT_DOUBLE8:
                            double8VectDiv(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    end;
                    expressionNode.setData(expressionNode.lineIndex, dst.valueType, LOAD_CONST, dst);
                    code.removeNode(operand1Node);
                    code.removeNode(operand0Node);
                    continue;
                end;
                case operatorKind of
                OPER_SCAL_MUL: begin
                    if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_SHORT8) then begin
                        typeReturnRef := getPrimitiveType(AVT_INT + (primitiveKind and 3));
                    end else
                    if (primitiveKind >= AVT_INT) and (primitiveKind <= AVT_DOUBLE8) or (primitiveKind = AVT_REAL) then begin
                        typeReturnRef := typeCommonRef;
                    end else begin
                        goto label0;
                    end;
                end;
                OPER_SCAL_DIV, OPER_SCAL_DIVU: begin
                    if (primitiveKind = AVT_BYTE) or (primitiveKind = AVT_SHORT) then begin
                        typeReturnRef := getPrimitiveType(AVT_INT);
                    end else
                    if (primitiveKind = AVT_INT) or (primitiveKind = AVT_LONG) or (primitiveKind >= AVT_FLOAT) and (primitiveKind <= AVT_DOUBLE8) or (primitiveKind = AVT_REAL) then begin
                        typeReturnRef := typeCommonRef;
                    end else begin
                        goto label0;
                    end;
                end;
                OPER_SCAL_REM, OPER_SCAL_REMU: begin
                    if (primitiveKind = AVT_BYTE) or (primitiveKind = AVT_SHORT) then begin
                        typeReturnRef := getPrimitiveType(AVT_INT);
                    end else
                    if (primitiveKind = AVT_INT) or (primitiveKind = AVT_LONG) or (primitiveKind = AVT_FLOAT) or (primitiveKind = AVT_DOUBLE) or (primitiveKind = AVT_REAL) then begin
                        typeReturnRef := typeCommonRef;
                    end else begin
                        goto label0;
                    end;
                end;
                OPER_VECT_MUL: begin
                    if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_DOUBLE8) then begin
                        typeReturnRef := typeCommonRef;
                    end else begin
                        goto label0;
                    end;
                end;
                OPER_VECT_MULS, OPER_VECT_MULU: begin
                    if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_SHORT8) then begin
                        typeReturnRef := typeCommonRef;
                    end else begin
                        goto label0;
                    end;
                end;
                OPER_VECT_DIV: begin
                    if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_SHORT8) then begin
                        primitiveKind := AVT_FLOAT + (primitiveKind and 3);
                        typeCommonRef := getPrimitiveType(primitiveKind);
                        cast(operand0Node, code, typeCommonRef);
                        cast(operand1Node, code, typeCommonRef);
                    end else
                    if (primitiveKind >= AVT_INT) and (primitiveKind <= AVT_INT8) then begin
                        primitiveKind := AVT_DOUBLE + (primitiveKind and 3);
                        typeCommonRef := getPrimitiveType(primitiveKind);
                        cast(operand0Node, code, typeCommonRef);
                        cast(operand1Node, code, typeCommonRef);
                    end;
                    if (primitiveKind >= AVT_FLOAT) and (primitiveKind <= AVT_DOUBLE8) then begin
                        typeReturnRef := typeCommonRef;
                    end else begin
                        goto label0;
                    end;
                end;
                end;
                operand0Node := cast(operand0Node, code, typeCommonRef);
                operand1Node := cast(operand1Node, code, typeCommonRef);
                expressionNode.dataType := typeReturnRef;
                expressionNode.operand1 := typeCommonRef;
                continue;
            end;
            if typeOperand0Ref is AVTTypeStructured then begin
                argumentTypes := Vector.create();
                try
                    argumentTypes.append(ValueOfObject.create(typeOperand1Ref, false));
                    foundMethod := AVTTypeStructured(typeOperand0Ref).findMethod(AVTOperator.operatorToSpecName(operatorKind), argumentTypes, typeRef, operatorPos);
                    isRight := (foundMethod <> nil) and foundMethod.isConvertableArgumentTypes(argumentTypes);
                finally
                    argumentTypes.free();
                end;
                if isRight then begin
                    if not foundMethod.isVisible(AVTTypeStructured(typeOperand0Ref), typeRef) then begin
                        raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
                    end;
                    cast(operand1Node, code, foundMethod.getArgumentAt(0).valueType);
                    if foundMethod.parentType.isService() then begin
                        instruction := INVOKE_SERVICE;
                    end else begin
                        instruction := INVOKE_VIRTUAL;
                    end;
                    expressionNode.setData(expressionNode.lineIndex, foundMethod.returnType, instruction, foundMethod);
                    continue;
                end;
            end;
            label0:
            dst.free();
            raise AVTCompilerException.create('The operator ' + AVTLexer.lexemeToString(operatorKind) + ' is undefined for the argument types ' + itemToString(typeOperand0Ref) + ', ' + itemToString(typeOperand1Ref), source, operatorPos);
        until false;
        result := pos;
    end;

    function AVTCodeBuilder.parseAdditive(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
    label
        label0;
    var
        isRight: boolean;
        instruction: int;
        operatorPos: int;
        operatorKind: int;
        primitiveKind: int;
        dst: AVTConstant;
        op0: AVTConstant;
        op1: AVTConstant;
        argumentTypes: Vector;
        foundMethod: AVTMethod;
        typeReturnRef: AVTType;
        typeCommonRef: AVTType;
        typeOperand0Ref: AVTType;
        typeOperand1Ref: AVTType;
        expressionNode: AVTNode;
        operand0Node: AVTNode;
        operand1Node: AVTNode;
        typeString: AVTTypeStructured;
    begin
        pos := parseMultiplicative(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
        repeat
            operatorKind := source.getLexemeType(pos);
            case operatorKind of
            OPER_SCAL_ADD, OPER_SCAL_SUB, OPER_VECT_ADD, OPER_VECT_ADDS, OPER_VECT_ADDU, OPER_VECT_SUB, OPER_VECT_SUBS, OPER_VECT_SUBU: begin
                operatorPos := pos;
                operand0Node := parentNode.lastChild();
                expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, operatorKind, nil);
                code.moveNode(operand0Node, expressionNode, 0);
                pos := parseMultiplicative(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
            end
            else
                break;
            end;
            dst := nil;
            operand1Node := expressionNode.lastChild();
            typeOperand0Ref := operand0Node.dataType;
            typeOperand1Ref := operand1Node.dataType;
            typeCommonRef := commonType(typeOperand0Ref, typeOperand1Ref);
            if typeCommonRef is AVTTypePrimitive then begin
                primitiveKind := AVTTypePrimitive(typeCommonRef).primitiveKind;
                if (operand0Node.instruction = LOAD_CONST) and (operand1Node.instruction = LOAD_CONST) then begin
                    op0 := operand0Node.operand1 as AVTConstant;
                    op1 := operand1Node.operand1 as AVTConstant;
                    cast(op0, op0, AVTTypePrimitive(typeCommonRef));
                    cast(op1, op1, AVTTypePrimitive(typeCommonRef));
                    dst := AVTConstant.create();
                    case operatorKind of
                    OPER_SCAL_ADD: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteScalAdd(dst, op0, op1);
                        AVT_BYTE2:
                            byte2ScalAdd(dst, op0, op1);
                        AVT_BYTE4:
                            byte4ScalAdd(dst, op0, op1);
                        AVT_BYTE8:
                            byte8ScalAdd(dst, op0, op1);
                        AVT_SHORT:
                            shortScalAdd(dst, op0, op1);
                        AVT_SHORT2:
                            short2ScalAdd(dst, op0, op1);
                        AVT_SHORT4:
                            short4ScalAdd(dst, op0, op1);
                        AVT_SHORT8:
                            short8ScalAdd(dst, op0, op1);
                        AVT_INT:
                            intScalAdd(dst, op0, op1);
                        AVT_INT2:
                            int2ScalAdd(dst, op0, op1);
                        AVT_INT4:
                            int4ScalAdd(dst, op0, op1);
                        AVT_INT8:
                            int8ScalAdd(dst, op0, op1);
                        AVT_LONG:
                            longScalAdd(dst, op0, op1);
                        AVT_LONG2:
                            long2ScalAdd(dst, op0, op1);
                        AVT_LONG4:
                            long4ScalAdd(dst, op0, op1);
                        AVT_LONG8:
                            long8ScalAdd(dst, op0, op1);
                        AVT_FLOAT:
                            floatScalAdd(dst, op0, op1);
                        AVT_FLOAT2:
                            float2ScalAdd(dst, op0, op1);
                        AVT_FLOAT4:
                            float4ScalAdd(dst, op0, op1);
                        AVT_FLOAT8:
                            float8ScalAdd(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleScalAdd(dst, op0, op1);
                        AVT_DOUBLE2:
                            double2ScalAdd(dst, op0, op1);
                        AVT_DOUBLE4:
                            double4ScalAdd(dst, op0, op1);
                        AVT_DOUBLE8:
                            double8ScalAdd(dst, op0, op1);
                        AVT_REAL:
                            realScalAdd(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_SCAL_SUB: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteScalSub(dst, op0, op1);
                        AVT_BYTE2:
                            byte2ScalSub(dst, op0, op1);
                        AVT_BYTE4:
                            byte4ScalSub(dst, op0, op1);
                        AVT_BYTE8:
                            byte8ScalSub(dst, op0, op1);
                        AVT_SHORT:
                            shortScalSub(dst, op0, op1);
                        AVT_SHORT2:
                            short2ScalSub(dst, op0, op1);
                        AVT_SHORT4:
                            short4ScalSub(dst, op0, op1);
                        AVT_SHORT8:
                            short8ScalSub(dst, op0, op1);
                        AVT_INT:
                            intScalSub(dst, op0, op1);
                        AVT_INT2:
                            int2ScalSub(dst, op0, op1);
                        AVT_INT4:
                            int4ScalSub(dst, op0, op1);
                        AVT_INT8:
                            int8ScalSub(dst, op0, op1);
                        AVT_LONG:
                            longScalSub(dst, op0, op1);
                        AVT_LONG2:
                            long2ScalSub(dst, op0, op1);
                        AVT_LONG4:
                            long4ScalSub(dst, op0, op1);
                        AVT_LONG8:
                            long8ScalSub(dst, op0, op1);
                        AVT_FLOAT:
                            floatScalSub(dst, op0, op1);
                        AVT_FLOAT2:
                            float2ScalSub(dst, op0, op1);
                        AVT_FLOAT4:
                            float4ScalSub(dst, op0, op1);
                        AVT_FLOAT8:
                            float8ScalSub(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleScalSub(dst, op0, op1);
                        AVT_DOUBLE2:
                            double2ScalSub(dst, op0, op1);
                        AVT_DOUBLE4:
                            double4ScalSub(dst, op0, op1);
                        AVT_DOUBLE8:
                            double8ScalSub(dst, op0, op1);
                        AVT_REAL:
                            realScalSub(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_VECT_ADD: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteVectAdd(dst, op0, op1);
                        AVT_BYTE2:
                            byte2VectAdd(dst, op0, op1);
                        AVT_BYTE4:
                            byte4VectAdd(dst, op0, op1);
                        AVT_BYTE8:
                            byte8VectAdd(dst, op0, op1);
                        AVT_SHORT:
                            shortVectAdd(dst, op0, op1);
                        AVT_SHORT2:
                            short2VectAdd(dst, op0, op1);
                        AVT_SHORT4:
                            short4VectAdd(dst, op0, op1);
                        AVT_SHORT8:
                            short8VectAdd(dst, op0, op1);
                        AVT_INT:
                            intVectAdd(dst, op0, op1);
                        AVT_INT2:
                            int2VectAdd(dst, op0, op1);
                        AVT_INT4:
                            int4VectAdd(dst, op0, op1);
                        AVT_INT8:
                            int8VectAdd(dst, op0, op1);
                        AVT_LONG:
                            longVectAdd(dst, op0, op1);
                        AVT_LONG2:
                            long2VectAdd(dst, op0, op1);
                        AVT_LONG4:
                            long4VectAdd(dst, op0, op1);
                        AVT_LONG8:
                            long8VectAdd(dst, op0, op1);
                        AVT_FLOAT:
                            floatVectAdd(dst, op0, op1);
                        AVT_FLOAT2:
                            float2VectAdd(dst, op0, op1);
                        AVT_FLOAT4:
                            float4VectAdd(dst, op0, op1);
                        AVT_FLOAT8:
                            float8VectAdd(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleVectAdd(dst, op0, op1);
                        AVT_DOUBLE2:
                            double2VectAdd(dst, op0, op1);
                        AVT_DOUBLE4:
                            double4VectAdd(dst, op0, op1);
                        AVT_DOUBLE8:
                            double8VectAdd(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_VECT_ADDS: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteVectAdds(dst, op0, op1);
                        AVT_BYTE2:
                            byte2VectAdds(dst, op0, op1);
                        AVT_BYTE4:
                            byte4VectAdds(dst, op0, op1);
                        AVT_BYTE8:
                            byte8VectAdds(dst, op0, op1);
                        AVT_SHORT:
                            shortVectAdds(dst, op0, op1);
                        AVT_SHORT2:
                            short2VectAdds(dst, op0, op1);
                        AVT_SHORT4:
                            short4VectAdds(dst, op0, op1);
                        AVT_SHORT8:
                            short8VectAdds(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_VECT_ADDU: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteVectAddu(dst, op0, op1);
                        AVT_BYTE2:
                            byte2VectAddu(dst, op0, op1);
                        AVT_BYTE4:
                            byte4VectAddu(dst, op0, op1);
                        AVT_BYTE8:
                            byte8VectAddu(dst, op0, op1);
                        AVT_SHORT:
                            shortVectAddu(dst, op0, op1);
                        AVT_SHORT2:
                            short2VectAddu(dst, op0, op1);
                        AVT_SHORT4:
                            short4VectAddu(dst, op0, op1);
                        AVT_SHORT8:
                            short8VectAddu(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_VECT_SUB: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteVectSub(dst, op0, op1);
                        AVT_BYTE2:
                            byte2VectSub(dst, op0, op1);
                        AVT_BYTE4:
                            byte4VectSub(dst, op0, op1);
                        AVT_BYTE8:
                            byte8VectSub(dst, op0, op1);
                        AVT_SHORT:
                            shortVectSub(dst, op0, op1);
                        AVT_SHORT2:
                            short2VectSub(dst, op0, op1);
                        AVT_SHORT4:
                            short4VectSub(dst, op0, op1);
                        AVT_SHORT8:
                            short8VectSub(dst, op0, op1);
                        AVT_INT:
                            intVectSub(dst, op0, op1);
                        AVT_INT2:
                            int2VectSub(dst, op0, op1);
                        AVT_INT4:
                            int4VectSub(dst, op0, op1);
                        AVT_INT8:
                            int8VectSub(dst, op0, op1);
                        AVT_LONG:
                            longVectSub(dst, op0, op1);
                        AVT_LONG2:
                            long2VectSub(dst, op0, op1);
                        AVT_LONG4:
                            long4VectSub(dst, op0, op1);
                        AVT_LONG8:
                            long8VectSub(dst, op0, op1);
                        AVT_FLOAT:
                            floatVectSub(dst, op0, op1);
                        AVT_FLOAT2:
                            float2VectSub(dst, op0, op1);
                        AVT_FLOAT4:
                            float4VectSub(dst, op0, op1);
                        AVT_FLOAT8:
                            float8VectSub(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleVectSub(dst, op0, op1);
                        AVT_DOUBLE2:
                            double2VectSub(dst, op0, op1);
                        AVT_DOUBLE4:
                            double4VectSub(dst, op0, op1);
                        AVT_DOUBLE8:
                            double8VectSub(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_VECT_SUBS: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteVectSubs(dst, op0, op1);
                        AVT_BYTE2:
                            byte2VectSubs(dst, op0, op1);
                        AVT_BYTE4:
                            byte4VectSubs(dst, op0, op1);
                        AVT_BYTE8:
                            byte8VectSubs(dst, op0, op1);
                        AVT_SHORT:
                            shortVectSubs(dst, op0, op1);
                        AVT_SHORT2:
                            short2VectSubs(dst, op0, op1);
                        AVT_SHORT4:
                            short4VectSubs(dst, op0, op1);
                        AVT_SHORT8:
                            short8VectSubs(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_VECT_SUBU: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteVectSubu(dst, op0, op1);
                        AVT_BYTE2:
                            byte2VectSubu(dst, op0, op1);
                        AVT_BYTE4:
                            byte4VectSubu(dst, op0, op1);
                        AVT_BYTE8:
                            byte8VectSubu(dst, op0, op1);
                        AVT_SHORT:
                            shortVectSubu(dst, op0, op1);
                        AVT_SHORT2:
                            short2VectSubu(dst, op0, op1);
                        AVT_SHORT4:
                            short4VectSubu(dst, op0, op1);
                        AVT_SHORT8:
                            short8VectSubu(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    end;
                    expressionNode.setData(expressionNode.lineIndex, dst.valueType, LOAD_CONST, dst);
                    code.removeNode(operand1Node);
                    code.removeNode(operand0Node);
                    continue;
                end;
                case operatorKind of
                OPER_SCAL_ADD, OPER_SCAL_SUB: begin
                    if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_SHORT8) then begin
                        typeReturnRef := getPrimitiveType(AVT_INT + (primitiveKind and 3));
                    end else
                    if (primitiveKind >= AVT_INT) and (primitiveKind <= AVT_DOUBLE8) or (primitiveKind = AVT_REAL) then begin
                        typeReturnRef := typeCommonRef;
                    end else begin
                        goto label0;
                    end;
                end;
                OPER_VECT_ADD, OPER_VECT_SUB: begin
                    if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_DOUBLE8) then begin
                        typeReturnRef := typeCommonRef;
                    end else begin
                        goto label0;
                    end;
                end;
                OPER_VECT_ADDS, OPER_VECT_ADDU, OPER_VECT_SUBS, OPER_VECT_SUBU: begin
                    if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_SHORT8) then begin
                        typeReturnRef := typeCommonRef;
                    end else begin
                        goto label0;
                    end;
                end;
                end;
                operand0Node := cast(operand0Node, code, typeCommonRef);
                operand1Node := cast(operand1Node, code, typeCommonRef);
                expressionNode.dataType := typeReturnRef;
                expressionNode.operand1 := typeCommonRef;
                continue;
            end;
            if typeOperand0Ref is AVTTypeStructured then begin
                typeString := getStringType();
                if (operatorKind = OPER_SCAL_ADD) and (typeOperand0Ref = typeString) and (operand0Node.instruction = LOAD_CONST) and (typeOperand1Ref = typeString) and (operand1Node.instruction = LOAD_CONST) then begin
                    op0 := operand0Node.operand1 as AVTConstant;
                    op1 := operand1Node.operand1 as AVTConstant;
                    dst := AVTConstant.create(typeString);
                    dst.value.asString := op0.value.asString + op1.value.asString;
                    expressionNode.setData(expressionNode.lineIndex, typeString, LOAD_CONST, dst);
                    code.removeNode(operand1Node);
                    code.removeNode(operand0Node);
                    continue;
                end;
                argumentTypes := Vector.create();
                try
                    argumentTypes.append(ValueOfObject.create(typeOperand1Ref, false));
                    foundMethod := AVTTypeStructured(typeOperand0Ref).findMethod(AVTOperator.operatorToSpecName(operatorKind), argumentTypes, typeRef, operatorPos);
                    isRight := (foundMethod <> nil) and foundMethod.isConvertableArgumentTypes(argumentTypes);
                finally
                    argumentTypes.free();
                end;
                if isRight then begin
                    if not foundMethod.isVisible(AVTTypeStructured(typeOperand0Ref), typeRef) then begin
                        raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
                    end;
                    cast(operand1Node, code, foundMethod.getArgumentAt(0).valueType);
                    if foundMethod.parentType.isService() then begin
                        instruction := INVOKE_SERVICE;
                    end else begin
                        instruction := INVOKE_VIRTUAL;
                    end;
                    expressionNode.setData(expressionNode.lineIndex, foundMethod.returnType, instruction, foundMethod);
                    continue;
                end;
            end;
            label0:
            dst.free();
            raise AVTCompilerException.create('The operator ' + AVTLexer.lexemeToString(operatorKind) + ' is undefined for the argument types ' + itemToString(typeOperand0Ref) + ', ' + itemToString(typeOperand1Ref), source, operatorPos);
        until false;
        result := pos;
    end;

    function AVTCodeBuilder.parseShift(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
    label
        label0;
    var
        isChar: boolean;
        isRight: boolean;
        instruction: int;
        operatorPos: int;
        operatorKind: int;
        primitiveKind: int;
        dst: AVTConstant;
        op0: AVTConstant;
        op1: AVTConstant;
        argumentTypes: Vector;
        foundMethod: AVTMethod;
        typeReturnRef: AVTType;
        typeOperand0Ref: AVTType;
        typeOperand1Ref: AVTType;
        expressionNode: AVTNode;
        operand0Node: AVTNode;
        operand1Node: AVTNode;
    begin
        pos := parseAdditive(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
        repeat
            operatorKind := source.getLexemeType(pos);
            case operatorKind of
            OPER_SCAL_SAR, OPER_SCAL_SAL, OPER_SCAL_SHR, OPER_VECT_SAR, OPER_VECT_SAL, OPER_VECT_SHR: begin
                operatorPos := pos;
                operand0Node := parentNode.lastChild();
                expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, operatorKind, nil);
                code.moveNode(operand0Node, expressionNode, 0);
                pos := parseAdditive(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
            end
            else
                break;
            end;
            dst := nil;
            operand1Node := expressionNode.lastChild();
            typeOperand0Ref := operand0Node.dataType;
            typeOperand1Ref := operand1Node.dataType;
            if (typeOperand0Ref is AVTTypePrimitive) and (typeOperand1Ref is AVTTypePrimitive) then begin
                primitiveKind := AVTTypePrimitive(typeOperand0Ref).primitiveKind;
                if primitiveKind = AVT_CHAR then begin
                    isChar := true;
                    primitiveKind := AVT_INT;
                    typeOperand0Ref := getPrimitiveType(AVT_INT);
                end else begin
                    isChar := false;
                end;
                if ((primitiveKind < AVT_BYTE) or (primitiveKind > AVT_LONG8)) or not typeOperand1Ref.isInt() then begin
                    goto label0;
                end;
                if (operand0Node.instruction = LOAD_CONST) and (operand1Node.instruction = LOAD_CONST) then begin
                    op0 := operand0Node.operand1 as AVTConstant;
                    op1 := operand1Node.operand1 as AVTConstant;
                    if isChar then begin
                        op0.value.asInt := int(op0.value.asChar);
                    end;
                    dst := AVTConstant.create();
                    case operatorKind of
                    OPER_SCAL_SAR: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteScalSar(dst, op0, op1);
                        AVT_BYTE2:
                            byte2ScalSar(dst, op0, op1);
                        AVT_BYTE4:
                            byte4ScalSar(dst, op0, op1);
                        AVT_BYTE8:
                            byte8ScalSar(dst, op0, op1);
                        AVT_SHORT:
                            shortScalSar(dst, op0, op1);
                        AVT_SHORT2:
                            short2ScalSar(dst, op0, op1);
                        AVT_SHORT4:
                            short4ScalSar(dst, op0, op1);
                        AVT_SHORT8:
                            short8ScalSar(dst, op0, op1);
                        AVT_INT:
                            intScalSar(dst, op0, op1);
                        AVT_INT2:
                            int2ScalSar(dst, op0, op1);
                        AVT_INT4:
                            int4ScalSar(dst, op0, op1);
                        AVT_INT8:
                            int8ScalSar(dst, op0, op1);
                        AVT_LONG:
                            longScalSar(dst, op0, op1);
                        AVT_LONG2:
                            long2ScalSar(dst, op0, op1);
                        AVT_LONG4:
                            long4ScalSar(dst, op0, op1);
                        AVT_LONG8:
                            long8ScalSar(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_SCAL_SAL: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteScalSal(dst, op0, op1);
                        AVT_BYTE2:
                            byte2ScalSal(dst, op0, op1);
                        AVT_BYTE4:
                            byte4ScalSal(dst, op0, op1);
                        AVT_BYTE8:
                            byte8ScalSal(dst, op0, op1);
                        AVT_SHORT:
                            shortScalSal(dst, op0, op1);
                        AVT_SHORT2:
                            short2ScalSal(dst, op0, op1);
                        AVT_SHORT4:
                            short4ScalSal(dst, op0, op1);
                        AVT_SHORT8:
                            short8ScalSal(dst, op0, op1);
                        AVT_INT:
                            intScalSal(dst, op0, op1);
                        AVT_INT2:
                            int2ScalSal(dst, op0, op1);
                        AVT_INT4:
                            int4ScalSal(dst, op0, op1);
                        AVT_INT8:
                            int8ScalSal(dst, op0, op1);
                        AVT_LONG:
                            longScalSal(dst, op0, op1);
                        AVT_LONG2:
                            long2ScalSal(dst, op0, op1);
                        AVT_LONG4:
                            long4ScalSal(dst, op0, op1);
                        AVT_LONG8:
                            long8ScalSal(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_SCAL_SHR: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteScalShr(dst, op0, op1);
                        AVT_BYTE2:
                            byte2ScalShr(dst, op0, op1);
                        AVT_BYTE4:
                            byte4ScalShr(dst, op0, op1);
                        AVT_BYTE8:
                            byte8ScalShr(dst, op0, op1);
                        AVT_SHORT:
                            shortScalShr(dst, op0, op1);
                        AVT_SHORT2:
                            short2ScalShr(dst, op0, op1);
                        AVT_SHORT4:
                            short4ScalShr(dst, op0, op1);
                        AVT_SHORT8:
                            short8ScalShr(dst, op0, op1);
                        AVT_INT:
                            intScalShr(dst, op0, op1);
                        AVT_INT2:
                            int2ScalShr(dst, op0, op1);
                        AVT_INT4:
                            int4ScalShr(dst, op0, op1);
                        AVT_INT8:
                            int8ScalShr(dst, op0, op1);
                        AVT_LONG:
                            longScalShr(dst, op0, op1);
                        AVT_LONG2:
                            long2ScalShr(dst, op0, op1);
                        AVT_LONG4:
                            long4ScalShr(dst, op0, op1);
                        AVT_LONG8:
                            long8ScalShr(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_VECT_SAR: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteVectSar(dst, op0, op1);
                        AVT_BYTE2:
                            byte2VectSar(dst, op0, op1);
                        AVT_BYTE4:
                            byte4VectSar(dst, op0, op1);
                        AVT_BYTE8:
                            byte8VectSar(dst, op0, op1);
                        AVT_SHORT:
                            shortVectSar(dst, op0, op1);
                        AVT_SHORT2:
                            short2VectSar(dst, op0, op1);
                        AVT_SHORT4:
                            short4VectSar(dst, op0, op1);
                        AVT_SHORT8:
                            short8VectSar(dst, op0, op1);
                        AVT_INT:
                            intVectSar(dst, op0, op1);
                        AVT_INT2:
                            int2VectSar(dst, op0, op1);
                        AVT_INT4:
                            int4VectSar(dst, op0, op1);
                        AVT_INT8:
                            int8VectSar(dst, op0, op1);
                        AVT_LONG:
                            longVectSar(dst, op0, op1);
                        AVT_LONG2:
                            long2VectSar(dst, op0, op1);
                        AVT_LONG4:
                            long4VectSar(dst, op0, op1);
                        AVT_LONG8:
                            long8VectSar(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_VECT_SAL: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteVectSal(dst, op0, op1);
                        AVT_BYTE2:
                            byte2VectSal(dst, op0, op1);
                        AVT_BYTE4:
                            byte4VectSal(dst, op0, op1);
                        AVT_BYTE8:
                            byte8VectSal(dst, op0, op1);
                        AVT_SHORT:
                            shortVectSal(dst, op0, op1);
                        AVT_SHORT2:
                            short2VectSal(dst, op0, op1);
                        AVT_SHORT4:
                            short4VectSal(dst, op0, op1);
                        AVT_SHORT8:
                            short8VectSal(dst, op0, op1);
                        AVT_INT:
                            intVectSal(dst, op0, op1);
                        AVT_INT2:
                            int2VectSal(dst, op0, op1);
                        AVT_INT4:
                            int4VectSal(dst, op0, op1);
                        AVT_INT8:
                            int8VectSal(dst, op0, op1);
                        AVT_LONG:
                            longVectSal(dst, op0, op1);
                        AVT_LONG2:
                            long2VectSal(dst, op0, op1);
                        AVT_LONG4:
                            long4VectSal(dst, op0, op1);
                        AVT_LONG8:
                            long8VectSal(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_VECT_SHR: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteVectShr(dst, op0, op1);
                        AVT_BYTE2:
                            byte2VectShr(dst, op0, op1);
                        AVT_BYTE4:
                            byte4VectShr(dst, op0, op1);
                        AVT_BYTE8:
                            byte8VectShr(dst, op0, op1);
                        AVT_SHORT:
                            shortVectShr(dst, op0, op1);
                        AVT_SHORT2:
                            short2VectShr(dst, op0, op1);
                        AVT_SHORT4:
                            short4VectShr(dst, op0, op1);
                        AVT_SHORT8:
                            short8VectShr(dst, op0, op1);
                        AVT_INT:
                            intVectShr(dst, op0, op1);
                        AVT_INT2:
                            int2VectShr(dst, op0, op1);
                        AVT_INT4:
                            int4VectShr(dst, op0, op1);
                        AVT_INT8:
                            int8VectShr(dst, op0, op1);
                        AVT_LONG:
                            longVectShr(dst, op0, op1);
                        AVT_LONG2:
                            long2VectShr(dst, op0, op1);
                        AVT_LONG4:
                            long4VectShr(dst, op0, op1);
                        AVT_LONG8:
                            long8VectShr(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    end;
                    expressionNode.setData(expressionNode.lineIndex, dst.valueType, LOAD_CONST, dst);
                    code.removeNode(operand1Node);
                    code.removeNode(operand0Node);
                    continue;
                end;
                case operatorKind of
                OPER_SCAL_SAR, OPER_SCAL_SAL, OPER_SCAL_SHR: begin
                    if primitiveKind < AVT_INT then begin
                        typeReturnRef := getPrimitiveType(AVT_INT + (primitiveKind and 3));
                    end else begin
                        typeReturnRef := typeOperand0Ref;
                    end;
                end;
                OPER_VECT_SAR, OPER_VECT_SAL, OPER_VECT_SHR: begin
                    typeReturnRef := typeOperand0Ref;
                end;
                end;
                expressionNode.dataType := typeReturnRef;
                expressionNode.operand1 := typeOperand0Ref;
                continue;
            end;
            if typeOperand0Ref is AVTTypeStructured then begin
                argumentTypes := Vector.create();
                try
                    argumentTypes.append(ValueOfObject.create(typeOperand1Ref, false));
                    foundMethod := AVTTypeStructured(typeOperand0Ref).findMethod(AVTOperator.operatorToSpecName(operatorKind), argumentTypes, typeRef, operatorPos);
                    isRight := (foundMethod <> nil) and foundMethod.isConvertableArgumentTypes(argumentTypes);
                finally
                    argumentTypes.free();
                end;
                if isRight then begin
                    if not foundMethod.isVisible(AVTTypeStructured(typeOperand0Ref), typeRef) then begin
                        raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
                    end;
                    cast(operand1Node, code, foundMethod.getArgumentAt(0).valueType);
                    if foundMethod.parentType.isService() then begin
                        instruction := INVOKE_SERVICE;
                    end else begin
                        instruction := INVOKE_VIRTUAL;
                    end;
                    expressionNode.setData(expressionNode.lineIndex, foundMethod.returnType, instruction, foundMethod);
                    continue;
                end;
            end;
            label0:
            dst.free();
            raise AVTCompilerException.create('The operator ' + AVTLexer.lexemeToString(operatorKind) + ' is undefined for the argument types ' + itemToString(typeOperand0Ref) + ', ' + itemToString(typeOperand1Ref), source, operatorPos);
        until false;
        result := pos;
    end;

    function AVTCodeBuilder.parseRelational(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
    label
        label0;
    var
        isRight: boolean;
        instruction: int;
        operatorPos: int;
        operatorKind: int;
        primitiveKind: int;
        dst: AVTConstant;
        op0: AVTConstant;
        op1: AVTConstant;
        argumentTypes: Vector;
        foundMethod: AVTMethod;
        typeReturnRef: AVTType;
        typeCommonRef: AVTType;
        typeOperand0Ref: AVTType;
        typeOperand1Ref: AVTType;
        expressionNode: AVTNode;
        operand0Node: AVTNode;
        operand1Node: AVTNode;
    begin
        pos := parseShift(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
        repeat
            operatorKind := source.getLexemeType(pos);
            case operatorKind of
            AVT_INSTANCEOF: begin
                operatorPos := pos;
                typeReturnRef := parseType(parentNode, methodRef, typeRef, source, pos + 1);
                if not(typeReturnRef is AVTTypeStructured) then begin
                    raise AVTCompilerException.create('Reference type expected', source, operatorPos + 1);
                end;
                operand0Node := parentNode.lastChild();
                typeOperand0Ref := operand0Node.dataType;
                if (typeOperand0Ref <> nil) and not(typeOperand0Ref is AVTTypeStructured) then begin
                    raise AVTCompilerException.create('The operator instanceof is undefined for the argument type ' + itemToString(typeOperand0Ref), source, operatorPos);
                end;
                if typeOperand0Ref is AVTTypeArray then begin
                    AVTTypeArray(typeOperand0Ref).makeCompilable();
                end;
                expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(operatorPos), getPrimitiveType(AVT_BOOLEAN), AVT_INSTANCEOF, typeReturnRef);
                code.moveNode(operand0Node, expressionNode, 0);
                pos := source.position;
                continue;
            end;
            OPER_SCAL_G, OPER_SCAL_GE, OPER_SCAL_L, OPER_SCAL_LE, OPER_VECT_G, OPER_VECT_GE, OPER_VECT_L, OPER_VECT_LE: begin
                operatorPos := pos;
                operand0Node := parentNode.lastChild();
                expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, operatorKind, nil);
                code.moveNode(operand0Node, expressionNode, 0);
                pos := parseShift(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
            end
            else
                break;
            end;
            dst := nil;
            operand1Node := expressionNode.lastChild();
            typeOperand0Ref := operand0Node.dataType;
            typeOperand1Ref := operand1Node.dataType;
            typeCommonRef := commonType(typeOperand0Ref, typeOperand1Ref);
            if typeCommonRef is AVTTypePrimitive then begin
                primitiveKind := AVTTypePrimitive(typeCommonRef).primitiveKind;
                if (operand0Node.instruction = LOAD_CONST) and (operand1Node.instruction = LOAD_CONST) then begin
                    op0 := operand0Node.operand1 as AVTConstant;
                    op1 := operand1Node.operand1 as AVTConstant;
                    cast(op0, op0, AVTTypePrimitive(typeCommonRef));
                    cast(op1, op1, AVTTypePrimitive(typeCommonRef));
                    dst := AVTConstant.create();
                    case operatorKind of
                    OPER_SCAL_G: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteScalG(dst, op0, op1);
                        AVT_SHORT:
                            shortScalG(dst, op0, op1);
                        AVT_INT:
                            intScalG(dst, op0, op1);
                        AVT_LONG:
                            longScalG(dst, op0, op1);
                        AVT_FLOAT:
                            floatScalG(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleScalG(dst, op0, op1);
                        AVT_REAL:
                            realScalG(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_SCAL_GE: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteScalGE(dst, op0, op1);
                        AVT_SHORT:
                            shortScalGE(dst, op0, op1);
                        AVT_INT:
                            intScalGE(dst, op0, op1);
                        AVT_LONG:
                            longScalGE(dst, op0, op1);
                        AVT_FLOAT:
                            floatScalGE(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleScalGE(dst, op0, op1);
                        AVT_REAL:
                            realScalGE(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_SCAL_L: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteScalL(dst, op0, op1);
                        AVT_SHORT:
                            shortScalL(dst, op0, op1);
                        AVT_INT:
                            intScalL(dst, op0, op1);
                        AVT_LONG:
                            longScalL(dst, op0, op1);
                        AVT_FLOAT:
                            floatScalL(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleScalL(dst, op0, op1);
                        AVT_REAL:
                            realScalL(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_SCAL_LE: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteScalLE(dst, op0, op1);
                        AVT_SHORT:
                            shortScalLE(dst, op0, op1);
                        AVT_INT:
                            intScalLE(dst, op0, op1);
                        AVT_LONG:
                            longScalLE(dst, op0, op1);
                        AVT_FLOAT:
                            floatScalLE(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleScalLE(dst, op0, op1);
                        AVT_REAL:
                            realScalLE(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_VECT_G: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteVectG(dst, op0, op1);
                        AVT_BYTE2:
                            byte2VectG(dst, op0, op1);
                        AVT_BYTE4:
                            byte4VectG(dst, op0, op1);
                        AVT_BYTE8:
                            byte8VectG(dst, op0, op1);
                        AVT_SHORT:
                            shortVectG(dst, op0, op1);
                        AVT_SHORT2:
                            short2VectG(dst, op0, op1);
                        AVT_SHORT4:
                            short4VectG(dst, op0, op1);
                        AVT_SHORT8:
                            short8VectG(dst, op0, op1);
                        AVT_INT:
                            intVectG(dst, op0, op1);
                        AVT_INT2:
                            int2VectG(dst, op0, op1);
                        AVT_INT4:
                            int4VectG(dst, op0, op1);
                        AVT_INT8:
                            int8VectG(dst, op0, op1);
                        AVT_LONG:
                            longVectG(dst, op0, op1);
                        AVT_LONG2:
                            long2VectG(dst, op0, op1);
                        AVT_LONG4:
                            long4VectG(dst, op0, op1);
                        AVT_LONG8:
                            long8VectG(dst, op0, op1);
                        AVT_FLOAT:
                            floatVectG(dst, op0, op1);
                        AVT_FLOAT2:
                            float2VectG(dst, op0, op1);
                        AVT_FLOAT4:
                            float4VectG(dst, op0, op1);
                        AVT_FLOAT8:
                            float8VectG(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleVectG(dst, op0, op1);
                        AVT_DOUBLE2:
                            double2VectG(dst, op0, op1);
                        AVT_DOUBLE4:
                            double4VectG(dst, op0, op1);
                        AVT_DOUBLE8:
                            double8VectG(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_VECT_GE: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteVectGE(dst, op0, op1);
                        AVT_BYTE2:
                            byte2VectGE(dst, op0, op1);
                        AVT_BYTE4:
                            byte4VectGE(dst, op0, op1);
                        AVT_BYTE8:
                            byte8VectGE(dst, op0, op1);
                        AVT_SHORT:
                            shortVectGE(dst, op0, op1);
                        AVT_SHORT2:
                            short2VectGE(dst, op0, op1);
                        AVT_SHORT4:
                            short4VectGE(dst, op0, op1);
                        AVT_SHORT8:
                            short8VectGE(dst, op0, op1);
                        AVT_INT:
                            intVectGE(dst, op0, op1);
                        AVT_INT2:
                            int2VectGE(dst, op0, op1);
                        AVT_INT4:
                            int4VectGE(dst, op0, op1);
                        AVT_INT8:
                            int8VectGE(dst, op0, op1);
                        AVT_LONG:
                            longVectGE(dst, op0, op1);
                        AVT_LONG2:
                            long2VectGE(dst, op0, op1);
                        AVT_LONG4:
                            long4VectGE(dst, op0, op1);
                        AVT_LONG8:
                            long8VectGE(dst, op0, op1);
                        AVT_FLOAT:
                            floatVectGE(dst, op0, op1);
                        AVT_FLOAT2:
                            float2VectGE(dst, op0, op1);
                        AVT_FLOAT4:
                            float4VectGE(dst, op0, op1);
                        AVT_FLOAT8:
                            float8VectGE(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleVectGE(dst, op0, op1);
                        AVT_DOUBLE2:
                            double2VectGE(dst, op0, op1);
                        AVT_DOUBLE4:
                            double4VectGE(dst, op0, op1);
                        AVT_DOUBLE8:
                            double8VectGE(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_VECT_L: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteVectL(dst, op0, op1);
                        AVT_BYTE2:
                            byte2VectL(dst, op0, op1);
                        AVT_BYTE4:
                            byte4VectL(dst, op0, op1);
                        AVT_BYTE8:
                            byte8VectL(dst, op0, op1);
                        AVT_SHORT:
                            shortVectL(dst, op0, op1);
                        AVT_SHORT2:
                            short2VectL(dst, op0, op1);
                        AVT_SHORT4:
                            short4VectL(dst, op0, op1);
                        AVT_SHORT8:
                            short8VectL(dst, op0, op1);
                        AVT_INT:
                            intVectL(dst, op0, op1);
                        AVT_INT2:
                            int2VectL(dst, op0, op1);
                        AVT_INT4:
                            int4VectL(dst, op0, op1);
                        AVT_INT8:
                            int8VectL(dst, op0, op1);
                        AVT_LONG:
                            longVectL(dst, op0, op1);
                        AVT_LONG2:
                            long2VectL(dst, op0, op1);
                        AVT_LONG4:
                            long4VectL(dst, op0, op1);
                        AVT_LONG8:
                            long8VectL(dst, op0, op1);
                        AVT_FLOAT:
                            floatVectL(dst, op0, op1);
                        AVT_FLOAT2:
                            float2VectL(dst, op0, op1);
                        AVT_FLOAT4:
                            float4VectL(dst, op0, op1);
                        AVT_FLOAT8:
                            float8VectL(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleVectL(dst, op0, op1);
                        AVT_DOUBLE2:
                            double2VectL(dst, op0, op1);
                        AVT_DOUBLE4:
                            double4VectL(dst, op0, op1);
                        AVT_DOUBLE8:
                            double8VectL(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_VECT_LE: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteVectLE(dst, op0, op1);
                        AVT_BYTE2:
                            byte2VectLE(dst, op0, op1);
                        AVT_BYTE4:
                            byte4VectLE(dst, op0, op1);
                        AVT_BYTE8:
                            byte8VectLE(dst, op0, op1);
                        AVT_SHORT:
                            shortVectLE(dst, op0, op1);
                        AVT_SHORT2:
                            short2VectLE(dst, op0, op1);
                        AVT_SHORT4:
                            short4VectLE(dst, op0, op1);
                        AVT_SHORT8:
                            short8VectLE(dst, op0, op1);
                        AVT_INT:
                            intVectLE(dst, op0, op1);
                        AVT_INT2:
                            int2VectLE(dst, op0, op1);
                        AVT_INT4:
                            int4VectLE(dst, op0, op1);
                        AVT_INT8:
                            int8VectLE(dst, op0, op1);
                        AVT_LONG:
                            longVectLE(dst, op0, op1);
                        AVT_LONG2:
                            long2VectLE(dst, op0, op1);
                        AVT_LONG4:
                            long4VectLE(dst, op0, op1);
                        AVT_LONG8:
                            long8VectLE(dst, op0, op1);
                        AVT_FLOAT:
                            floatVectLE(dst, op0, op1);
                        AVT_FLOAT2:
                            float2VectLE(dst, op0, op1);
                        AVT_FLOAT4:
                            float4VectLE(dst, op0, op1);
                        AVT_FLOAT8:
                            float8VectLE(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleVectLE(dst, op0, op1);
                        AVT_DOUBLE2:
                            double2VectLE(dst, op0, op1);
                        AVT_DOUBLE4:
                            double4VectLE(dst, op0, op1);
                        AVT_DOUBLE8:
                            double8VectLE(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    end;
                    expressionNode.setData(expressionNode.lineIndex, dst.valueType, LOAD_CONST, dst);
                    code.removeNode(operand1Node);
                    code.removeNode(operand0Node);
                    continue;
                end;
                case operatorKind of
                OPER_SCAL_G, OPER_SCAL_GE, OPER_SCAL_L, OPER_SCAL_LE: begin
                    if (primitiveKind = AVT_BYTE) or (primitiveKind = AVT_SHORT) or (primitiveKind = AVT_INT) or (primitiveKind = AVT_LONG) or (primitiveKind = AVT_FLOAT) or (primitiveKind = AVT_DOUBLE) or (primitiveKind = AVT_REAL) then begin
                        typeReturnRef := getPrimitiveType(AVT_BOOLEAN);
                    end else begin
                        goto label0;
                    end;
                end;
                OPER_VECT_G, OPER_VECT_GE, OPER_VECT_L, OPER_VECT_LE: begin
                    if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_LONG8) then begin
                        typeReturnRef := typeCommonRef;
                    end else
                    if (primitiveKind >= AVT_FLOAT) and (primitiveKind <= AVT_DOUBLE8) then begin
                        typeReturnRef := getPrimitiveType(AVT_INT + (primitiveKind and 7));
                    end else begin
                        goto label0;
                    end;
                end;
                end;
                operand0Node := cast(operand0Node, code, typeCommonRef);
                operand1Node := cast(operand1Node, code, typeCommonRef);
                expressionNode.dataType := typeReturnRef;
                expressionNode.operand1 := typeCommonRef;
                continue;
            end;
            if typeOperand0Ref is AVTTypeStructured then begin
                argumentTypes := Vector.create();
                try
                    argumentTypes.append(ValueOfObject.create(typeOperand1Ref, false));
                    foundMethod := AVTTypeStructured(typeOperand0Ref).findMethod(AVTOperator.operatorToSpecName(operatorKind), argumentTypes, typeRef, operatorPos);
                    isRight := (foundMethod <> nil) and foundMethod.isConvertableArgumentTypes(argumentTypes);
                finally
                    argumentTypes.free();
                end;
                if isRight then begin
                    if not foundMethod.isVisible(AVTTypeStructured(typeOperand0Ref), typeRef) then begin
                        raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
                    end;
                    cast(operand1Node, code, foundMethod.getArgumentAt(0).valueType);
                    if foundMethod.parentType.isService() then begin
                        instruction := INVOKE_SERVICE;
                    end else begin
                        instruction := INVOKE_VIRTUAL;
                    end;
                    expressionNode.setData(expressionNode.lineIndex, foundMethod.returnType, instruction, foundMethod);
                    continue;
                end;
            end;
            label0:
            dst.free();
            raise AVTCompilerException.create('The operator ' + AVTLexer.lexemeToString(operatorKind) + ' is undefined for the argument types ' + itemToString(typeOperand0Ref) + ', ' + itemToString(typeOperand1Ref), source, operatorPos);
        until false;
        result := pos;
    end;

    function AVTCodeBuilder.parseEquality(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
    label
        label0;
    var
        isRight: boolean;
        instruction: int;
        operatorPos: int;
        operatorKind: int;
        primitiveKind: int;
        dst: AVTConstant;
        op0: AVTConstant;
        op1: AVTConstant;
        argumentTypes: Vector;
        foundMethod: AVTMethod;
        typeReturnRef: AVTType;
        typeCommonRef: AVTType;
        typeOperand0Ref: AVTType;
        typeOperand1Ref: AVTType;
        expressionNode: AVTNode;
        operand0Node: AVTNode;
        operand1Node: AVTNode;
    begin
        pos := parseRelational(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
        repeat
            operatorKind := source.getLexemeType(pos);
            case operatorKind of
            OPER_SCAL_E, OPER_SCAL_NE, OPER_VECT_E, OPER_VECT_NE: begin
                operatorPos := pos;
                operand0Node := parentNode.lastChild();
                expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, operatorKind, nil);
                code.moveNode(operand0Node, expressionNode, 0);
                pos := parseRelational(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
            end
            else
                break;
            end;
            dst := nil;
            operand1Node := expressionNode.lastChild();
            typeOperand0Ref := operand0Node.dataType;
            typeOperand1Ref := operand1Node.dataType;
            typeCommonRef := commonType(typeOperand0Ref, typeOperand1Ref);
            if typeCommonRef is AVTTypePrimitive then begin
                primitiveKind := AVTTypePrimitive(typeCommonRef).primitiveKind;
                if (operand0Node.instruction = LOAD_CONST) and (operand1Node.instruction = LOAD_CONST) then begin
                    op0 := operand0Node.operand1 as AVTConstant;
                    op1 := operand1Node.operand1 as AVTConstant;
                    cast(op0, op0, AVTTypePrimitive(typeCommonRef));
                    cast(op1, op1, AVTTypePrimitive(typeCommonRef));
                    dst := AVTConstant.create();
                    case operatorKind of
                    OPER_SCAL_E: begin
                        case primitiveKind of
                        AVT_BYTE, AVT_BOOLEAN:
                            byteScalE(dst, op0, op1);
                        AVT_BYTE2:
                            byte2ScalE(dst, op0, op1);
                        AVT_BYTE4:
                            byte4ScalE(dst, op0, op1);
                        AVT_BYTE8:
                            byte8ScalE(dst, op0, op1);
                        AVT_SHORT:
                            shortScalE(dst, op0, op1);
                        AVT_SHORT2:
                            short2ScalE(dst, op0, op1);
                        AVT_SHORT4:
                            short4ScalE(dst, op0, op1);
                        AVT_SHORT8:
                            short8ScalE(dst, op0, op1);
                        AVT_INT:
                            intScalE(dst, op0, op1);
                        AVT_INT2:
                            int2ScalE(dst, op0, op1);
                        AVT_INT4:
                            int4ScalE(dst, op0, op1);
                        AVT_INT8:
                            int8ScalE(dst, op0, op1);
                        AVT_LONG:
                            longScalE(dst, op0, op1);
                        AVT_LONG2:
                            long2ScalE(dst, op0, op1);
                        AVT_LONG4:
                            long4ScalE(dst, op0, op1);
                        AVT_LONG8:
                            long8ScalE(dst, op0, op1);
                        AVT_FLOAT:
                            floatScalE(dst, op0, op1);
                        AVT_FLOAT2:
                            float2ScalE(dst, op0, op1);
                        AVT_FLOAT4:
                            float4ScalE(dst, op0, op1);
                        AVT_FLOAT8:
                            float8ScalE(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleScalE(dst, op0, op1);
                        AVT_DOUBLE2:
                            double2ScalE(dst, op0, op1);
                        AVT_DOUBLE4:
                            double4ScalE(dst, op0, op1);
                        AVT_DOUBLE8:
                            double8ScalE(dst, op0, op1);
                        AVT_REAL:
                            realScalE(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_SCAL_NE: begin
                        case primitiveKind of
                        AVT_BYTE, AVT_BOOLEAN:
                            byteScalNE(dst, op0, op1);
                        AVT_BYTE2:
                            byte2ScalNE(dst, op0, op1);
                        AVT_BYTE4:
                            byte4ScalNE(dst, op0, op1);
                        AVT_BYTE8:
                            byte8ScalNE(dst, op0, op1);
                        AVT_SHORT:
                            shortScalNE(dst, op0, op1);
                        AVT_SHORT2:
                            short2ScalNE(dst, op0, op1);
                        AVT_SHORT4:
                            short4ScalNE(dst, op0, op1);
                        AVT_SHORT8:
                            short8ScalNE(dst, op0, op1);
                        AVT_INT:
                            intScalNE(dst, op0, op1);
                        AVT_INT2:
                            int2ScalNE(dst, op0, op1);
                        AVT_INT4:
                            int4ScalNE(dst, op0, op1);
                        AVT_INT8:
                            int8ScalNE(dst, op0, op1);
                        AVT_LONG:
                            longScalNE(dst, op0, op1);
                        AVT_LONG2:
                            long2ScalNE(dst, op0, op1);
                        AVT_LONG4:
                            long4ScalNE(dst, op0, op1);
                        AVT_LONG8:
                            long8ScalNE(dst, op0, op1);
                        AVT_FLOAT:
                            floatScalNE(dst, op0, op1);
                        AVT_FLOAT2:
                            float2ScalNE(dst, op0, op1);
                        AVT_FLOAT4:
                            float4ScalNE(dst, op0, op1);
                        AVT_FLOAT8:
                            float8ScalNE(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleScalNE(dst, op0, op1);
                        AVT_DOUBLE2:
                            double2ScalNE(dst, op0, op1);
                        AVT_DOUBLE4:
                            double4ScalNE(dst, op0, op1);
                        AVT_DOUBLE8:
                            double8ScalNE(dst, op0, op1);
                        AVT_REAL:
                            realScalNE(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_VECT_E: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteVectE(dst, op0, op1);
                        AVT_BYTE2:
                            byte2VectE(dst, op0, op1);
                        AVT_BYTE4:
                            byte4VectE(dst, op0, op1);
                        AVT_BYTE8:
                            byte8VectE(dst, op0, op1);
                        AVT_SHORT:
                            shortVectE(dst, op0, op1);
                        AVT_SHORT2:
                            short2VectE(dst, op0, op1);
                        AVT_SHORT4:
                            short4VectE(dst, op0, op1);
                        AVT_SHORT8:
                            short8VectE(dst, op0, op1);
                        AVT_INT:
                            intVectE(dst, op0, op1);
                        AVT_INT2:
                            int2VectE(dst, op0, op1);
                        AVT_INT4:
                            int4VectE(dst, op0, op1);
                        AVT_INT8:
                            int8VectE(dst, op0, op1);
                        AVT_LONG:
                            longVectE(dst, op0, op1);
                        AVT_LONG2:
                            long2VectE(dst, op0, op1);
                        AVT_LONG4:
                            long4VectE(dst, op0, op1);
                        AVT_LONG8:
                            long8VectE(dst, op0, op1);
                        AVT_FLOAT:
                            floatVectE(dst, op0, op1);
                        AVT_FLOAT2:
                            float2VectE(dst, op0, op1);
                        AVT_FLOAT4:
                            float4VectE(dst, op0, op1);
                        AVT_FLOAT8:
                            float8VectE(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleVectE(dst, op0, op1);
                        AVT_DOUBLE2:
                            double2VectE(dst, op0, op1);
                        AVT_DOUBLE4:
                            double4VectE(dst, op0, op1);
                        AVT_DOUBLE8:
                            double8VectE(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    OPER_VECT_NE: begin
                        case primitiveKind of
                        AVT_BYTE:
                            byteVectNE(dst, op0, op1);
                        AVT_BYTE2:
                            byte2VectNE(dst, op0, op1);
                        AVT_BYTE4:
                            byte4VectNE(dst, op0, op1);
                        AVT_BYTE8:
                            byte8VectNE(dst, op0, op1);
                        AVT_SHORT:
                            shortVectNE(dst, op0, op1);
                        AVT_SHORT2:
                            short2VectNE(dst, op0, op1);
                        AVT_SHORT4:
                            short4VectNE(dst, op0, op1);
                        AVT_SHORT8:
                            short8VectNE(dst, op0, op1);
                        AVT_INT:
                            intVectNE(dst, op0, op1);
                        AVT_INT2:
                            int2VectNE(dst, op0, op1);
                        AVT_INT4:
                            int4VectNE(dst, op0, op1);
                        AVT_INT8:
                            int8VectNE(dst, op0, op1);
                        AVT_LONG:
                            longVectNE(dst, op0, op1);
                        AVT_LONG2:
                            long2VectNE(dst, op0, op1);
                        AVT_LONG4:
                            long4VectNE(dst, op0, op1);
                        AVT_LONG8:
                            long8VectNE(dst, op0, op1);
                        AVT_FLOAT:
                            floatVectNE(dst, op0, op1);
                        AVT_FLOAT2:
                            float2VectNE(dst, op0, op1);
                        AVT_FLOAT4:
                            float4VectNE(dst, op0, op1);
                        AVT_FLOAT8:
                            float8VectNE(dst, op0, op1);
                        AVT_DOUBLE:
                            doubleVectNE(dst, op0, op1);
                        AVT_DOUBLE2:
                            double2VectNE(dst, op0, op1);
                        AVT_DOUBLE4:
                            double4VectNE(dst, op0, op1);
                        AVT_DOUBLE8:
                            double8VectNE(dst, op0, op1);
                        else
                            goto label0;
                        end;
                    end;
                    end;
                    expressionNode.setData(expressionNode.lineIndex, dst.valueType, LOAD_CONST, dst);
                    code.removeNode(operand1Node);
                    code.removeNode(operand0Node);
                    continue;
                end;
                case operatorKind of
                OPER_SCAL_E, OPER_SCAL_NE: begin
                    typeReturnRef := getPrimitiveType(AVT_BOOLEAN);
                end;
                OPER_VECT_E, OPER_VECT_NE: begin
                    if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_LONG8) then begin
                        typeReturnRef := typeCommonRef;
                    end else
                    if (primitiveKind >= AVT_FLOAT) and (primitiveKind <= AVT_DOUBLE8) then begin
                        typeReturnRef := getPrimitiveType(AVT_INT + (primitiveKind and 7));
                    end else begin
                        goto label0;
                    end;
                end;
                end;
                operand0Node := cast(operand0Node, code, typeCommonRef);
                operand1Node := cast(operand1Node, code, typeCommonRef);
                expressionNode.dataType := typeReturnRef;
                expressionNode.operand1 := typeCommonRef;
                continue;
            end;
            if (operatorKind = OPER_SCAL_E) or (operatorKind = OPER_SCAL_NE) then begin
                if typeCommonRef = nil then begin
                    dst := AVTConstant.create(getPrimitiveType(AVT_BOOLEAN));
                    dst.value.asBoolean := operatorKind = OPER_SCAL_E;
                    expressionNode.setData(expressionNode.lineIndex, dst.valueType, LOAD_CONST, dst);
                    code.removeNode(operand1Node);
                    code.removeNode(operand0Node);
                    continue;
                end;
                if typeCommonRef is AVTTypeStructured then begin
                    expressionNode.setData(expressionNode.lineIndex, getPrimitiveType(AVT_BOOLEAN), operatorKind, typeCommonRef);
                    continue;
                end;
            end else
            if typeOperand0Ref is AVTTypeStructured then begin
                argumentTypes := Vector.create();
                try
                    argumentTypes.append(ValueOfObject.create(typeOperand1Ref, false));
                    foundMethod := AVTTypeStructured(typeOperand0Ref).findMethod(AVTOperator.operatorToSpecName(operatorKind), argumentTypes, typeRef, operatorPos);
                    isRight := (foundMethod <> nil) and foundMethod.isConvertableArgumentTypes(argumentTypes);
                finally
                    argumentTypes.free();
                end;
                if isRight then begin
                    if not foundMethod.isVisible(AVTTypeStructured(typeOperand0Ref), typeRef) then begin
                        raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
                    end;
                    cast(operand1Node, code, foundMethod.getArgumentAt(0).valueType);
                    if foundMethod.parentType.isService() then begin
                        instruction := INVOKE_SERVICE;
                    end else begin
                        instruction := INVOKE_VIRTUAL;
                    end;
                    expressionNode.setData(expressionNode.lineIndex, foundMethod.returnType, instruction, foundMethod);
                    continue;
                end;
            end;
            label0:
            dst.free();
            raise AVTCompilerException.create('The operator ' + AVTLexer.lexemeToString(operatorKind) + ' is undefined for the argument types ' + itemToString(typeOperand0Ref) + ', ' + itemToString(typeOperand1Ref), source, operatorPos);
        until false;
        result := pos;
    end;

    function AVTCodeBuilder.parseBitAnd(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
    label
        label0;
    var
        isRight: boolean;
        instruction: int;
        operatorPos: int;
        primitiveKind: int;
        dst: AVTConstant;
        op0: AVTConstant;
        op1: AVTConstant;
        argumentTypes: Vector;
        foundMethod: AVTMethod;
        typeCommonRef: AVTType;
        typeOperand0Ref: AVTType;
        typeOperand1Ref: AVTType;
        expressionNode: AVTNode;
        operand0Node: AVTNode;
        operand1Node: AVTNode;
    begin
        pos := parseEquality(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
        while source.getLexemeType(pos) = OPER_BIT_AND do begin
            operatorPos := pos;
            operand0Node := parentNode.lastChild();
            expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, OPER_BIT_AND, nil);
            code.moveNode(operand0Node, expressionNode, 0);
            pos := parseEquality(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
            dst := nil;
            operand1Node := expressionNode.lastChild();
            typeOperand0Ref := operand0Node.dataType;
            typeOperand1Ref := operand1Node.dataType;
            typeCommonRef := commonType(typeOperand0Ref, typeOperand1Ref);
            if typeCommonRef is AVTTypePrimitive then begin
                primitiveKind := AVTTypePrimitive(typeCommonRef).primitiveKind;
                if (operand0Node.instruction = LOAD_CONST) and (operand1Node.instruction = LOAD_CONST) then begin
                    op0 := operand0Node.operand1 as AVTConstant;
                    op1 := operand1Node.operand1 as AVTConstant;
                    cast(op0, op0, AVTTypePrimitive(typeCommonRef));
                    cast(op1, op1, AVTTypePrimitive(typeCommonRef));
                    dst := AVTConstant.create();
                    case primitiveKind of
                    AVT_BYTE, AVT_BOOLEAN:
                        byteBitAnd(dst, op0, op1);
                    AVT_BYTE2:
                        byte2BitAnd(dst, op0, op1);
                    AVT_BYTE4:
                        byte4BitAnd(dst, op0, op1);
                    AVT_BYTE8:
                        byte8BitAnd(dst, op0, op1);
                    AVT_SHORT:
                        shortBitAnd(dst, op0, op1);
                    AVT_SHORT2:
                        short2BitAnd(dst, op0, op1);
                    AVT_SHORT4:
                        short4BitAnd(dst, op0, op1);
                    AVT_SHORT8:
                        short8BitAnd(dst, op0, op1);
                    AVT_INT:
                        intBitAnd(dst, op0, op1);
                    AVT_INT2:
                        int2BitAnd(dst, op0, op1);
                    AVT_INT4:
                        int4BitAnd(dst, op0, op1);
                    AVT_INT8:
                        int8BitAnd(dst, op0, op1);
                    AVT_LONG:
                        longBitAnd(dst, op0, op1);
                    AVT_LONG2:
                        long2BitAnd(dst, op0, op1);
                    AVT_LONG4:
                        long4BitAnd(dst, op0, op1);
                    AVT_LONG8:
                        long8BitAnd(dst, op0, op1);
                    else
                        goto label0;
                    end;
                    expressionNode.setData(expressionNode.lineIndex, dst.valueType, LOAD_CONST, dst);
                    code.removeNode(operand1Node);
                    code.removeNode(operand0Node);
                    continue;
                end;
                if (primitiveKind <> AVT_BOOLEAN) and ((primitiveKind < AVT_BYTE) or (primitiveKind > AVT_LONG8)) then begin
                    goto label0;
                end;
                operand0Node := cast(operand0Node, code, typeCommonRef);
                operand1Node := cast(operand1Node, code, typeCommonRef);
                expressionNode.dataType := typeCommonRef;
                expressionNode.operand1 := typeCommonRef;
                continue;
            end;
            if typeOperand0Ref is AVTTypeStructured then begin
                argumentTypes := Vector.create();
                try
                    argumentTypes.append(ValueOfObject.create(typeOperand1Ref, false));
                    foundMethod := AVTTypeStructured(typeOperand0Ref).findMethod(AVTOperator.operatorToSpecName(OPER_BIT_AND), argumentTypes, typeRef, operatorPos);
                    isRight := (foundMethod <> nil) and foundMethod.isConvertableArgumentTypes(argumentTypes);
                finally
                    argumentTypes.free();
                end;
                if isRight then begin
                    if not foundMethod.isVisible(AVTTypeStructured(typeOperand0Ref), typeRef) then begin
                        raise AVTCompilerException.create('The operator &' + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
                    end;
                    cast(operand1Node, code, foundMethod.getArgumentAt(0).valueType);
                    if foundMethod.parentType.isService() then begin
                        instruction := INVOKE_SERVICE;
                    end else begin
                        instruction := INVOKE_VIRTUAL;
                    end;
                    expressionNode.setData(expressionNode.lineIndex, foundMethod.returnType, instruction, foundMethod);
                    continue;
                end;
            end;
            label0:
            dst.free();
            raise AVTCompilerException.create('The operator & is undefined for the argument types ' + itemToString(typeOperand0Ref) + ', ' + itemToString(typeOperand1Ref), source, operatorPos);
        end;
        result := pos;
    end;

    function AVTCodeBuilder.parseBitXor(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
    label
        label0;
    var
        isRight: boolean;
        instruction: int;
        operatorPos: int;
        primitiveKind: int;
        dst: AVTConstant;
        op0: AVTConstant;
        op1: AVTConstant;
        argumentTypes: Vector;
        foundMethod: AVTMethod;
        typeCommonRef: AVTType;
        typeOperand0Ref: AVTType;
        typeOperand1Ref: AVTType;
        expressionNode: AVTNode;
        operand0Node: AVTNode;
        operand1Node: AVTNode;
    begin
        pos := parseBitAnd(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
        while source.getLexemeType(pos) = OPER_BIT_XOR do begin
            operatorPos := pos;
            operand0Node := parentNode.lastChild();
            expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, OPER_BIT_XOR, nil);
            code.moveNode(operand0Node, expressionNode, 0);
            pos := parseBitAnd(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
            dst := nil;
            operand1Node := expressionNode.lastChild();
            typeOperand0Ref := operand0Node.dataType;
            typeOperand1Ref := operand1Node.dataType;
            typeCommonRef := commonType(typeOperand0Ref, typeOperand1Ref);
            if typeCommonRef is AVTTypePrimitive then begin
                primitiveKind := AVTTypePrimitive(typeCommonRef).primitiveKind;
                if (operand0Node.instruction = LOAD_CONST) and (operand1Node.instruction = LOAD_CONST) then begin
                    op0 := operand0Node.operand1 as AVTConstant;
                    op1 := operand1Node.operand1 as AVTConstant;
                    cast(op0, op0, AVTTypePrimitive(typeCommonRef));
                    cast(op1, op1, AVTTypePrimitive(typeCommonRef));
                    dst := AVTConstant.create();
                    case primitiveKind of
                    AVT_BYTE, AVT_BOOLEAN:
                        byteBitXor(dst, op0, op1);
                    AVT_BYTE2:
                        byte2BitXor(dst, op0, op1);
                    AVT_BYTE4:
                        byte4BitXor(dst, op0, op1);
                    AVT_BYTE8:
                        byte8BitXor(dst, op0, op1);
                    AVT_SHORT:
                        shortBitXor(dst, op0, op1);
                    AVT_SHORT2:
                        short2BitXor(dst, op0, op1);
                    AVT_SHORT4:
                        short4BitXor(dst, op0, op1);
                    AVT_SHORT8:
                        short8BitXor(dst, op0, op1);
                    AVT_INT:
                        intBitXor(dst, op0, op1);
                    AVT_INT2:
                        int2BitXor(dst, op0, op1);
                    AVT_INT4:
                        int4BitXor(dst, op0, op1);
                    AVT_INT8:
                        int8BitXor(dst, op0, op1);
                    AVT_LONG:
                        longBitXor(dst, op0, op1);
                    AVT_LONG2:
                        long2BitXor(dst, op0, op1);
                    AVT_LONG4:
                        long4BitXor(dst, op0, op1);
                    AVT_LONG8:
                        long8BitXor(dst, op0, op1);
                    else
                        goto label0;
                    end;
                    expressionNode.setData(expressionNode.lineIndex, dst.valueType, LOAD_CONST, dst);
                    code.removeNode(operand1Node);
                    code.removeNode(operand0Node);
                    continue;
                end;
                if (primitiveKind <> AVT_BOOLEAN) and ((primitiveKind < AVT_BYTE) or (primitiveKind > AVT_LONG8)) then begin
                    goto label0;
                end;
                operand0Node := cast(operand0Node, code, typeCommonRef);
                operand1Node := cast(operand1Node, code, typeCommonRef);
                expressionNode.dataType := typeCommonRef;
                expressionNode.operand1 := typeCommonRef;
                continue;
            end;
            if typeOperand0Ref is AVTTypeStructured then begin
                argumentTypes := Vector.create();
                try
                    argumentTypes.append(ValueOfObject.create(typeOperand1Ref, false));
                    foundMethod := AVTTypeStructured(typeOperand0Ref).findMethod(AVTOperator.operatorToSpecName(OPER_BIT_XOR), argumentTypes, typeRef, operatorPos);
                    isRight := (foundMethod <> nil) and foundMethod.isConvertableArgumentTypes(argumentTypes);
                finally
                    argumentTypes.free();
                end;
                if isRight then begin
                    if not foundMethod.isVisible(AVTTypeStructured(typeOperand0Ref), typeRef) then begin
                        raise AVTCompilerException.create('The operator ^' + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
                    end;
                    cast(operand1Node, code, foundMethod.getArgumentAt(0).valueType);
                    if foundMethod.parentType.isService() then begin
                        instruction := INVOKE_SERVICE;
                    end else begin
                        instruction := INVOKE_VIRTUAL;
                    end;
                    expressionNode.setData(expressionNode.lineIndex, foundMethod.returnType, instruction, foundMethod);
                    continue;
                end;
            end;
            label0:
            dst.free();
            raise AVTCompilerException.create('The operator ^ is undefined for the argument types ' + itemToString(typeOperand0Ref) + ', ' + itemToString(typeOperand1Ref), source, operatorPos);
        end;
        result := pos;
    end;

    function AVTCodeBuilder.parseBitOr(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
    label
        label0;
    var
        isRight: boolean;
        instruction: int;
        operatorPos: int;
        primitiveKind: int;
        dst: AVTConstant;
        op0: AVTConstant;
        op1: AVTConstant;
        argumentTypes: Vector;
        foundMethod: AVTMethod;
        typeCommonRef: AVTType;
        typeOperand0Ref: AVTType;
        typeOperand1Ref: AVTType;
        expressionNode: AVTNode;
        operand0Node: AVTNode;
        operand1Node: AVTNode;
    begin
        pos := parseBitXor(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
        while source.getLexemeType(pos) = OPER_BIT_OR do begin
            operatorPos := pos;
            operand0Node := parentNode.lastChild();
            expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, OPER_BIT_OR, nil);
            code.moveNode(operand0Node, expressionNode, 0);
            pos := parseBitXor(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
            dst := nil;
            operand1Node := expressionNode.lastChild();
            typeOperand0Ref := operand0Node.dataType;
            typeOperand1Ref := operand1Node.dataType;
            typeCommonRef := commonType(typeOperand0Ref, typeOperand1Ref);
            if typeCommonRef is AVTTypePrimitive then begin
                primitiveKind := AVTTypePrimitive(typeCommonRef).primitiveKind;
                if (operand0Node.instruction = LOAD_CONST) and (operand1Node.instruction = LOAD_CONST) then begin
                    op0 := operand0Node.operand1 as AVTConstant;
                    op1 := operand1Node.operand1 as AVTConstant;
                    cast(op0, op0, AVTTypePrimitive(typeCommonRef));
                    cast(op1, op1, AVTTypePrimitive(typeCommonRef));
                    dst := AVTConstant.create();
                    case primitiveKind of
                    AVT_BYTE, AVT_BOOLEAN:
                        byteBitOr(dst, op0, op1);
                    AVT_BYTE2:
                        byte2BitOr(dst, op0, op1);
                    AVT_BYTE4:
                        byte4BitOr(dst, op0, op1);
                    AVT_BYTE8:
                        byte8BitOr(dst, op0, op1);
                    AVT_SHORT:
                        shortBitOr(dst, op0, op1);
                    AVT_SHORT2:
                        short2BitOr(dst, op0, op1);
                    AVT_SHORT4:
                        short4BitOr(dst, op0, op1);
                    AVT_SHORT8:
                        short8BitOr(dst, op0, op1);
                    AVT_INT:
                        intBitOr(dst, op0, op1);
                    AVT_INT2:
                        int2BitOr(dst, op0, op1);
                    AVT_INT4:
                        int4BitOr(dst, op0, op1);
                    AVT_INT8:
                        int8BitOr(dst, op0, op1);
                    AVT_LONG:
                        longBitOr(dst, op0, op1);
                    AVT_LONG2:
                        long2BitOr(dst, op0, op1);
                    AVT_LONG4:
                        long4BitOr(dst, op0, op1);
                    AVT_LONG8:
                        long8BitOr(dst, op0, op1);
                    else
                        goto label0;
                    end;
                    expressionNode.setData(expressionNode.lineIndex, dst.valueType, LOAD_CONST, dst);
                    code.removeNode(operand1Node);
                    code.removeNode(operand0Node);
                    continue;
                end;
                if (primitiveKind <> AVT_BOOLEAN) and ((primitiveKind < AVT_BYTE) or (primitiveKind > AVT_LONG8)) then begin
                    goto label0;
                end;
                operand0Node := cast(operand0Node, code, typeCommonRef);
                operand1Node := cast(operand1Node, code, typeCommonRef);
                expressionNode.dataType := typeCommonRef;
                expressionNode.operand1 := typeCommonRef;
                continue;
            end;
            if typeOperand0Ref is AVTTypeStructured then begin
                argumentTypes := Vector.create();
                try
                    argumentTypes.append(ValueOfObject.create(typeOperand1Ref, false));
                    foundMethod := AVTTypeStructured(typeOperand0Ref).findMethod(AVTOperator.operatorToSpecName(OPER_BIT_OR), argumentTypes, typeRef, operatorPos);
                    isRight := (foundMethod <> nil) and foundMethod.isConvertableArgumentTypes(argumentTypes);
                finally
                    argumentTypes.free();
                end;
                if isRight then begin
                    if not foundMethod.isVisible(AVTTypeStructured(typeOperand0Ref), typeRef) then begin
                        raise AVTCompilerException.create('The operator |' + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
                    end;
                    cast(operand1Node, code, foundMethod.getArgumentAt(0).valueType);
                    if foundMethod.parentType.isService() then begin
                        instruction := INVOKE_SERVICE;
                    end else begin
                        instruction := INVOKE_VIRTUAL;
                    end;
                    expressionNode.setData(expressionNode.lineIndex, foundMethod.returnType, instruction, foundMethod);
                    continue;
                end;
            end;
            label0:
            dst.free();
            raise AVTCompilerException.create('The operator | is undefined for the argument types ' + itemToString(typeOperand0Ref) + ', ' + itemToString(typeOperand1Ref), source, operatorPos);
        end;
        result := pos;
    end;

    function AVTCodeBuilder.parseBoolAnd(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
    var
        operatorPos: int;
        dst: AVTConstant;
        op0: AVTConstant;
        op1: AVTConstant;
        typeCommonRef: AVTType;
        typeOperand0Ref: AVTType;
        typeOperand1Ref: AVTType;
        expressionNode: AVTNode;
        operand0Node: AVTNode;
        operand1Node: AVTNode;
    begin
        pos := parseBitOr(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
        while source.getLexemeType(pos) = OPER_BOOL_AND do begin
            operatorPos := pos;
            operand0Node := parentNode.lastChild();
            expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, OPER_BOOL_AND);
            code.moveNode(operand0Node, expressionNode, 0);
            pos := parseBitOr(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
            dst := nil;
            operand1Node := expressionNode.lastChild();
            typeOperand0Ref := operand0Node.dataType;
            typeOperand1Ref := operand1Node.dataType;
            typeCommonRef := commonType(typeOperand0Ref, typeOperand1Ref);
            if (typeCommonRef is AVTTypePrimitive) and typeCommonRef.isBoolean() then begin
                if (operand0Node.instruction = LOAD_CONST) and (operand1Node.instruction = LOAD_CONST) then begin
                    op0 := operand0Node.operand1 as AVTConstant;
                    op1 := operand1Node.operand1 as AVTConstant;
                    dst := AVTConstant.create(typeCommonRef);
                    dst.value.asBoolean := op0.value.asBoolean and op1.value.asBoolean;
                    expressionNode.setData(expressionNode.lineIndex, typeCommonRef, LOAD_CONST, dst);
                    code.removeNode(operand1Node);
                    code.removeNode(operand0Node);
                    continue;
                end;
                expressionNode.dataType := typeCommonRef;
                continue;
            end;
            dst.free();
            raise AVTCompilerException.create('The operator && is undefined for the argument types ' + itemToString(typeOperand0Ref) + ', ' + itemToString(typeOperand1Ref), source, operatorPos);
        end;
        result := pos;
    end;

    function AVTCodeBuilder.parseBoolOr(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
    var
        operatorPos: int;
        dst: AVTConstant;
        op0: AVTConstant;
        op1: AVTConstant;
        typeCommonRef: AVTType;
        typeOperand0Ref: AVTType;
        typeOperand1Ref: AVTType;
        expressionNode: AVTNode;
        operand0Node: AVTNode;
        operand1Node: AVTNode;
    begin
        pos := parseBoolAnd(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
        while source.getLexemeType(pos) = OPER_BOOL_OR do begin
            operatorPos := pos;
            operand0Node := parentNode.lastChild();
            expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, OPER_BOOL_OR);
            code.moveNode(operand0Node, expressionNode, 0);
            pos := parseBoolAnd(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
            dst := nil;
            operand1Node := expressionNode.lastChild();
            typeOperand0Ref := operand0Node.dataType;
            typeOperand1Ref := operand1Node.dataType;
            typeCommonRef := commonType(typeOperand0Ref, typeOperand1Ref);
            if (typeCommonRef is AVTTypePrimitive) and typeCommonRef.isBoolean() then begin
                if (operand0Node.instruction = LOAD_CONST) and (operand1Node.instruction = LOAD_CONST) then begin
                    op0 := operand0Node.operand1 as AVTConstant;
                    op1 := operand1Node.operand1 as AVTConstant;
                    dst := AVTConstant.create(typeCommonRef);
                    dst.value.asBoolean := op0.value.asBoolean or op1.value.asBoolean;
                    expressionNode.setData(expressionNode.lineIndex, typeCommonRef, LOAD_CONST, dst);
                    code.removeNode(operand1Node);
                    code.removeNode(operand0Node);
                    continue;
                end;
                expressionNode.dataType := typeCommonRef;
                continue;
            end;
            dst.free();
            raise AVTCompilerException.create('The operator || is undefined for the argument types ' + itemToString(typeOperand0Ref) + ', ' + itemToString(typeOperand1Ref), source, operatorPos);
        end;
        result := pos;
    end;

    function AVTCodeBuilder.parseConditional(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
    var
        operatorPos: int;
        typeCommonRef: AVTType;
        typeOperand0Ref: AVTType;
        typeOperand1Ref: AVTType;
        typeOperand2Ref: AVTType;
        expressionNode: AVTNode;
        operand0Node: AVTNode;
        operand1Node: AVTNode;
        operand2Node: AVTNode;
    begin
        pos := parseBoolOr(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
        if source.getLexemeType(pos) = CHAR_QUESTION then begin
            operand0Node := parentNode.lastChild();
            typeOperand0Ref := operand0Node.dataType;
            if (typeOperand0Ref = nil) or not typeOperand0Ref.isBoolean() then begin
                raise AVTCompilerException.create('The operator ?: is undefined for the argument type ' + itemToString(typeOperand0Ref), source, pos);
            end;
            expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, OPER_BOOL_COND);
            code.moveNode(operand0Node, expressionNode, 0);
            operatorPos := parseExpression(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
            if source.getLexemeType(operatorPos) <> CHAR_COLON then begin
                raise AVTCompilerException.create('":" expected', source, operatorPos);
            end;
            operand1Node := expressionNode.lastChild();
            code.appendNode(expressionNode).setData(source.getLexemeLineIndex(operatorPos), getPrimitiveType(AVT_VOID), JUMP);
            pos := parseExpression(expressionNode, code, methodRef, typeRef, source, operatorPos + 1, ignoreInstanceMembers);
            operand2Node := expressionNode.lastChild();
            needValue(operand1Node, code);
            needValue(operand2Node, code);
            typeOperand1Ref := operand1Node.dataType;
            typeOperand2Ref := operand2Node.dataType;
            typeCommonRef := commonType(typeOperand1Ref, typeOperand2Ref);
            if typeCommonRef is AVTTypeInvalid then begin
                raise AVTCompilerException.create('The operator ?: is undefined for the argument types ' + itemToString(typeOperand1Ref) + ', ' + itemToString(typeOperand2Ref), source, operatorPos);
            end;
            cast(operand1Node, code, typeCommonRef);
            cast(operand2Node, code, typeCommonRef);
            expressionNode.dataType := typeCommonRef;
        end;
        result := pos;
    end;

    function AVTCodeBuilder.parseExpression(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
    label
        label0, label1;
    var
        i: int;
        lineIndex: int;
        lexemeType: int;
        instruction: int;
        operatorPos: int;
        operatorKind: int;
        primitiveKind: int;
        argumentTypes: Vector;
        foundField: AVTField;
        foundMethod: AVTMethod;
        foundMethodSet: AVTMethod;
        foundProperty: AVTProperty;
        foundVariable: AVTVariable;
        operandNode: AVTNode;
        operatorNode: AVTNode;
        leftSideNode: AVTNode;
        rightSideNode: AVTNode;
        typeVoidRef: AVTType;
        typeReturnRef: AVTType;
        typeLeftSideRef: AVTType;
        typeRightSideRef: AVTType;
        typeDereferenceRef: AVTTypeStructured;
    begin
        pos := parseConditional(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
        lexemeType := source.getLexemeType(pos);
        case lexemeType of
        CHAR_EQUALS: begin
            operatorPos := pos;
            leftSideNode := parentNode.lastChild();
            instruction := leftSideNode.instruction;
            case instruction of
            LOAD_VARIABLE: begin
                typeLeftSideRef := (leftSideNode.operand1 as AVTVariable).valueType;
                pos := parseExpression(leftSideNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
                rightSideNode := leftSideNode.lastChild();
                needValue(rightSideNode, code);
                typeRightSideRef := rightSideNode.dataType;
                if not typeLeftSideRef.isConvertableFrom(typeRightSideRef) then begin
                    raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeRightSideRef) + ' to ' + itemToString(typeLeftSideRef), source, operatorPos);
                end;
                cast(rightSideNode, code, typeLeftSideRef);
                leftSideNode.dataType := getPrimitiveType(AVT_VOID);
                leftSideNode.instruction := STORE_VARIABLE;
            end;
            LOAD_STATIC: begin
                foundField := leftSideNode.operand1 as AVTField;
                if foundField.isFinal() and (not(methodRef is AVTClassInit) or (foundField.parentType <> methodRef.parentType) or (foundField.implementationPosition >= 0)) then begin
                    raise AVTCompilerException.create('The final field ' + foundField.fullName + ' can not be assigned', source, operatorPos);
                end;
                typeLeftSideRef := foundField.valueType;
                pos := parseExpression(leftSideNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
                rightSideNode := leftSideNode.lastChild();
                needValue(rightSideNode, code);
                typeRightSideRef := rightSideNode.dataType;
                if not typeLeftSideRef.isConvertableFrom(typeRightSideRef) then begin
                    raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeRightSideRef) + ' to ' + itemToString(typeLeftSideRef), source, operatorPos);
                end;
                cast(rightSideNode, code, typeLeftSideRef);
                leftSideNode.dataType := getPrimitiveType(AVT_VOID);
                leftSideNode.instruction := STORE_STATIC;
            end;
            GET_FIELD: begin
                foundField := leftSideNode.operand1 as AVTField;
                operandNode := leftSideNode[0];
                if foundField.isFinal() and (not(methodRef is AVTInstInit) or (foundField.parentType <> methodRef.parentType) or (operandNode.instruction <> LOAD_VARIABLE) or (operandNode.operand1 <> methodRef.argumentThis)) then begin
                    raise AVTCompilerException.create('The final field ' + foundField.fullName + ' can not be assigned', source, operatorPos);
                end;
                typeLeftSideRef := foundField.valueType;
                pos := parseExpression(leftSideNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
                rightSideNode := leftSideNode.lastChild();
                needValue(rightSideNode, code);
                typeRightSideRef := rightSideNode.dataType;
                if not typeLeftSideRef.isConvertableFrom(typeRightSideRef) then begin
                    raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeRightSideRef) + ' to ' + itemToString(typeLeftSideRef), source, operatorPos);
                end;
                cast(rightSideNode, code, typeLeftSideRef);
                leftSideNode.dataType := getPrimitiveType(AVT_VOID);
                leftSideNode.instruction := SET_FIELD;
            end;
            GET_PROPERTY, SET_PROPERTY: begin
                if leftSideNode.length > 1 then begin
                    raise AVTCompilerException.create('The operator = applicable only to variables, properties and array elements', source, operatorPos);
                end;
                foundProperty := leftSideNode.operand1 as AVTProperty;
                if foundProperty.writeSynthetic = nil then begin
                    raise AVTCompilerException.create('The read-only property ' + foundProperty.simpleName + ' can not be assigned', source, operatorPos);
                end;
                typeLeftSideRef := foundProperty.valueType;
                pos := parseExpression(leftSideNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
                rightSideNode := leftSideNode.lastChild();
                needValue(rightSideNode, code);
                typeRightSideRef := rightSideNode.dataType;
                if not typeLeftSideRef.isConvertableFrom(typeRightSideRef) then begin
                    raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeRightSideRef) + ' to ' + itemToString(typeLeftSideRef), source, operatorPos);
                end;
                cast(rightSideNode, code, typeLeftSideRef);
                leftSideNode.dataType := getPrimitiveType(AVT_VOID);
                leftSideNode.instruction := SET_PROPERTY;
            end;
            GET_ARRAY_ELEMENT: begin
                typeLeftSideRef := leftSideNode.operand1 as AVTType;
                pos := parseExpression(leftSideNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
                rightSideNode := leftSideNode.lastChild();
                needValue(rightSideNode, code);
                typeRightSideRef := rightSideNode.dataType;
                if not typeLeftSideRef.isConvertableFrom(typeRightSideRef) then begin
                    raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeRightSideRef) + ' to ' + itemToString(typeLeftSideRef), source, operatorPos);
                end;
                cast(rightSideNode, code, typeLeftSideRef);
                leftSideNode.dataType := getPrimitiveType(AVT_VOID);
                leftSideNode.instruction := SET_ARRAY_ELEMENT;
            end;
            INVOKE_SPECIAL, INVOKE_VIRTUAL, INVOKE_SERVICE: begin
                foundMethod := leftSideNode.operand1 as AVTMethod;
                if foundMethod is AVTOperator then begin
                    operatorKind := AVTOperator(foundMethod).operatorKind;
                end else begin
                    operatorKind := -1;
                end;
                if (operatorKind = GET_ARRAY_ELEMENT) or (operatorKind = SET_ARRAY_ELEMENT) then begin
                    if leftSideNode.length > 2 then begin
                        raise AVTCompilerException.create('The operator = applicable only to variables, properties and array elements', source, operatorPos);
                    end;
                    pos := parseExpression(leftSideNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
                    rightSideNode := leftSideNode.lastChild();
                    needValue(rightSideNode, code);
                    typeRightSideRef := rightSideNode.dataType;
                    typeDereferenceRef := leftSideNode[0].dataType as AVTTypeStructured;
                    argumentTypes := Vector.create();
                    try
                        argumentTypes.append(ValueOfObject.create(leftSideNode[1].dataType, false));
                        argumentTypes.append(ValueOfObject.create(typeRightSideRef, false));
                        foundMethod := typeDereferenceRef.findMethod(AVTOperator.operatorToSpecName(SET_ARRAY_ELEMENT), argumentTypes, typeRef, operatorPos);
                        if (foundMethod = nil) or not foundMethod.isConvertableArgumentTypes(argumentTypes) then begin
                            raise AVTCompilerException.create('The operator []=' + argumentTypes.toString() + ' is undefined for the type ' + typeDereferenceRef.fullName, source, operatorPos);
                        end;
                    finally
                        argumentTypes.free();
                    end;
                    if not foundMethod.isVisible(typeDereferenceRef, typeRef) then begin
                        raise AVTCompilerException.create('The operator []=' + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
                    end;
                    if (instruction = INVOKE_SPECIAL) and foundMethod.isAbstract() then begin
                        raise AVTCompilerException.create('Can not directly invoke abstract operator []=' + foundMethod.argumentsToString() + ' from the type ' + foundMethod.parentType.fullName, source, operatorPos);
                    end;
                    for i := foundMethod.getArgumentsCount() - 1 downto 0 do begin
                        cast(leftSideNode[i + 1], code, foundMethod.getArgumentAt(i).valueType);
                    end;
                    if (instruction <> INVOKE_SPECIAL) or foundMethod.isAbstract() then begin
                        if foundMethod.parentType.isService() then begin
                            instruction := INVOKE_SERVICE;
                        end else begin
                            instruction := INVOKE_VIRTUAL;
                        end;
                    end;
                    leftSideNode.setData(leftSideNode.lineIndex, getPrimitiveType(AVT_VOID), instruction, foundMethod);
                end else begin
                    foundProperty := foundMethod.linkedProperty;
                    if (leftSideNode.length > 1) or (foundProperty = nil) or ((foundProperty.readSynthetic <> foundMethod) and (foundProperty.writeSynthetic <> foundMethod)) then begin
                        raise AVTCompilerException.create('The operator = applicable only to variables, properties and array elements', source, operatorPos);
                    end;
                    foundMethod := foundProperty.writeSynthetic;
                    if foundMethod = nil then begin
                        raise AVTCompilerException.create('The read-only property ' + foundProperty.simpleName + ' can not be assigned', source, operatorPos);
                    end;
                    pos := parseExpression(leftSideNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
                    rightSideNode := leftSideNode.lastChild();
                    needValue(rightSideNode, code);
                    typeRightSideRef := rightSideNode.dataType;
                    typeLeftSideRef := foundProperty.valueType;
                    if not typeLeftSideRef.isConvertableFrom(typeRightSideRef) then begin
                        raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeRightSideRef) + ' to ' + itemToString(typeLeftSideRef), source, operatorPos);
                    end;
                    cast(rightSideNode, code, typeLeftSideRef);
                    leftSideNode.dataType := getPrimitiveType(AVT_VOID);
                    leftSideNode.operand1 := foundMethod;
                end;
            end
            else
                raise AVTCompilerException.create('The operator = applicable only to variables, properties and array elements', source, operatorPos);
            end;
        end;
        ASGN_BIT_AND, ASGN_BIT_OR, ASGN_BIT_XOR,
        ASGN_SCAL_MUL, ASGN_SCAL_DIV, ASGN_SCAL_DIVU, ASGN_SCAL_REM, ASGN_SCAL_REMU,
        ASGN_SCAL_ADD, ASGN_SCAL_SUB, ASGN_SCAL_SAR, ASGN_SCAL_SAL, ASGN_SCAL_SHR,
        ASGN_VECT_MUL, ASGN_VECT_DIV, ASGN_VECT_ADD, ASGN_VECT_SUB, ASGN_VECT_SAR, ASGN_VECT_SAL, ASGN_VECT_SHR,
        ASGN_VECT_G, ASGN_VECT_GE, ASGN_VECT_L, ASGN_VECT_LE, ASGN_VECT_E, ASGN_VECT_NE,
        ASGN_VECT_MULS, ASGN_VECT_ADDS, ASGN_VECT_SUBS, ASGN_VECT_MULU, ASGN_VECT_ADDU, ASGN_VECT_SUBU: begin
            operatorPos := pos;
            operatorKind := lexemeType - 256;
            leftSideNode := parentNode.lastChild();
            lineIndex := source.getLexemeLineIndex(pos);
            operatorNode := code.appendNode(leftSideNode, lineIndex, nil, operatorKind, nil);
            pos := parseExpression(operatorNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
            rightSideNode := operatorNode.lastChild();
            needValue(rightSideNode, code);
            typeRightSideRef := rightSideNode.dataType;
            if (typeRightSideRef = nil) or not typeRightSideRef.isNumeric() and not typeRightSideRef.isBoolean() then begin
                raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + '= is undefined for the argument type ' + itemToString(typeRightSideRef), source, operatorPos);
            end;
            instruction := leftSideNode.instruction;
            case instruction of
            LOAD_VARIABLE: begin
                foundVariable := leftSideNode.operand1 as AVTVariable;
                typeLeftSideRef := foundVariable.valueType;
                typeVoidRef := getPrimitiveType(AVT_VOID);
                operandNode := code.insertNode(operatorNode, 0, lineIndex, typeLeftSideRef, LOAD_VARIABLE, foundVariable);
                leftSideNode.dataType := typeVoidRef;
                leftSideNode.instruction := STORE_VARIABLE;
            end;
            LOAD_STATIC: begin
                foundField := leftSideNode.operand1 as AVTField;
                if foundField.isFinal() then begin
                    raise AVTCompilerException.create('The final field ' + foundField.fullName + ' can not be assigned', source, operatorPos);
                end;
                typeLeftSideRef := foundField.valueType;
                typeVoidRef := getPrimitiveType(AVT_VOID);
                operandNode := code.insertNode(operatorNode, 0, lineIndex, typeLeftSideRef, LOAD_STATIC, foundField);
                leftSideNode.dataType := typeVoidRef;
                leftSideNode.instruction := STORE_STATIC;
            end;
            GET_FIELD: begin
                foundField := leftSideNode.operand1 as AVTField;
                if foundField.isFinal() then begin
                    raise AVTCompilerException.create('The final field ' + foundField.fullName + ' can not be assigned', source, operatorPos);
                end;
                typeLeftSideRef := foundField.valueType;
                typeVoidRef := getPrimitiveType(AVT_VOID);
                operandNode := code.insertNode(operatorNode, 0, lineIndex, typeLeftSideRef, GET_FIELD, foundField);
                code.appendNode(operandNode).setData(lineIndex, typeVoidRef, DUP1);
                leftSideNode.dataType := typeVoidRef;
                leftSideNode.instruction := SET_FIELD;
            end;
            GET_PROPERTY: begin
                foundProperty := leftSideNode.operand1 as AVTProperty;
                if foundProperty.writeSynthetic = nil then begin
                    raise AVTCompilerException.create('The read-only property ' + foundProperty.simpleName + ' can not be assigned', source, operatorPos);
                end;
                typeLeftSideRef := foundProperty.valueType;
                typeVoidRef := getPrimitiveType(AVT_VOID);
                operandNode := code.insertNode(operatorNode, 0, lineIndex, typeLeftSideRef, GET_PROPERTY, foundProperty);
                code.appendNode(operandNode).setData(lineIndex, typeVoidRef, DUP1);
                leftSideNode.dataType := typeVoidRef;
                leftSideNode.instruction := SET_PROPERTY;
            end;
            GET_ARRAY_ELEMENT: begin
                typeLeftSideRef := leftSideNode.operand1 as AVTType;
                typeVoidRef := getPrimitiveType(AVT_VOID);
                operandNode := code.insertNode(operatorNode, 0, lineIndex, typeLeftSideRef, GET_ARRAY_ELEMENT, typeLeftSideRef);
                code.appendNode(operandNode).setData(lineIndex, typeVoidRef, DUP2);
                leftSideNode.dataType := typeVoidRef;
                leftSideNode.instruction := SET_ARRAY_ELEMENT;
            end;
            INVOKE_SPECIAL, INVOKE_VIRTUAL, INVOKE_SERVICE: begin
                foundMethod := leftSideNode.operand1 as AVTMethod;
                if (foundMethod is AVTOperator) and (AVTOperator(foundMethod).operatorKind = GET_ARRAY_ELEMENT) then begin
                    typeLeftSideRef := foundMethod.returnType;
                    typeVoidRef := getPrimitiveType(AVT_VOID);
                    typeDereferenceRef := leftSideNode[0].dataType as AVTTypeStructured;
                    argumentTypes := Vector.create();
                    try
                        argumentTypes.append(ValueOfObject.create(leftSideNode[1].dataType, false));
                        argumentTypes.append(ValueOfObject.create(typeLeftSideRef, false));
                        foundMethodSet := typeDereferenceRef.findMethod(AVTOperator.operatorToSpecName(SET_ARRAY_ELEMENT), argumentTypes, typeRef, operatorPos);
                        if (foundMethodSet = nil) or not foundMethodSet.isIdentityArgumentTypes(argumentTypes) then begin
                            raise AVTCompilerException.create('The operator []=' + argumentTypes.toString() + ' is undefined for the type ' + typeDereferenceRef.fullName, source, operatorPos);
                        end;
                    finally
                        argumentTypes.free();
                    end;
                    if not foundMethodSet.isVisible(typeDereferenceRef, typeRef) then begin
                        raise AVTCompilerException.create('The operator []=' + foundMethodSet.argumentsToString() + ' in the type ' + foundMethodSet.parentType.fullName + ' is not visible', source, operatorPos);
                    end;
                    if (instruction = INVOKE_SPECIAL) and foundMethodSet.isAbstract() then begin
                        raise AVTCompilerException.create('Can not directly invoke abstract operator []=' + foundMethodSet.argumentsToString() + ' from the type ' + foundMethodSet.parentType.fullName, source, operatorPos);
                    end;
                    for i := foundMethodSet.getArgumentsCount() - 1 downto 0 do begin
                        cast(leftSideNode[i + 1], code, foundMethodSet.getArgumentAt(i).valueType);
                    end;
                    operandNode := code.insertNode(operatorNode, 0, lineIndex, typeLeftSideRef, instruction, foundMethod);
                    code.appendNode(operandNode).setData(lineIndex, typeVoidRef, DUP2);
                    if (instruction <> INVOKE_SPECIAL) or foundMethodSet.isAbstract() then begin
                        if foundMethodSet.parentType.isService() then begin
                            instruction := INVOKE_SERVICE;
                        end else begin
                            instruction := INVOKE_VIRTUAL;
                        end;
                    end;
                    leftSideNode.setData(leftSideNode.lineIndex, typeVoidRef, instruction, foundMethodSet);
                end else begin
                    foundProperty := foundMethod.linkedProperty;
                    if (foundProperty = nil) or (foundProperty.readSynthetic <> foundMethod) then begin
                        raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + '= applicable only to variables, properties and array elements', source, operatorPos);
                    end;
                    foundMethodSet := foundProperty.writeSynthetic;
                    if foundMethodSet = nil then begin
                        raise AVTCompilerException.create('The read-only property ' + foundProperty.simpleName + ' can not be assigned', source, operatorPos);
                    end;
                    typeLeftSideRef := foundProperty.valueType;
                    typeVoidRef := getPrimitiveType(AVT_VOID);
                    operandNode := code.insertNode(operatorNode, 0, lineIndex, typeLeftSideRef, instruction, foundMethod);
                    code.appendNode(operandNode).setData(lineIndex, typeVoidRef, DUP1);
                    leftSideNode.setData(leftSideNode.lineIndex, typeVoidRef, instruction, foundMethodSet);
                end;
            end
            else
                raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + '= applicable only to variables, properties and array elements', source, operatorPos);
            end;
            case operatorKind of
            OPER_SCAL_SAR, OPER_SCAL_SAL, OPER_SCAL_SHR, OPER_VECT_SAR, OPER_VECT_SAL, OPER_VECT_SHR: begin
                if not getPrimitiveType(AVT_INT).isConvertableFrom(typeRightSideRef) then begin
                    raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeRightSideRef) + ' to int', source, operatorPos);
                end;
            end
            else
                if not typeLeftSideRef.isConvertableFrom(typeRightSideRef) then begin
                    raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeRightSideRef) + ' to ' + itemToString(typeLeftSideRef), source, operatorPos);
                end;
                cast(rightSideNode, code, typeLeftSideRef);
            end;
            primitiveKind := (typeLeftSideRef as AVTTypePrimitive).primitiveKind;
            begin
                begin
                    case operatorKind of
                    OPER_BIT_AND, OPER_BIT_OR, OPER_BIT_XOR: begin
                        if (primitiveKind = AVT_BOOLEAN) or (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_LONG8) then begin
                            typeReturnRef := typeLeftSideRef;
                        end else begin
                            goto label0;
                        end;
                    end;
                    OPER_VECT_SAR, OPER_VECT_SAL, OPER_VECT_SHR,
                    OPER_VECT_G, OPER_VECT_GE, OPER_VECT_L, OPER_VECT_LE, OPER_VECT_E, OPER_VECT_NE: begin
                        if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_LONG8) then begin
                            typeReturnRef := typeLeftSideRef;
                        end else begin
                            goto label0;
                        end;
                    end;
                    OPER_SCAL_MUL, OPER_SCAL_ADD, OPER_SCAL_SUB: begin
                        if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_SHORT8) then begin
                            typeReturnRef := getPrimitiveType(AVT_INT + (primitiveKind and 3));
                        end else
                        if (primitiveKind >= AVT_INT) and (primitiveKind <= AVT_DOUBLE8) or (primitiveKind = AVT_REAL) then begin
                            typeReturnRef := typeLeftSideRef;
                        end else begin
                            goto label0;
                        end;
                    end;
                    OPER_SCAL_DIV, OPER_SCAL_DIVU: begin
                        if (primitiveKind = AVT_BYTE) or (primitiveKind = AVT_SHORT) then begin
                            typeReturnRef := getPrimitiveType(AVT_INT);
                        end else
                        if (primitiveKind = AVT_INT) or (primitiveKind = AVT_LONG) or (primitiveKind >= AVT_FLOAT) and (primitiveKind <= AVT_DOUBLE8) or (primitiveKind = AVT_REAL) then begin
                            typeReturnRef := typeLeftSideRef;
                        end else begin
                            goto label0;
                        end;
                    end;
                    OPER_SCAL_REM, OPER_SCAL_REMU: begin
                        if (primitiveKind = AVT_BYTE) or (primitiveKind = AVT_SHORT) then begin
                            typeReturnRef := getPrimitiveType(AVT_INT);
                        end else
                        if (primitiveKind = AVT_INT) or (primitiveKind = AVT_LONG) or (primitiveKind = AVT_FLOAT) or (primitiveKind = AVT_DOUBLE) or (primitiveKind = AVT_REAL) then begin
                            typeReturnRef := typeLeftSideRef;
                        end else begin
                            goto label0;
                        end;
                    end;
                    OPER_SCAL_SAR, OPER_SCAL_SAL, OPER_SCAL_SHR: begin
                        if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_SHORT8) then begin
                            typeReturnRef := getPrimitiveType(AVT_INT + (primitiveKind and 3));
                        end else
                        if (primitiveKind >= AVT_INT) and (primitiveKind <= AVT_LONG8) then begin
                            typeReturnRef := typeLeftSideRef;
                        end else begin
                            goto label0;
                        end;
                    end;
                    OPER_VECT_MUL, OPER_VECT_ADD, OPER_VECT_SUB: begin
                        if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_DOUBLE8) then begin
                            typeReturnRef := typeLeftSideRef;
                        end else begin
                            goto label0;
                        end;
                    end;
                    OPER_VECT_DIV: begin
                        if (primitiveKind >= AVT_FLOAT) and (primitiveKind <= AVT_DOUBLE8) then begin
                            typeReturnRef := typeLeftSideRef;
                        end else begin
                            goto label0;
                        end;
                    end;
                    OPER_VECT_MULS, OPER_VECT_ADDS, OPER_VECT_SUBS, OPER_VECT_MULU, OPER_VECT_ADDU, OPER_VECT_SUBU: begin
                        if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_SHORT8) then begin
                            typeReturnRef := typeLeftSideRef;
                        end else begin
                            goto label0;
                        end;
                    end;
                    end;
                    goto label1;
                end;
                label0:
                raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + '= is undefined for the argument type ' + itemToString(typeLeftSideRef), source, operatorPos);
            end;
            label1:
            operatorNode.dataType := typeReturnRef;
            operatorNode.operand1 := typeLeftSideRef;
            if typeReturnRef <> typeLeftSideRef then begin
                cast(operatorNode, code, typeLeftSideRef);
            end;
        end;
        end;
        result := pos;
    end;

    function AVTCodeBuilder.parseLocal(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; variableAllowed: boolean): int;
    var
        namePos: int;
        lineIndex: int;
        name: AnsiString;
        expType: AVTType;
        expNode: AVTNode;
        varType: AVTType;
        varNode: AVTNode;
        varValue: AVTConstant;
    begin
        if variableAllowed then begin
            varType := tryParseType(parentNode, methodRef, typeRef, source, pos);
            namePos := source.position;
        end else begin
            varType := nil;
            namePos := 0;
        end;
        if (varType <> nil) and (source.getLexemeType(namePos) = LITR_NAME) then begin
            name := source.getLexemeAnsiString(namePos);
            if varType.isVoid() then begin
                raise AVTCompilerException.create('void is an invalid type for the variable ' + name, source, namePos);
            end;
            if getVariable(name, parentNode, methodRef) <> nil then begin
                raise AVTCompilerException.create('Duplicate local variable ' + name, source, namePos);
            end;
            lineIndex := source.getLexemeLineIndex(namePos);
            varNode := code.appendNode(parentNode);
            pos := namePos + 1;
            if source.getLexemeType(pos) <> CHAR_EQUALS then begin
                varValue := AVTConstant.create(varType);
                varValue.value.isNull := true;
                code.appendNode(varNode).setData(lineIndex, varType, LOAD_CONST, varValue);
            end else begin
                pos := parseExpression(varNode, code, methodRef, typeRef, source, pos + 1);
                expNode := varNode.lastChild();
                needValue(expNode, code);
                expType := expNode.dataType;
                if not varType.isConvertableFrom(expType) then begin
                    raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(expType) + ' to ' + itemToString(varType), source, namePos + 1);
                end;
                cast(expNode, code, varType);
            end;
            varNode.setData(lineIndex, getPrimitiveType(AVT_VOID), DECLARE_VARIABLE, AVTVariable.create(varType, name, source, namePos));
        end else begin
            pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos);
            expNode := parentNode.lastChild();
            case expNode.instruction of
            STORE_VARIABLE, STORE_STATIC, SET_FIELD, SET_PROPERTY, SET_ARRAY_ELEMENT,
            INVOKE_STATIC, INVOKE_SPECIAL, INVOKE_SERVICE, INVOKE_VIRTUAL, NEW_CLASS, NEW_SERVICE,
            OPER_INCREMENT, OPER_DECREMENT, OPER_INC_POST, OPER_DEC_POST, OPER_INC_PRED, OPER_DEC_PRED:
                discardValue(expNode, code)
            else
                raise AVTCompilerException.create('Method invokation or assignment expected', source, pos);
            end;
        end;
        result := pos;
    end;

    function AVTCodeBuilder.parseBlock(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
    begin
        while source.getLexemeType(pos) <> CHAR_CURLY_CLOSED do begin
            pos := parseStatement(parentNode, code, methodRef, typeRef, source, pos);
        end;
        result := pos + 1;
    end;

    function AVTCodeBuilder.parseDo(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
    var
        expressionNode: AVTNode;
        expressionType: AVTType;
    begin
        pos := parseStatement(parentNode, code, methodRef, typeRef, source, pos);
        if source.getLexemeType(pos) <> AVT_WHILE then begin
            raise AVTCompilerException.create('"while" expected', source, pos);
        end;
        inc(pos);
        if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
            raise AVTCompilerException.create('"(" expected', source, pos);
        end;
        pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos + 1);
        if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then begin
            raise AVTCompilerException.create('")" expected', source, pos);
        end;
        expressionNode := parentNode.lastChild();
        needValue(expressionNode, code);
        expressionType := expressionNode.dataType;
        if (expressionType = nil) or not expressionType.isBoolean() then begin
            raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(expressionType) + ' to boolean', source, pos);
        end;
        if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then begin
            raise AVTCompilerException.create('")" expected', source, pos);
        end;
        inc(pos);
        if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
            raise AVTCompilerException.create('";" expected', source, pos);
        end;
        result := pos + 1;
    end;

    function AVTCodeBuilder.parseIf(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
    var
        expressionNode: AVTNode;
        expressionType: AVTType;
    begin
        if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
            raise AVTCompilerException.create('"(" expected', source, pos);
        end;
        pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos + 1);
        if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then begin
            raise AVTCompilerException.create('")" expected', source, pos);
        end;
        expressionNode := parentNode.lastChild();
        needValue(expressionNode, code);
        expressionType := expressionNode.dataType;
        if (expressionType = nil) or not expressionType.isBoolean() then begin
            raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(expressionType) + ' to boolean', source, pos);
        end;
        pos := parseStatement(parentNode, code, methodRef, typeRef, source, pos + 1);
        if source.getLexemeType(pos) = AVT_ELSE then begin
            code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), JUMP);
            pos := parseStatement(parentNode, code, methodRef, typeRef, source, pos + 1);
        end;
        result := pos;
    end;

    function AVTCodeBuilder.parseFor(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
    var
        index: int;
        stepNode: AVTNode;
        expressionNode: AVTNode;
        expressionType: AVTType;
        typeBooleanRef: AVTType;
        typeVoidRef: AVTType;
        trueConstant: AVTConstant;
    begin
        if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
            raise AVTCompilerException.create('"(" expected', source, pos);
        end;
        inc(pos);
        { инициализация }
        if source.getLexemeType(pos) <> CHAR_SEMICOLON then repeat
            pos := parseLocal(parentNode, code, methodRef, typeRef, source, pos);
            case source.getLexemeType(pos) of
            CHAR_COMMA: begin
                inc(pos);
            end;
            CHAR_SEMICOLON: begin
                break;
            end
            else
                raise AVTCompilerException.create('";" expected', source, pos);
            end;
        until false;
        typeVoidRef := getPrimitiveType(AVT_VOID);
        code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeVoidRef, JUMP);
        inc(pos);
        { условие повтора }
        if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
            pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos);
        end else begin
            typeBooleanRef := getPrimitiveType(AVT_BOOLEAN);
            trueConstant := AVTConstant.create(typeBooleanRef);
            trueConstant.value.asBoolean := true;
            code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeBooleanRef, LOAD_CONST, trueConstant);
        end;
        expressionNode := parentNode.lastChild();
        needValue(expressionNode, code);
        expressionType := expressionNode.dataType;
        if (expressionType = nil) or not expressionType.isBoolean() then begin
            raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(expressionType) + ' to boolean', source, pos);
        end;
        if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
            raise AVTCompilerException.create('";" expected', source, pos);
        end;
        inc(pos);
        { шаг }
        stepNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), typeVoidRef, AVT_BLOCK);
        if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then repeat
            pos := parseLocal(stepNode, code, methodRef, typeRef, source, pos, false);
            case source.getLexemeType(pos) of
            CHAR_COMMA: begin
                inc(pos);
            end;
            CHAR_PARENTH_CLOSED: begin
                break;
            end
            else
                raise AVTCompilerException.create('")" expected', source, pos);
            end;
        until false;
        { тело цикла }
        pos := parseStatement(parentNode, code, methodRef, typeRef, source, pos + 1);
        { перестановка узлов }
        index := parentNode.length;
        code.moveNode(stepNode, index);
        code.moveNode(expressionNode, index);
        result := pos;
    end;

    function AVTCodeBuilder.parseTry(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
    var
        catchAdded: boolean;
        name: AnsiString;
        lineIndex: int;
        blockNode: AVTNode;
        catchNode: AVTNode;
        tryEndNode: AVTNode;
        typeVoidRef: AVTType;
        typeParsedRef: AVTType;
        typeThrowableRef: AVTType;
    begin
        if source.getLexemeType(pos) <> CHAR_CURLY_OPENED then begin
            raise AVTCompilerException.create('"{" expected', source, pos);
        end;
        typeVoidRef := getPrimitiveType(AVT_VOID);
        blockNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), typeVoidRef, AVT_BLOCK);
        pos := parseBlock(blockNode, code, methodRef, typeRef, source, pos + 1);
        lineIndex := source.getLexemeLineIndex(pos - 1);
        tryEndNode := code.appendNode(parentNode, lineIndex, typeVoidRef, AVT_TRY_END);
        code.appendNode(parentNode, lineIndex, typeVoidRef, JUMP);
        case source.getLexemeType(pos) of
        AVT_CATCH: begin
            catchAdded := false;
            typeThrowableRef := getThrowableType();
            repeat
                if catchAdded then begin
                    code.appendNode(parentNode.lastChild(), source.getLexemeLineIndex(pos - 1), typeVoidRef, JUMP);
                end;
                lineIndex := source.getLexemeLineIndex(pos);
                inc(pos);
                if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
                    raise AVTCompilerException.create('"(" expected', source, pos);
                end;
                typeParsedRef := parseType(parentNode, methodRef, typeRef, source, pos + 1);
                if not typeParsedRef.isClass() or not typeThrowableRef.isAssignableFrom(typeParsedRef) then begin
                    raise AVTCompilerException.create('No exception of type ' + itemToString(typeParsedRef) + ' can be thrown; an exception type must be a subclass of ' + itemToString(typeThrowableRef), source, pos);
                end;
                pos := source.position;
                if source.getLexemeType(pos) <> LITR_NAME then begin
                    raise AVTCompilerException.create('Variable name expected', source, pos);
                end;
                name := source.getLexemeAnsiString(pos);
                if getVariable(name, parentNode.parent, methodRef) <> nil then begin
                    raise AVTCompilerException.create('Duplicate local variable ' + name, source, pos);
                end;
                catchNode := code.appendNode(parentNode, lineIndex, typeVoidRef, AVT_CATCH, AVTVariable.create(typeParsedRef, name, source, pos));
                inc(pos);
                if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then begin
                    raise AVTCompilerException.create('")" expected', source, pos);
                end;
                inc(pos);
                if source.getLexemeType(pos) <> CHAR_CURLY_OPENED then begin
                    raise AVTCompilerException.create('"{" expected', source, pos);
                end;
                pos := parseBlock(catchNode, code, methodRef, typeRef, source, pos + 1);
                catchAdded := true;
            until source.getLexemeType(pos) <> AVT_CATCH;
        end;
        AVT_FINALLY: begin
            catchNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), typeVoidRef, AVT_FINALLY);
            code.appendNode(tryEndNode).setData(tryEndNode.lineIndex, typeVoidRef, AVT_FINALLY_INVOKE, catchNode);
            inc(pos);
            if source.getLexemeType(pos) <> CHAR_CURLY_OPENED then begin
                raise AVTCompilerException.create('"{" expected', source, pos);
            end;
            pos := parseBlock(catchNode, code, methodRef, typeRef, source, pos + 1);
            code.appendNode(catchNode, source.getLexemeLineIndex(pos - 1), typeVoidRef, AVT_FINALLY_RETURN);
        end
        else
            raise AVTCompilerException.create('"catch" or "finally" expected', source, pos);
        end;
        result := pos;
    end;

    function AVTCodeBuilder.parseWith(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
    var
        typeVoidRef: AVTType;
        variableNode: AVTNode;
        expressionNode: AVTNode;
        expressionType: AVTType;
    begin
        if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
            raise AVTCompilerException.create('"(" expected', source, pos);
        end;
        inc(pos);
        typeVoidRef := getPrimitiveType(AVT_VOID);
        repeat
            pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos);
            expressionNode := parentNode.lastChild();
            needValue(expressionNode, code);
            expressionType := expressionNode.dataType;
            if not(expressionType is AVTTypeStructured) then begin
                raise AVTCompilerException.create(itemToString(expressionType) + ' is not a valid type''s argument for the with statement', source, pos);
            end;
            variableNode := code.appendNode(parentNode);
            variableNode.setData(NO_LINE_INDEX, typeVoidRef, DECLARE_VARIABLE, methodRef.createWithVariable(AVTTypeStructured(expressionType)));
            code.moveNode(expressionNode, variableNode, 0);
            case source.getLexemeType(pos) of
            CHAR_COMMA: begin
                inc(pos);
            end;
            CHAR_PARENTH_CLOSED: begin
                break;
            end
            else
                raise AVTCompilerException.create('")" expected', source, pos);
            end;
        until false;
        result := parseStatement(parentNode, code, methodRef, typeRef, source, pos + 1);
    end;

    function AVTCodeBuilder.parseBreak(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
    label
        label0;
    var
        labelName: UnicodeString;
        currentNode: AVTNode;
    begin
        if source.getLexemeType(pos) <> LITR_NAME then begin
            currentNode := parentNode.parent;
            while currentNode <> nil do begin
                case currentNode.instruction of
                AVT_DO, AVT_FOR, AVT_WHILE, AVT_SWITCH:
                    goto label0;
                end;
                currentNode := currentNode.parent;
            end;
            raise AVTCompilerException.create('Break can not be used outside of a loop or a switch', source, pos);
        end else begin
            labelName := source.getLexemeUnicodeString(pos);
            currentNode := parentNode.parent;
            while currentNode <> nil do begin
                if (currentNode.instruction = AVT_LABEL) and ((currentNode.operand1 as AVTConstant).value.asString = labelName) then begin
                    inc(pos);
                    goto label0;
                end;
                currentNode := currentNode.parent;
            end;
            raise AVTCompilerException.create('The label ' + stringToUTF8(labelName) + ' is missing', source, pos);
        end;
        label0:
        parentNode.operand1 := currentNode;
        if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
            raise AVTCompilerException.create('";" expected', source, pos);
        end;
        result := pos + 1;
    end;

    function AVTCodeBuilder.parseThrow(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
    var
        expressionNode: AVTNode;
        expressionType: AVTType;
        typeThrowableRef: AVTType;
    begin
        pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos);
        expressionNode := parentNode.lastChild();
        needValue(expressionNode, code);
        expressionType := expressionNode.dataType;
        typeThrowableRef := getThrowableType();
        if not typeThrowableRef.isAssignableFrom(expressionType) then begin
            raise AVTCompilerException.create('No exception of type ' + itemToString(expressionType) + ' can be thrown; an exception type must be a subclass of ' + itemToString(typeThrowableRef), source, pos);
        end;
        if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
            raise AVTCompilerException.create('";" expected', source, pos);
        end;
        result := pos + 1;
    end;

    function AVTCodeBuilder.parseWhile(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
    var
        expressionNode: AVTNode;
        expressionType: AVTType;
    begin
        if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
            raise AVTCompilerException.create('"(" expected', source, pos);
        end;
        pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos + 1);
        if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then begin
            raise AVTCompilerException.create('")" expected', source, pos);
        end;
        expressionNode := parentNode.lastChild();
        needValue(expressionNode, code);
        expressionType := expressionNode.dataType;
        if (expressionType = nil) or not expressionType.isBoolean() then begin
            raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(expressionType) + ' to boolean', source, pos);
        end;
        pos := parseStatement(parentNode, code, methodRef, typeRef, source, pos + 1);
        code.moveNode(expressionNode, 2);
        code.insertNode(parentNode).setData(-1, getPrimitiveType(AVT_VOID), JUMP);
        result := pos;
    end;

    function AVTCodeBuilder.parseReturn(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
    var
        typeReturnRef: AVTType;
        expressionType: AVTType;
        expressionNode: AVTNode;
    begin
        typeReturnRef := methodRef.returnType;
        if not typeReturnRef.isVoid() then begin
            pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos);
            expressionNode := parentNode.lastChild();
            needValue(expressionNode, code);
            expressionType := expressionNode.dataType;
            if not typeReturnRef.isConvertableFrom(expressionType) then begin
                raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(expressionType) + ' to ' + itemToString(typeReturnRef), source, pos);
            end;
            cast(expressionNode, code, typeReturnRef);
        end;
        if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
            raise AVTCompilerException.create('";" expected', source, pos);
        end;
        result := pos + 1;
    end;

    function AVTCodeBuilder.parseSwitch(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
    var
        hasDefault: boolean;
        hasValues: Vector;
        expressionNode: AVTNode;
        expressionType: AVTType;
        valueConst: AVTConstant;
        valueAsObject: Value;
        valueType: AVTType;
        valueNode: AVTNode;
        blockNode: AVTNode;
        typeVoidRef: AVTType;
        typeIntRef: AVTTypePrimitive;
    begin
        if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
            raise AVTCompilerException.create('"(" expected', source, pos);
        end;
        pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos + 1);
        expressionNode := parentNode.lastChild();
        needValue(expressionNode, code);
        expressionType := expressionNode.dataType;
        typeIntRef := getPrimitiveType(AVT_INT);
        if not typeIntRef.isConvertableFrom(expressionType) then begin
            raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(expressionType) + ' to int', source, pos);
        end;
        if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then begin
            raise AVTCompilerException.create('")" expected', source, pos);
        end;
        inc(pos);
        if source.getLexemeType(pos) <> CHAR_CURLY_OPENED then begin
            raise AVTCompilerException.create('"{" expected', source, pos);
        end;
        inc(pos);
        typeVoidRef := getPrimitiveType(AVT_VOID);
        blockNode := nil;
        hasDefault := false;
        hasValues := Vector.create();
        try
            repeat
                case source.getLexemeType(pos) of
                AVT_CASE: begin
                    blockNode := nil;
                    pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos + 1);
                    valueNode := parentNode.lastChild();
                    if valueNode.instruction <> LOAD_CONST then begin
                        raise AVTCompilerException.create('Case expressions must be constant expressions', source, pos);
                    end;
                    valueType := valueNode.dataType;
                    if not expressionType.isConvertableFrom(valueType) then begin
                        raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(valueType) + ' to ' + itemToString(expressionType), source, pos);
                    end;
                    valueConst := valueNode.operand1 as AVTConstant;
                    cast(valueConst, valueConst, typeIntRef);
                    valueAsObject := ValueOfLong.create(valueConst.value.asInt, pascalx.lang.TYPE_INT);
                    if hasValues.contains(valueAsObject) then begin
                        raise AVTCompilerException.create('Duplicate case', source, pos);
                    end;
                    if source.getLexemeType(pos) <> CHAR_COLON then begin
                        raise AVTCompilerException.create('":" expected', source, pos);
                    end;
                    valueNode.setData(source.getLexemeLineIndex(pos), typeVoidRef, AVT_CASE, valueConst);
                    hasValues.append(valueAsObject);
                    inc(pos);
                end;
                AVT_DEFAULT: begin
                    blockNode := nil;
                    inc(pos);
                    if hasDefault then begin
                        raise AVTCompilerException.create('The default case already defined', source, pos);
                    end;
                    if source.getLexemeType(pos) <> CHAR_COLON then begin
                        raise AVTCompilerException.create('":" expected', source, pos);
                    end;
                    code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeVoidRef, AVT_DEFAULT);
                    hasDefault := true;
                    inc(pos);
                end;
                CHAR_CURLY_CLOSED: begin
                    if not hasDefault then begin
                        code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeVoidRef, AVT_DEFAULT);
                    end;
                    break;
                end
                else
                    if not hasDefault and hasValues.isEmpty() then begin
                        raise AVTCompilerException.create('"case" or "default" expected', source, pos);
                    end;
                    if blockNode = nil then begin
                        blockNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), typeVoidRef, AVT_BLOCK);
                    end;
                    pos := parseStatement(blockNode, code, methodRef, typeRef, source, pos);
                end;
            until false;
        finally
            hasValues.free();
        end;
        result := pos + 1;
    end;

    function AVTCodeBuilder.parseContinue(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
    label
        label0;
    var
        labelName: UnicodeString;
        currentNode: AVTNode;
    begin
        if source.getLexemeType(pos) <> LITR_NAME then begin
            currentNode := parentNode.parent;
            while currentNode <> nil do begin
                case currentNode.instruction of
                AVT_DO, AVT_FOR, AVT_WHILE:
                    goto label0;
                end;
                currentNode := currentNode.parent;
            end;
            raise AVTCompilerException.create('Continue can not be used outside of a loop', source, pos);
        end else begin
            labelName := source.getLexemeUnicodeString(pos);
            currentNode := parentNode.parent;
            while currentNode <> nil do begin
                if (currentNode.instruction = AVT_LABEL) and ((currentNode.operand1 as AVTConstant).value.asString = labelName) then begin
                    currentNode := currentNode.firstChild();
                    case currentNode.instruction of
                    AVT_DO, AVT_FOR, AVT_WHILE: begin
                        inc(pos);
                        goto label0;
                    end
                    else
                        raise AVTCompilerException.create('Continue can not be used outside of a loop', source, pos);
                    end;
                end;
                currentNode := currentNode.parent;
            end;
            raise AVTCompilerException.create('The label ' + stringToUTF8(labelName) + ' is missing', source, pos);
        end;
        label0:
        parentNode.operand1 := currentNode;
        if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
            raise AVTCompilerException.create('";" expected', source, pos);
        end;
        result := pos + 1;
    end;

    function AVTCodeBuilder.parseSynchronized(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
    var
        isWith: boolean;
        lineIndex: int;
        tryNode: AVTNode;
        catchNode: AVTNode;
        storeNode: AVTNode;
        blockNode: AVTNode;
        tryEndNode: AVTNode;
        typeVoidRef: AVTType;
        monitorVar: AVTVariable;
        expressionNode: AVTNode;
        expressionType: AVTType;
    begin
        isWith := false;
        if source.getLexemeType(pos) = AVT_WITH then begin
            isWith := true;
            inc(pos);
        end;
        if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
            raise AVTCompilerException.create('"(" expected', source, pos);
        end;
        storeNode := code.appendNode(parentNode);
        pos := parseExpression(storeNode, code, methodRef, typeRef, source, pos + 1);
        expressionNode := storeNode.lastChild();
        needValue(expressionNode, code);
        expressionType := expressionNode.dataType;
        if not(expressionType is AVTTypeStructured) then begin
            raise AVTCompilerException.create(itemToString(expressionType) + ' is not a valid type''s argument for the synchronized statement', source, pos);
        end;
        typeVoidRef := getPrimitiveType(AVT_VOID);
        if isWith then begin
            monitorVar := methodRef.createWithVariable(AVTTypeStructured(expressionType));
        end else begin
            monitorVar := methodRef.createMonitorVariable(AVTTypeStructured(expressionType));
        end;
        lineIndex := source.getLexemeLineIndex(pos);
        storeNode.setData(lineIndex, typeVoidRef, DECLARE_VARIABLE, monitorVar);
        code.appendNode(storeNode).setData(lineIndex, typeVoidRef, DUP1);
        if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then begin
            raise AVTCompilerException.create('")" expected', source, pos);
        end;
        inc(pos);
        if source.getLexemeType(pos) <> CHAR_CURLY_OPENED then begin
            raise AVTCompilerException.create('"{" expected', source, pos);
        end;
        lineIndex := source.getLexemeLineIndex(pos);
        tryNode := code.appendNode(parentNode, lineIndex, typeVoidRef, AVT_TRY_BEGIN);
        blockNode := code.appendNode(tryNode, lineIndex, typeVoidRef, AVT_BLOCK);
        pos := parseBlock(blockNode, code, methodRef, typeRef, source, pos + 1);
        lineIndex := source.getLexemeLineIndex(pos - 1);
        tryEndNode := code.appendNode(tryNode, lineIndex, typeVoidRef, AVT_TRY_END);
        code.appendNode(tryNode, lineIndex, typeVoidRef, JUMP);
        catchNode := code.appendNode(tryNode, lineIndex, typeVoidRef, AVT_FINALLY);
        code.appendNode(tryEndNode).setData(lineIndex, typeVoidRef, AVT_FINALLY_INVOKE, catchNode);
        storeNode := code.appendNode(catchNode, lineIndex, typeVoidRef, AVT_MONITOR_LEAVE);
        code.appendNode(storeNode).setData(lineIndex, expressionType, LOAD_VARIABLE, monitorVar);
        code.appendNode(catchNode).setData(lineIndex, typeVoidRef, AVT_FINALLY_RETURN);
        result := pos;
    end;

    function AVTCodeBuilder.parseStatement(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
    var
        typeVoidRef: AVTType;
        statementNode: AVTNode;
        labelConstant: AVTConstant;
    begin
        typeVoidRef := nil;
        while (source.getLexemeType(pos) = LITR_NAME) and (source.getLexemeType(pos + 1) = CHAR_COLON) do begin
            if typeVoidRef = nil then typeVoidRef := getPrimitiveType(AVT_VOID);
            labelConstant := AVTConstant.create();
            labelConstant.value.asString := source.getLexemeUnicodeString(pos);
            parentNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), typeVoidRef, AVT_LABEL, labelConstant);
            inc(pos, 2);
        end;
        case source.getLexemeType(pos) of
        AVT_SYNCHRONIZED: begin
            statementNode := code.appendNode(parentNode);
            statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_MONITOR_ENTER);
            pos := parseSynchronized(statementNode, code, methodRef, typeRef, source, pos + 1);
        end;
        AVT_CONTINUE: begin
            statementNode := code.appendNode(parentNode);
            statementNode.setData(source.getLexemeLineIndex(pos), nil, AVT_CONTINUE, nil);
            pos := parseContinue(statementNode, code, methodRef, typeRef, source, pos + 1);
        end;
        AVT_SWITCH: begin
            statementNode := code.appendNode(parentNode);
            statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_SWITCH);
            pos := parseSwitch(statementNode, code, methodRef, typeRef, source, pos + 1);
        end;
        AVT_RETURN: begin
            statementNode := code.appendNode(parentNode);
            statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_RETURN);
            pos := parseReturn(statementNode, code, methodRef, typeRef, source, pos + 1);
        end;
        AVT_WHILE: begin
            statementNode := code.appendNode(parentNode);
            statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_WHILE);
            pos := parseWhile(statementNode, code, methodRef, typeRef, source, pos + 1);
        end;
        AVT_THROW: begin
            statementNode := code.appendNode(parentNode);
            statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_THROW);
            pos := parseThrow(statementNode, code, methodRef, typeRef, source, pos + 1);
        end;
        AVT_BREAK: begin
            statementNode := code.appendNode(parentNode);
            statementNode.setData(source.getLexemeLineIndex(pos), nil, AVT_BREAK, nil);
            pos := parseBreak(statementNode, code, methodRef, typeRef, source, pos + 1);
        end;
        AVT_WITH: begin
            statementNode := code.appendNode(parentNode);
            statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_WITH);
            pos := parseWith(statementNode, code, methodRef, typeRef, source, pos + 1);
        end;
        AVT_TRY_BEGIN: begin
            statementNode := parentNode;
            while statementNode <> nil do begin
                if statementNode.instruction = AVT_FINALLY then begin
                    raise AVTCompilerException.create('Try block surrounded with finally block not supported in this compiler version', source, pos);
                end;
                statementNode := statementNode.parent;
            end;
            statementNode := code.appendNode(parentNode);
            statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_TRY_BEGIN);
            pos := parseTry(statementNode, code, methodRef, typeRef, source, pos + 1);
        end;
        AVT_FOR: begin
            statementNode := code.appendNode(parentNode);
            statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_FOR);
            pos := parseFor(statementNode, code, methodRef, typeRef, source, pos + 1);
        end;
        AVT_IF: begin
            statementNode := code.appendNode(parentNode);
            statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_IF);
            pos := parseIf(statementNode, code, methodRef, typeRef, source, pos + 1);
        end;
        AVT_DO: begin
            statementNode := code.appendNode(parentNode);
            statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_DO);
            pos := parseDo(statementNode, code, methodRef, typeRef, source, pos + 1);
        end;
        CHAR_CURLY_OPENED: begin
            statementNode := code.appendNode(parentNode);
            statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_BLOCK);
            pos := parseBlock(statementNode, code, methodRef, typeRef, source, pos + 1);
        end;
        CHAR_SEMICOLON: begin
            code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_BLOCK);
            inc(pos);
        end
        else
            pos := parseLocal(parentNode, code, methodRef, typeRef, source, pos);
            if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
                raise AVTCompilerException.create('";" expected', source, pos);
            end;
            inc(pos);
        end;
        result := pos;
    end;

    function AVTCodeBuilder.parseType(parentNode: AVTNode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): AVTType;
    var
        lxt: int;
        dimensions: int;
        app: AVTProgramme;
        itemParsedRef: AVTItem;
        typeParsedRef: AVTType;
    begin
        app := programme;
        lxt := source.getLexemeType(pos);
        if lxt = AVT_VOID then begin
            source.position := pos + 1;
            result := app.systemPackage.getType(AVTTypePrimitive.getName(AVT_VOID));
            exit;
        end;
        typeParsedRef := nil;
        if (lxt >= AVT_BOOLEAN) and (lxt <= AVT_DOUBLE8) then begin
            typeParsedRef := app.systemPackage.getType(AVTTypePrimitive.getName(lxt));
            inc(pos);
        end else
        if lxt = LITR_NAME then begin
            itemParsedRef := resolveName(source.getLexemeAnsiString(pos), parentNode, methodRef, typeRef, pos);
            if itemParsedRef is AVTPackage then begin
                typeParsedRef := parseFullyQualifiedTypeName(AVTPackage(itemParsedRef), typeRef, pos + 1);
                pos := source.position;
            end else
            if itemParsedRef is AVTType then begin
                typeParsedRef := AVTType(itemParsedRef);
                inc(pos);
            end;
        end;
        if typeParsedRef = nil then begin
            raise AVTCompilerException.create('Type expected', source, pos);
        end;
        dimensions := 0;
        while (dimensions < 99) and (source.getLexemeType(pos) = CHAR_BRACKET_OPENED) and (source.getLexemeType(pos + 1) = CHAR_BRACKET_CLOSED) do begin
            typeParsedRef := app.getArrayOf(typeParsedRef);
            inc(dimensions);
            inc(pos, 2);
        end;
        source.position := pos;
        result := typeParsedRef;
    end;

    function AVTCodeBuilder.tryParseType(parentNode: AVTNode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): AVTType;
    var
        lxt: int;
        dimensions: int;
        app: AVTProgramme;
        itemParsedRef: AVTItem;
        typeParsedRef: AVTType;
    begin
        app := programme;
        lxt := source.getLexemeType(pos);
        if lxt = AVT_VOID then begin
            source.position := pos + 1;
            result := app.systemPackage.getType(AVTTypePrimitive.getName(AVT_VOID));
            exit;
        end;
        typeParsedRef := nil;
        if (lxt >= AVT_BOOLEAN) and (lxt <= AVT_DOUBLE8) then begin
            typeParsedRef := app.systemPackage.getType(AVTTypePrimitive.getName(lxt));
            inc(pos);
        end else
        if lxt = LITR_NAME then begin
            itemParsedRef := resolveName(source.getLexemeAnsiString(pos), parentNode, methodRef, typeRef, pos);
            if itemParsedRef is AVTPackage then begin
                typeParsedRef := tryParseFullyQualifiedTypeName(AVTPackage(itemParsedRef), typeRef, pos + 1);
                pos := source.position;
            end else
            if itemParsedRef is AVTType then begin
                typeParsedRef := AVTType(itemParsedRef);
                inc(pos);
            end;
        end;
        if typeParsedRef = nil then begin
            result := nil;
            exit;
        end;
        dimensions := 0;
        while (dimensions < 99) and (source.getLexemeType(pos) = CHAR_BRACKET_OPENED) and (source.getLexemeType(pos + 1) = CHAR_BRACKET_CLOSED) do begin
            typeParsedRef := app.getArrayOf(typeParsedRef);
            inc(dimensions);
            inc(pos, 2);
        end;
        source.position := pos;
        result := typeParsedRef;
    end;

    function AVTCodeBuilder.resolveName(const simpleName: AnsiString; parentNode: AVTNode; methodRef: AVTMethod; typeRef: AVTTypeStructured; pos: int): AVTItem;
    var
        i: int;
        found: AVTItem;
        childNode: AVTNode;
        associate: _Object;
    begin
        fldResolvedVariable := nil;
        repeat
            for i := parentNode.length - 1 downto 0 do begin
                childNode := parentNode[i];
                associate := childNode.operand1;
                if associate is AVTVariable then begin
                    if childNode.isWithVariable() then begin
                        found := resolveMember(AVTVariable(associate).valueType as AVTTypeStructured, simpleName, typeRef, pos);
                        if found <> nil then begin
                            fldResolvedVariable := AVTVariable(associate);
                            result := found;
                            exit;
                        end;
                    end else begin
                        case childNode.instruction of
                        DECLARE_VARIABLE, AVT_CATCH: begin
                            if AVTVariable(associate).simpleName = simpleName then begin
                                result := AVTVariable(associate);
                                exit;
                            end;
                        end;
                        end;
                    end;
                end;
            end;
            parentNode := parentNode.parent;
        until parentNode = nil;
        found := methodRef.getArgument(simpleName);
        if found <> nil then begin
            result := found;
            exit;
        end;
        found := inherited resolveName(simpleName, typeRef, pos);
        if (found is AVTMember) and not found.isStatic() then begin
            fldResolvedVariable := methodRef.argumentThis;
        end;
        result := found;
    end;

    function AVTCodeBuilder.insertIncrementCode(parentNode: AVTNode; code: AVTCode; typeOperandRef: AVTTypePrimitive; isIncrement: boolean; lineIndex: int): AVTNode;
    var
        currentNode: AVTNode;
        newConstant: AVTConstant;
        typeIntRef: AVTTypePrimitive;
    begin
        case typeOperandRef.primitiveKind of
        AVT_REAL: begin
            newConstant := AVTConstant.create(typeOperandRef);
            if isIncrement then begin
                newConstant.value.asReal := 1.0;
            end else begin
                newConstant.value.asReal := -1.0;
            end;
            currentNode := code.appendNode(parentNode, lineIndex, typeOperandRef, OPER_SCAL_ADD, typeOperandRef);
            code.appendNode(currentNode).setData(lineIndex, typeOperandRef, LOAD_CONST, newConstant);
        end;
        AVT_CHAR: begin
            typeIntRef := getPrimitiveType(AVT_INT);
            newConstant := AVTConstant.create(typeIntRef);
            if isIncrement then begin
                newConstant.value.asInt := 1;
            end else begin
                newConstant.value.asInt := -1;
            end;
            currentNode := code.appendNode(parentNode, lineIndex, typeOperandRef, OPER_TYPE_CAST, typeOperandRef, typeIntRef);
            currentNode := code.appendNode(currentNode, lineIndex, typeIntRef, OPER_SCAL_ADD, typeIntRef);
            code.appendNode(currentNode).setData(lineIndex, typeIntRef, LOAD_CONST, newConstant);
        end
        else
            newConstant := AVTConstant.create(getPrimitiveType(AVT_BYTE));
            if isIncrement then begin
                newConstant.value.asByte := 1;
            end else begin
                newConstant.value.asByte := -1;
            end;
            cast(newConstant, newConstant, typeOperandRef);
            currentNode := code.appendNode(parentNode, lineIndex, typeOperandRef, OPER_VECT_ADD, typeOperandRef);
            code.appendNode(currentNode).setData(lineIndex, typeOperandRef, LOAD_CONST, newConstant);
        end;
        result := currentNode;
    end;

    function AVTCodeBuilder.cast(currentNode: AVTNode; code: AVTCode; typeNewRef: AVTType): AVTNode;
    var
        associate: _Object;
        typeOldRef: AVTType;
        convertNode: AVTNode;
    begin
        typeOldRef := currentNode.dataType;
        if typeOldRef = typeNewRef then begin
            result := currentNode;
            exit;
        end;
        if typeOldRef = nil then begin
            if typeNewRef is AVTTypeStructured then begin
                currentNode.dataType := typeNewRef;
                result := currentNode;
                exit;
            end;
        end else
        if typeOldRef is AVTTypePrimitive then begin
            if typeNewRef is AVTTypePrimitive then begin
                associate := currentNode.operand1;
                if (currentNode.instruction = LOAD_CONST) and (associate is AVTConstant) then begin
                    cast(AVTConstant(associate), AVTConstant(associate), AVTTypePrimitive(typeNewRef));
                    currentNode.dataType := typeNewRef;
                    result := currentNode;
                    exit;
                end;
                if (AVTTypePrimitive(typeNewRef).primitiveKind = AVT_INT) and not typeOldRef.isStackable() then begin
                    currentNode.dataType := typeNewRef;
                    result := currentNode;
                    exit;
                end;
                convertNode := code.insertNode(currentNode.parent, currentNode.index, currentNode.lineIndex, typeNewRef, OPER_TYPE_CAST, typeNewRef, typeOldRef);
                code.moveNode(currentNode, convertNode, 0);
                result := convertNode;
                exit;
            end;
        end else
        if typeOldRef is AVTTypeStructured then begin
            if typeNewRef is AVTTypeStructured then begin
                if typeNewRef.isAssignableFrom(typeOldRef) then begin
                    currentNode.dataType := typeNewRef;
                    result := currentNode;
                    exit;
                end;
                convertNode := code.insertNode(currentNode.parent, currentNode.index, currentNode.lineIndex, typeNewRef, OPER_TYPE_CAST, typeNewRef, typeOldRef);
                code.moveNode(currentNode, convertNode, 0);
                result := convertNode;
                exit;
            end;
        end;
        result := currentNode;
    end;

    function AVTCodeBuilder.getPrimitiveTypeForIntValue(value: int): AVTTypePrimitive;
    begin
        if (value >= -$80) and (value < $80) then begin
            result := getPrimitiveType(AVT_BYTE);
            exit;
        end;
        if (value >= -$8000) and (value < $8000) then begin
            result := getPrimitiveType(AVT_SHORT);
            exit;
        end;
        result := getPrimitiveType(AVT_INT);
    end;

    procedure AVTCodeBuilder.parseMethods(typeRef: AVTTypeStructured);
    var
        member: TObject;
    begin
        with typeRef.members() do while hasMoreElements() do begin
            member := nextElement().objectValue();
            if member is AVTMethod then buildCode(AVTMethod(member));
        end;
    end;

    function AVTCodeBuilder.getThrowableType(): AVTTypeStructured;
    var
        packageAvtLangRef: AVTPackage;
        typeThrowableRef: AVTTypeStructured;
    begin
        typeThrowableRef := fldTypeThrowableRef;
        if typeThrowableRef <> nil then begin
            result := typeThrowableRef;
            exit;
        end;
        packageAvtLangRef := programme.getPackage('avt.lang');
        if packageAvtLangRef = nil then begin
            result := nil;
            exit;
        end;
        typeThrowableRef := packageAvtLangRef.getType('Throwable') as AVTTypeStructured;
        fldTypeThrowableRef := typeThrowableRef;
        result := typeThrowableRef;
    end;

    function AVTCodeBuilder.getStructType(): AVTTypeStructured;
    var
        packageAvtLangRef: AVTPackage;
        typeStructRef: AVTTypeStructured;
    begin
        typeStructRef := fldTypeStructRef;
        if typeStructRef <> nil then begin
            result := typeStructRef;
            exit;
        end;
        packageAvtLangRef := programme.getPackage('avt.lang');
        if packageAvtLangRef = nil then begin
            result := nil;
            exit;
        end;
        typeStructRef := packageAvtLangRef.getType('Struct') as AVTTypeStructured;
        fldTypeStructRef := typeStructRef;
        result := typeStructRef;
    end;

    function AVTCodeBuilder.getObjectType(): AVTTypeStructured;
    var
        packageAvtLangRef: AVTPackage;
        typeObjectRef: AVTTypeStructured;
    begin
        typeObjectRef := fldTypeObjectRef;
        if typeObjectRef <> nil then begin
            result := typeObjectRef;
            exit;
        end;
        packageAvtLangRef := programme.getPackage('avt.lang');
        if packageAvtLangRef = nil then begin
            result := nil;
            exit;
        end;
        typeObjectRef := packageAvtLangRef.getType('Object') as AVTTypeStructured;
        fldTypeObjectRef := typeObjectRef;
        result := typeObjectRef;
    end;
{%endregion}

end.