tranprog.pas

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

{
    Этот исходный текст является частью Продвинутого векторного транслятора.

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

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

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

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

unit TranProg;

{$MODE DELPHI,EXTENDEDSYNTAX ON}

interface

uses
    Lang, TranIntf, TranType;

{$ASMMODE INTEL,CALLING REGISTER,INLINE ON,GOTO ON}
{$H+,I-,J-,M-,Q-,R-,T-}

type
    TranslatorNamespaceEntry = class;
    TranslatorGlobalVariable = class;
    TranslatorGlobalConstantInt = class;
    TranslatorGlobalConstantLong = class;
    TranslatorGlobalConstantReal = class;
    TranslatorGlobalConstantUltra = class;
    TranslatorGlobalConstantXVector = class;
    TranslatorGlobalException = class;
    TranslatorGlobalFunction = class;
    TranslatorNamespace = class;

    TranslatorNamespaceEntry = class(RefCountInterfacedObject, NamedObject, NamespaceEntry)
    public
        constructor create(entryOwner: Namespace; entryPublic: boolean;
                const entryName: UnicodeString);
        function toString(): AnsiString; override;
        procedure setDeclarePosition(declarePosition: int); virtual;
        procedure setStartPosition(startPosition: int); virtual;
        function getDeclarePosition(): int; virtual;
        function getStartPosition(): int; virtual;
        function getName(): UnicodeString; virtual;
        function isPublic(): boolean; virtual;
        function getOwner(): Namespace; virtual;
    private
        textRepresentation: AnsiString;
    strict private
        entryPublic: boolean;
        startPosition: int;
        declarePosition: int;
        entryOwner: Namespace;
        entryName: UnicodeString;
    end;

    TranslatorGlobalVariable = class(TranslatorNamespaceEntry, NameAndType, GlobalVariable)
    public
        constructor create(entryOwner: Namespace; entryPublic: boolean;
                const entryName: UnicodeString; varType: TypeDescriptor);
        function getDataType(): TypeDescriptor; virtual;
    strict private
        varType: TypeDescriptor;
    end;

    TranslatorGlobalConstantInt = class(TranslatorGlobalVariable, GlobalConstant)
    public
        constructor create(entryOwner: Namespace; entryPublic: boolean;
                const entryName: UnicodeString; constType: TypeDescriptor;
                const constValue: int);
        function getBooleanValue(): boolean; virtual;
        function getCharValue(): int; virtual;
        function getByteValue(): int; virtual;
        function getShortValue(): int; virtual;
        function getIntValue(): int; virtual;
        function getLongValue(): int64; virtual;
        function getUltraValue(): ultra; virtual;
        function getRealValue(): real; virtual;
        function getXVectorValue(): xvector; virtual;
    private
        int0: int;
    end;

    TranslatorGlobalConstantLong = class(TranslatorGlobalConstantInt)
    public
        constructor create(entryOwner: Namespace; entryPublic: boolean;
                const entryName: UnicodeString; constType: TypeDescriptor;
                const constValue: int64);
        function getBooleanValue(): boolean; override;
        function getLongValue(): int64; override;
        function getUltraValue(): ultra; override;
        function getRealValue(): real; override;
        function getXVectorValue(): xvector; override;
    private
        int1: int;
    end;

    TranslatorGlobalConstantUltra = class(TranslatorGlobalConstantLong)
    public
        constructor create(entryOwner: Namespace; entryPublic: boolean;
                const entryName: UnicodeString; constType: TypeDescriptor;
                const constValue: ultra);
        function getUltraValue(): ultra; override;
        function getRealValue(): real; override;
        function getXVectorValue(): xvector; override;
    private
        int2: int;
        int3: int;
    end;

    TranslatorGlobalConstantReal = class(TranslatorGlobalVariable, GlobalConstant)
    public
        constructor create(entryOwner: Namespace; entryPublic: boolean;
                const entryName: UnicodeString; constType: TypeDescriptor;
                const constValue: real);
        function getBooleanValue(): boolean; virtual;
        function getCharValue(): int; virtual;
        function getByteValue(): int; virtual;
        function getShortValue(): int; virtual;
        function getIntValue(): int; virtual;
        function getLongValue(): int64; virtual;
        function getUltraValue(): ultra; virtual;
        function getRealValue(): real; virtual;
        function getXVectorValue(): xvector; virtual;
    private
        value: real;
    end;

    TranslatorGlobalConstantXVector = class(TranslatorGlobalVariable, GlobalConstant)
    public
        constructor create(entryOwner: Namespace; entryPublic: boolean;
                const entryName: UnicodeString; constType: TypeDescriptor;
                const constValue: xvector);
        function getBooleanValue(): boolean; virtual;
        function getCharValue(): int; virtual;
        function getByteValue(): int; virtual;
        function getShortValue(): int; virtual;
        function getIntValue(): int; virtual;
        function getLongValue(): int64; virtual;
        function getUltraValue(): ultra; virtual;
        function getRealValue(): real; virtual;
        function getXVectorValue(): xvector; virtual;
    private
        value: xvector;
    end;

    TranslatorGlobalException = class(TranslatorNamespaceEntry, GlobalException)
    public
        constructor create(entryOwner: Namespace; entryPublic: boolean;
                const entryName: UnicodeString; ancestorException: GlobalException);
        function isInheritedFrom(exceptionForTest: GlobalException): boolean; virtual;
        function getAncestor(): GlobalException; virtual;
    strict private
        ancestor: GlobalException;
    end;

    TranslatorGlobalFunction = class(TranslatorNamespaceEntry, GlobalFunction)
    public
        const CODE_TYPE_NORMAL = 0;
        const CODE_TYPE_ASSEMBLER = 1;
        const CODE_TYPE_PUREASSEMBLER = 3;
        const CODE_TYPE_INTERRUPT = 4;
        const CODE_TYPE_INTERRUPT_ASSEMBLER = CODE_TYPE_INTERRUPT + CODE_TYPE_ASSEMBLER;
        const CODE_TYPE_INTERRUPT_PUREASSEMBLER = CODE_TYPE_INTERRUPT + CODE_TYPE_PUREASSEMBLER;

    public
        constructor create(entryOwner: Namespace; entryPublic: boolean;
                const entryName: UnicodeString; operandSize, codeType: int;
                returnType: TypeDescriptor);
        function isInterrupt(): boolean; virtual;
        function isAssembler(): boolean; virtual;
        function isPureAssembler(): boolean; virtual;
        function getFunctionType(): TypeFunction; virtual;
    strict private
        codeType: int;
        funcType: TypeFunction;
    end;

    TranslatorNamespace = class(RefCountInterfacedObject, NamedObject, Namespace)
    public
        constructor create(const name: UnicodeString; lexemes: Lexer; operandSize: int);
        function toString(): AnsiString; override;
        procedure setDeclarePosition(declarePosition: int); virtual;
        procedure setStartPosition(startPosition: int); virtual;
        function getDeclarePosition(): int; virtual;
        function getStartPosition(): int; virtual;
        function getName(): UnicodeString; virtual;
        procedure clear(); virtual;
        procedure addImport(import: Namespace); virtual;
        function isImported(const namespaceName: UnicodeString): boolean; virtual;
        function isVisible(entry: NamespaceEntry): boolean; overload; virtual;
        function isVisible(field: StructureField): boolean; overload; virtual;
        function getImportsCount(): int; virtual;
        function getEntriesCount(): int; virtual;
        function getImport(index: int): Namespace; virtual;
        function getEntry(index: int): NamespaceEntry; virtual;
        function getLexemes(): Lexer; virtual;
        function addVariable(entryPublic: boolean; const entryName: UnicodeString;
                varType: TypeDescriptor): GlobalVariable; virtual;
        function addConstant(entryPublic: boolean; const entryName: UnicodeString;
                constType: TypeDescriptor; const constValue: real): GlobalConstant; virtual;
        function addConstantUltra(entryPublic: boolean; const entryName: UnicodeString;
                constType: TypeDescriptor; const constValue: ultra): GlobalConstant; virtual;
        function addConstantXVector(entryPublic: boolean; const entryName: UnicodeString;
                constType: TypeDescriptor; const constValue: xvector): GlobalConstant; virtual;
        function addException(entryPublic: boolean; const entryName: UnicodeString;
                ancestor: GlobalException): GlobalException; virtual;
        function addStructure(entryPublic: boolean; const entryName: UnicodeString;
                ancestor: TypeStructure): TypeStructure; virtual;
        function addStructureExt(entryPublic: boolean; const entryName: UnicodeString;
                ancestor: TypeStructure): NamespaceEntry; virtual;
        function addFunction(entryPublic: boolean; const entryName: UnicodeString;
                codeType: int; returnType: TypeDescriptor): GlobalFunction; virtual;
        function findEntry(const entryName: UnicodeString;
                findInImports: boolean): NamespaceEntry; virtual;
    strict private
        operandSize: int;
        startPosition: int;
        declarePosition: int;
        importsCount: int;
        entriesCount: int;
        imports: Namespace_Array1d;
        entries: NamespaceEntry_Array1d;
        lexemes: Lexer;
        name: UnicodeString;
        textRepresentation: AnsiString;
        procedure addEntry(entry: NamespaceEntry);
    end;

implementation

const
     MAX_INT_AS_FLOAT = 2.147483648e+09;
     MAX_INT_AS_XVECTOR: xvector = (
         floats: ( MAX_INT_AS_FLOAT, MAX_INT_AS_FLOAT, MAX_INT_AS_FLOAT, MAX_INT_AS_FLOAT )
     );

{ TranslatorNamespaceEntry }

constructor TranslatorNamespaceEntry.create(entryOwner: Namespace; entryPublic: boolean;
        const entryName: UnicodeString);
var
    representation: UnicodeString;
begin
    inherited create();
    if entryOwner <> nil then begin
        representation := entryOwner.name + '.' + entryName;
    end else begin
        representation := entryName;
    end;
    self.entryPublic := entryPublic;
    self.startPosition := -1;
    self.declarePosition := -1;
    self.entryOwner := entryOwner;
    self.entryName := entryName;
    self.textRepresentation := stringToUTF8(representation);
end;

function TranslatorNamespaceEntry.toString(): AnsiString;
begin
    result := textRepresentation;
end;

procedure TranslatorNamespaceEntry.setDeclarePosition(declarePosition: int);
begin
    self.declarePosition := declarePosition;
end;

procedure TranslatorNamespaceEntry.setStartPosition(startPosition: int);
begin
    self.startPosition := startPosition;
end;

function TranslatorNamespaceEntry.getDeclarePosition(): int;
begin
    result := declarePosition;
end;

function TranslatorNamespaceEntry.getStartPosition(): int;
begin
    result := startPosition;
end;

function TranslatorNamespaceEntry.getName(): UnicodeString;
begin
    result := entryName;
end;

function TranslatorNamespaceEntry.isPublic(): boolean;
begin
    result := entryPublic;
end;

function TranslatorNamespaceEntry.getOwner(): Namespace;
begin
    result := entryOwner;
end;

{ TranslatorGlobalVariable }

constructor TranslatorGlobalVariable.create(entryOwner: Namespace; entryPublic: boolean;
        const entryName: UnicodeString; varType: TypeDescriptor);
begin
    inherited create(entryOwner, entryPublic, entryName);
    if varType <> nil then begin
        self.textRepresentation := varType.toString() + #$20 + self.textRepresentation;
    end else begin
        self.textRepresentation := '<untyped> ' + self.textRepresentation;
    end;
    self.varType := varType;
end;

function TranslatorGlobalVariable.getDataType(): TypeDescriptor;
begin
    result := varType;
end;

{ TranslatorGlobalConstantInt }

constructor TranslatorGlobalConstantInt.create(entryOwner: Namespace; entryPublic: boolean;
        const entryName: UnicodeString; constType: TypeDescriptor; const constValue: int);
begin
    inherited create(entryOwner, entryPublic, entryName, constType);
    self.int0 := constValue;
end;

function TranslatorGlobalConstantInt.getBooleanValue(): boolean;
begin
    result := int0 <> 0;
end;

function TranslatorGlobalConstantInt.getCharValue(): int;
begin
    result := int0 and $ffff;
end;

function TranslatorGlobalConstantInt.getByteValue(): int;
begin
    result := byte(int0);
end;

function TranslatorGlobalConstantInt.getShortValue(): int;
begin
    result := short(int0);
end;

function TranslatorGlobalConstantInt.getIntValue(): int;
begin
    result := int0;
end;

function TranslatorGlobalConstantInt.getLongValue(): int64;
begin
    result := int0;
end;

function TranslatorGlobalConstantInt.getUltraValue(): ultra;
begin
    result := ultraBuild(0, int0);
end;

function TranslatorGlobalConstantInt.getRealValue(): real;
begin
    result := int0;
end;

function TranslatorGlobalConstantInt.getXVectorValue(): xvector;
begin
    result := xvectorBuild(0, 0, 0, int0);
end;

{ TranslatorGlobalConstantLong }

constructor TranslatorGlobalConstantLong.create(entryOwner: Namespace; entryPublic: boolean;
        const entryName: UnicodeString; constType: TypeDescriptor; const constValue: int64);
begin
    inherited create(entryOwner, entryPublic, entryName, constType, int(constValue));
    self.int1 := long(constValue).ints[1];
end;

function TranslatorGlobalConstantLong.getBooleanValue(): boolean;
begin
    result := false;
end;

function TranslatorGlobalConstantLong.getLongValue(): int64;
begin
    result := longBuild(int1, int0).native;
end;

function TranslatorGlobalConstantLong.getUltraValue(): ultra;
begin
    result := ultraBuild(0, 0, int1, int0);
end;

function TranslatorGlobalConstantLong.getRealValue(): real;
begin
    result := longBuild(int1, int0).native;
end;

function TranslatorGlobalConstantLong.getXVectorValue(): xvector;
begin
    result := xvectorBuild(0, 0, 0, longBuild(int1, int0).native);
end;

{ TranslatorGlobalConstantUltra }

constructor TranslatorGlobalConstantUltra.create(entryOwner: Namespace; entryPublic: boolean;
        const entryName: UnicodeString; constType: TypeDescriptor; const constValue: ultra);
begin
    inherited create(entryOwner, entryPublic, entryName, constType, constValue.longs[0].native);
    self.int2 := constValue.ints[2];
    self.int3 := constValue.ints[3];
end;

function TranslatorGlobalConstantUltra.getUltraValue(): ultra; assembler;
asm
    { ВХОД:     eax – self
                edx – результат }
                push            dword [eax + offset int3]
                push            dword [eax + offset int2]
                push            dword [eax + offset int1]
                push            dword [eax + offset int0]
                movdqu          xmm0, [esp]
                movdqu          [edx], xmm0
                lea             esp, [esp + $10]
end;

function TranslatorGlobalConstantUltra.getRealValue(): real;
begin
    result := longToReal(longBuild(int1, int0));
end;

function TranslatorGlobalConstantUltra.getXVectorValue(): xvector; assembler;
asm
    { ВХОД:     eax – self
                edx – результат }
                push            dword [eax + offset int3]
                push            dword [eax + offset int2]
                push            dword [eax + offset int1]
                push            dword [eax + offset int0]
                movdqu          xmm0, [esp]
                cvtdq2ps        xmm0, xmm0
                movups          [edx], xmm0
                lea             esp, [esp + $10]
end;

{ TranslatorGlobalConstantReal }

constructor TranslatorGlobalConstantReal.create(entryOwner: Namespace; entryPublic: boolean;
        const entryName: UnicodeString; constType: TypeDescriptor; const constValue: real);
begin
    inherited create(entryOwner, entryPublic, entryName, constType);
    if constType <> nil then begin
        case constType.kind of
        TranslatorType.KIND_FLOAT:
            self.value := realToFloat(constValue);
        TranslatorType.KIND_DOUBLE:
            self.value := realToDouble(constValue);
        else
            self.value := constValue;
        end;
    end else begin
        self.value := constValue;
    end;
end;

function TranslatorGlobalConstantReal.getBooleanValue(): boolean;
begin
    result := false;
end;

function TranslatorGlobalConstantReal.getCharValue(): int;
begin
    result := realToInt(value) and $ffff;
end;

function TranslatorGlobalConstantReal.getByteValue(): int;
begin
    result := byte(realToInt(value));
end;

function TranslatorGlobalConstantReal.getShortValue(): int;
begin
    result := short(realToInt(value));
end;

function TranslatorGlobalConstantReal.getIntValue(): int;
begin
    result := realToInt(value);
end;

function TranslatorGlobalConstantReal.getLongValue(): int64;
begin
    result := realToLong(value);
end;

function TranslatorGlobalConstantReal.getUltraValue(): ultra;
begin
    result := ultraBuild(0, realToLong(value));
end;

function TranslatorGlobalConstantReal.getRealValue(): real;
begin
    result := value;
end;

function TranslatorGlobalConstantReal.getXVectorValue(): xvector;
begin
    result := xvectorBuild(0, 0, 0, value);
end;

{ TranslatorGlobalConstantXVector }

constructor TranslatorGlobalConstantXVector.create(entryOwner: Namespace; entryPublic: boolean;
        const entryName: UnicodeString; constType: TypeDescriptor; const constValue: xvector);
begin
    inherited create(entryOwner, entryPublic, entryName, constType);
    self.value := constValue;
end;

function TranslatorGlobalConstantXVector.getBooleanValue(): boolean;
begin
    result := false;
end;

function TranslatorGlobalConstantXVector.getCharValue(): int;
begin
    result := realToInt(value.floats[0]) and $ffff;
end;

function TranslatorGlobalConstantXVector.getByteValue(): int;
begin
    result := byte(realToInt(value.floats[0]));
end;

function TranslatorGlobalConstantXVector.getShortValue(): int;
begin
    result := short(realToInt(value.floats[0]));
end;

function TranslatorGlobalConstantXVector.getIntValue(): int;
begin
    result := realToInt(value.floats[0]);
end;

function TranslatorGlobalConstantXVector.getLongValue(): int64;
begin
    result := realToLong(value.floats[0]);
end;

function TranslatorGlobalConstantXVector.getUltraValue(): ultra; assembler;
asm
    { ВХОД:     eax – self
                edx – результат }
                movups          xmm0, [eax + offset value]
                movups          xmm1, xmm0
                movups          xmm2, [MAX_INT_AS_XVECTOR]
                movups          xmm3, xmm0
                cvttps2dq       xmm0, xmm0
                cmpps           xmm1, xmm1, $07 { ordered }
                cmpps           xmm2, xmm3, $02 { ordered, <= }
                paddd           xmm0, xmm2
                pand            xmm0, xmm1
                movdqu          [edx], xmm0
end;

function TranslatorGlobalConstantXVector.getRealValue(): real;
begin
    result := value.floats[0];
end;

function TranslatorGlobalConstantXVector.getXVectorValue(): xvector; assembler;
asm
    { ВХОД:     eax – self
                edx – результат }
                movups          xmm0, [eax + offset value]
                movups          [edx], xmm0
end;

{ TranslatorGlobalException }

constructor TranslatorGlobalException.create(entryOwner: Namespace; entryPublic: boolean;
        const entryName: UnicodeString; ancestorException: GlobalException);
begin
    inherited create(entryOwner, entryPublic, entryName);
    self.ancestor := ancestorException;
end;

function TranslatorGlobalException.isInheritedFrom(exceptionForTest: GlobalException): boolean;
var
    current: GlobalException;
    obj: TObject;
begin
    current := self;
    obj := exceptionForTest as TObject;
    while (current <> nil) and ((current as TObject) <> obj) do begin
        current := current.ancestor;
    end;
    result := (current as TObject) = obj;
end;

function TranslatorGlobalException.getAncestor(): GlobalException;
begin
    result := ancestor;
end;

{ TranslatorGlobalFunction }

constructor TranslatorGlobalFunction.create(entryOwner: Namespace; entryPublic: boolean;
        const entryName: UnicodeString; operandSize, codeType: int; returnType: TypeDescriptor);
begin
    inherited create(entryOwner, entryPublic, entryName);
    if (codeType and 2) <> 0 then begin
        codeType := codeType or 1;
    end;
    self.codeType := codeType and 7;
    self.funcType := TranslatorTypeFunction.create(operandSize, returnType);
end;

function TranslatorGlobalFunction.isInterrupt(): boolean;
begin
    result := (codeType and 4) <> 0;
end;

function TranslatorGlobalFunction.isAssembler(): boolean;
begin
    result := (codeType and 1) <> 0;
end;

function TranslatorGlobalFunction.isPureAssembler(): boolean;
begin
    result := (codeType and 2) <> 0;
end;

function TranslatorGlobalFunction.getFunctionType(): TypeFunction;
begin
    result := funcType;
end;

{ TranslatorNamespace }

constructor TranslatorNamespace.create(const name: UnicodeString;
        lexemes: Lexer; operandSize: int);
begin
    inherited create();
    self.operandSize := operandSize;
    self.startPosition := -1;
    self.declarePosition := -1;
    self.importsCount := 0;
    self.entriesCount := 0;
    self.imports := nil;
    self.entries := nil;
    self.lexemes := lexemes;
    self.name := name;
    self.textRepresentation := stringToUTF8(name);
end;

function TranslatorNamespace.toString(): AnsiString;
begin
    result := textRepresentation;
end;

procedure TranslatorNamespace.setDeclarePosition(declarePosition: int);
begin
    self.declarePosition := declarePosition;
end;

procedure TranslatorNamespace.setStartPosition(startPosition: int);
begin
    self.startPosition := startPosition;
end;

function TranslatorNamespace.getDeclarePosition(): int;
begin
    result := declarePosition;
end;

function TranslatorNamespace.getStartPosition(): int;
begin
    result := startPosition;
end;

function TranslatorNamespace.getName(): UnicodeString;
begin
    result := name;
end;

procedure TranslatorNamespace.clear();
var
    i: int;
    c: int;
    current: NamespaceEntry;
    entries: NamespaceEntry_Array1d;
begin
    c := self.entriesCount - 1;
    entries := self.entries;
    for i := 0 to c do begin
        current := entries[i];
        if current is TypeStructure then begin
            (current as TypeStructure).clear();
        end;
    end;
    self.importsCount := 0;
    self.entriesCount := 0;
    self.imports := nil;
    self.entries := nil;
end;

procedure TranslatorNamespace.addImport(import: Namespace);
var
    c: int;
    imports: Namespace_Array1d;
    newimports: Namespace_Array1d;
begin
    if import = nil then begin
        raise NullPointerException.create(msgNullPointer);
    end;
    c := self.importsCount;
    imports := self.imports;
    if length(imports) = c then begin
        newimports := Namespace_Array1d(Interface_Array1d_create((c shl 1) + 1));
        arraycopyInterfaces(imports, 0, newimports, 0, c);
        self.imports := newimports;
        imports := newimports;
    end;
    imports[c] := import;
    self.importsCount := c + 1;
end;

function TranslatorNamespace.isImported(const namespaceName: UnicodeString): boolean;
var
    i: int;
    imports: Namespace_Array1d;
begin
    imports := self.imports;
    for i := importsCount - 1 downto 0 do begin
        if imports[i].name = namespaceName then begin
            result := true;
            exit;
        end;
    end;
    result := false;
end;

function TranslatorNamespace.isVisible(entry: NamespaceEntry): boolean;
begin
    if entry = nil then begin
        raise NullPointerException.create(msgNullPointer);
    end;
    result := entry.publicObject or ((entry.owner as TObject) = self);
end;

function TranslatorNamespace.isVisible(field: StructureField): boolean;
var
    struc: NamespaceEntry;
begin
    if field = nil then begin
        raise NullPointerException.create(msgNullPointer);
    end;
    if field.publicObject then begin
        result := true;
        exit;
    end;
    struc := field.owner as NamespaceEntry;
    if struc = nil then begin
        result := false;
        exit;
    end;
    result := (struc.owner as TObject) = self;
end;

function TranslatorNamespace.getImportsCount(): int;
begin
    result := importsCount;
end;

function TranslatorNamespace.getEntriesCount(): int;
begin
    result := entriesCount;
end;

function TranslatorNamespace.getImport(index: int): Namespace;
begin
    if (index < 0) or (index >= importsCount) then begin
        raise IndexOutOfBoundsException.create(msgIndexOutOfBounds);
    end;
    result := imports[index];
end;

function TranslatorNamespace.getEntry(index: int): NamespaceEntry;
begin
    if (index < 0) or (index >= entriesCount) then begin
        raise IndexOutOfBoundsException.create(msgIndexOutOfBounds);
    end;
    result := entries[index];
end;

function TranslatorNamespace.getLexemes(): Lexer;
begin
    result := lexemes;
end;

function TranslatorNamespace.addVariable(entryPublic: boolean;
        const entryName: UnicodeString; varType: TypeDescriptor): GlobalVariable;
begin
    if varType = nil then begin
        raise NullPointerException.create(msgNullPointer);
    end;
    result := TranslatorGlobalVariable.create(self, entryPublic, entryName, varType);
    addEntry(result as NamespaceEntry);
end;

function TranslatorNamespace.addConstant(entryPublic: boolean;
        const entryName: UnicodeString; constType: TypeDescriptor;
        const constValue: real): GlobalConstant;
begin
    if constType = nil then begin
        raise NullPointerException.create(msgNullPointer);
    end;
    case constType.kind of
    TranslatorType.KIND_BOOLEAN,
    TranslatorType.KIND_CHAR,
    TranslatorType.KIND_BYTE,
    TranslatorType.KIND_SHORT,
    TranslatorType.KIND_INT:
        result := TranslatorGlobalConstantInt.create(self, entryPublic, entryName, constType,
                realToInt(constValue));
    TranslatorType.KIND_LONG:
        result := TranslatorGlobalConstantLong.create(self, entryPublic, entryName, constType,
                realToLong(constValue));
    TranslatorType.KIND_FLOAT,
    TranslatorType.KIND_DOUBLE,
    TranslatorType.KIND_REAL:
        result := TranslatorGlobalConstantReal.create(self, entryPublic, entryName, constType,
                constValue);
    else
        raise IllegalArgumentException.create(msgIllegalArgument + 'constType');
    end;
    addEntry(result as NamespaceEntry);
end;

function TranslatorNamespace.addConstantUltra(entryPublic: boolean;
        const entryName: UnicodeString; constType: TypeDescriptor;
        const constValue: ultra): GlobalConstant;
begin
    if constType = nil then begin
        raise NullPointerException.create(msgNullPointer);
    end;
    if constType.kind <> TranslatorType.KIND_ULTRA then begin
        raise IllegalArgumentException.create(msgIllegalArgument + 'constType');
    end;
    result := TranslatorGlobalConstantUltra.create(self, entryPublic, entryName, constType,
            constValue);
    addEntry(result as NamespaceEntry);
end;

function TranslatorNamespace.addConstantXVector(entryPublic: boolean;
        const entryName: UnicodeString; constType: TypeDescriptor;
        const constValue: xvector): GlobalConstant;
begin
    if constType = nil then begin
        raise NullPointerException.create(msgNullPointer);
    end;
    if constType.kind <> TranslatorType.KIND_XVECTOR then begin
        raise IllegalArgumentException.create(msgIllegalArgument + 'constType');
    end;
    result := TranslatorGlobalConstantXVector.create(self, entryPublic, entryName, constType,
            constValue);
    addEntry(result as NamespaceEntry);
end;

function TranslatorNamespace.addException(entryPublic: boolean;
        const entryName: UnicodeString; ancestor: GlobalException): GlobalException;
begin
    result := TranslatorGlobalException.create(self, entryPublic, entryName, ancestor);
    addEntry(result as NamespaceEntry);
end;

function TranslatorNamespace.addStructure(entryPublic: boolean;
        const entryName: UnicodeString; ancestor: TypeStructure): TypeStructure;
begin
    result := TranslatorTypeStructure.create(self, entryPublic, entryName, operandSize, ancestor);
    addEntry(result as NamespaceEntry);
end;

function TranslatorNamespace.addStructureExt(entryPublic: boolean;
        const entryName: UnicodeString; ancestor: TypeStructure): NamespaceEntry;
begin
    result := TranslatorTypeStructure.create(self, entryPublic, entryName, operandSize, ancestor);
    addEntry(result as NamespaceEntry);
end;

function TranslatorNamespace.addFunction(entryPublic: boolean;
        const entryName: UnicodeString; codeType: int; returnType: TypeDescriptor): GlobalFunction;
begin
    result := TranslatorGlobalFunction.create(self, entryPublic, entryName, operandSize, codeType,
            returnType);
    addEntry(result as NamespaceEntry);
end;

function TranslatorNamespace.findEntry(const entryName: UnicodeString;
        findInImports: boolean): NamespaceEntry;
var
    i: int;
    j: int;
    c: int;
    currentImport: Namespace;
    currentEntry: NamespaceEntry;
    imports: Namespace_Array1d;
    entries: NamespaceEntry_Array1d;
begin
    c := self.entriesCount - 1;
    entries := self.entries;
    for j := 0 to c do begin
        currentEntry := entries[j];
        if currentEntry.name = entryName then begin
            result := currentEntry;
            exit;
        end;
    end;
    if findInImports then begin
        imports := self.imports;
        for i := self.importsCount - 1 downto 0 do begin
            currentImport := imports[i];
            c := currentImport.getEntriesCount() - 1;
            for j := 0 to c do begin
                currentEntry := currentImport.getEntry(j);
                if (currentEntry.name = entryName) and isVisible(currentEntry) then begin
                    result := currentEntry;
                    exit;
                end;
            end;
        end;
    end;
    result := nil;
end;

procedure TranslatorNamespace.addEntry(entry: NamespaceEntry);
var
    c: int;
    entries: NamespaceEntry_Array1d;
    newentries: NamespaceEntry_Array1d;
begin
    c := self.entriesCount;
    entries := self.entries;
    if length(entries) = c then begin
        newentries := NamespaceEntry_Array1d(Interface_Array1d_create((c shl 1) + 1));
        arraycopyInterfaces(entries, 0, newentries, 0, c);
        self.entries := newentries;
        entries := newentries;
    end;
    entries[c] := entry;
    self.entriesCount := c + 1;
end;

end.