trantype.pas

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

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

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

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

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

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

unit TranType;

{$MODE DELPHI,EXTENDEDSYNTAX ON}

interface

uses
    Lang, TranIntf;

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

type
    TranslatorType = class;
    TranslatorTypePrimitive = class;
    TranslatorTypeArray = class;
    TranslatorTypeFunction = class;
    TranslatorTypeStructure = class;
    TranslatorNameAndTypeObject = class;
    TranslatorLocalVariable = class;
    TranslatorStructureField = class;

    TranslatorType = class(RefCountInterfacedObject, TypeDescriptor)
    public                          //доступен| общий
        const KIND_VOID    = $0000; // везде  |
        const KIND_BOOLEAN = $0001; // везде  | везде
        const KIND_CHAR    = $0002; // везде  |
        const KIND_BYTE    = $0101; // везде  |
        const KIND_SHORT   = $0102; // везде  | 16
        const KIND_INT     = $0104; // 32, 64 | 32, 64
        const KIND_LONG    = $0108; // 64     | 64
        const KIND_ULTRA   = $0210; // 64     | 64
        const KIND_FLOAT   = $0304; // везде  | везде
        const KIND_DOUBLE  = $0308; // везде  | везде
        const KIND_REAL    = $030a; // везде  | везде
        const KIND_XVECTOR = $0410; // 64     | 64
        const KIND_STRUCT  = $0500; // везде
        const KIND_ARRAY   = $0600; // везде
        const KIND_FUNC    = $0700; // везде
        const SIZE_16_BIT  = $0002;
        const SIZE_32_BIT  = $0004;
        const SIZE_64_BIT  = $0008;

    public
        constructor create(kind: int);
        function possibleCastTo(typeForTest: TypeDescriptor): boolean; virtual; abstract;
        function possibleAssignTo(typeForTest: TypeDescriptor): boolean; virtual; abstract;
        function isMatchForConstant(): boolean; virtual;
        function isMatchForVariable(): boolean; virtual;
        function isMatchForReturnType(): boolean; virtual;
        function getAlignedSize(operandSize: int): int; virtual;
        function getKind(): int; virtual;
        function getSize(): int; virtual;
    private
        kind: int;
    end;

    TranslatorTypePrimitive = class(TranslatorType, TypePrimitive)
    public
        function equals(obj: TObject): boolean; override;
        function getHashCode(): int; override;
        function toString(): AnsiString; override;
        function possibleCastTo(typeForTest: TypeDescriptor): boolean; override;
        function possibleAssignTo(typeForTest: TypeDescriptor): boolean; override;
        function possibleAssignLong(value: long): boolean; virtual;
    end;

    TranslatorTypeArray = class(TranslatorType, TypeArray)
    public
        constructor create(operandSize: int; elementType: TypeDescriptor);
        function equals(obj: TObject): boolean; override;
        function getHashCode(): int; override;
        function toString(): AnsiString; override;
        function possibleCastTo(typeForTest: TypeDescriptor): boolean; override;
        function possibleAssignTo(typeForTest: TypeDescriptor): boolean; override;
        function getDimensions(): int; virtual;
        function getCellType(): TypeDescriptor; virtual;
        function getElementType(): TypeDescriptor; virtual;
    strict private
        dimensions: int;
        cellType: TypeDescriptor;
        elementType: TypeDescriptor;
        textRepresentation: AnsiString;
    end;

    TranslatorTypeFunction = class(TranslatorType, TypeFunction)
    public
        constructor create(operandSize: int; returnType: TypeDescriptor);
        function equals(obj: TObject): boolean; override;
        function getHashCode(): int; override;
        function toString(): AnsiString; override;
        function possibleCastTo(typeForTest: TypeDescriptor): boolean; override;
        function possibleAssignTo(typeForTest: TypeDescriptor): boolean; override;
        function getArgumentsSize(): int; virtual;
        function getArgumentsCount(): int; virtual;
        function getReturnType(): TypeDescriptor; virtual;
        function getArgument(index: int): FunctionArgument; virtual;
        function findArgument(const argName: UnicodeString): FunctionArgument; virtual;
        function addArgument(argType: TypeDescriptor;
                const argName: UnicodeString): FunctionArgument; virtual;
    strict private
        argSize: int;
        argCount: int;
        returnType: TypeDescriptor;
        arguments: FunctionArgument_Array1d;
    end;

    TranslatorTypeStructure = class(TranslatorType, TypeStructure, NamedObject, NamespaceEntry)
    public
        constructor create(entryOwner: Namespace; entryPublic: boolean;
                const entryName: UnicodeString; operandSize: int;
                ancestorStructure: TypeStructure);
        function toString(): AnsiString; override;
        function possibleCastTo(typeForTest: TypeDescriptor): boolean; override;
        function possibleAssignTo(typeForTest: TypeDescriptor): boolean; override;
        procedure clear(); virtual;
        procedure updateSize(); virtual;
        function isInheritedFrom(ancestorForTest: TypeStructure): boolean; virtual;
        function getStructureSize(): int; virtual;
        function getFieldsCount(): int; virtual;
        function getAncestor(): TypeStructure; virtual;
        function getField(index: int): StructureField; virtual;
        function findField(const fldName: UnicodeString;
                findInAncestors: boolean): StructureField; virtual;
        function addField(fldPublic: boolean; fldType: TypeDescriptor;
                const fldName: UnicodeString): StructureField; virtual;
        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;
    strict private
        entryPublic: boolean;
        fldSize: int;
        fldCount: int;
        startPosition: int;
        declarePosition: int;
        entryOwner: Namespace;
        ancestor: TypeStructure;
        fields: StructureField_Array1d;
        entryName: UnicodeString;
        textRepresentation: AnsiString;
    end;

    TranslatorNameAndTypeObject = class(RefCountInterfacedObject, NamedObject, NameAndType)
    public
        constructor create(objType: TypeDescriptor; const objName: 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 getDataType(): TypeDescriptor; virtual;
    strict private
        startPosition: int;
        declarePosition: int;
        objType: TypeDescriptor;
        objName: UnicodeString;
        textRepresentation: AnsiString;
    end;

    TranslatorLocalVariable = class(TranslatorNameAndTypeObject, LocalVariable)
    public
        constructor create(varType: TypeDescriptor; const varName: UnicodeString);
    end;

    TranslatorStructureField = class(TranslatorNameAndTypeObject, StructureField)
    public
        constructor create(fldOwner: TypeStructure; fldOffset: int;
                fldPublic: boolean; fldType: TypeDescriptor; const fldName: UnicodeString);
        function toString(): AnsiString; override;
        function isPublic(): boolean; virtual;
        function getOffset(): int; virtual;
        function getOwner(): TypeStructure; virtual;
    strict private
        fldPublic: boolean;
        fldOffset: int;
        fldOwner: TypeStructure;
        textRepresentation: AnsiString;
    end;

implementation

type
    TranslatorFunctionArgument = class;

    TranslatorFunctionArgument = class(TranslatorLocalVariable, FunctionArgument)
    public
        constructor create(argType: TypeDescriptor; const argName: UnicodeString);
    end;

{ TranslatorType }

constructor TranslatorType.create(kind: int);
begin
    inherited create();
    self.kind := kind;
end;

function TranslatorType.isMatchForConstant(): boolean;
begin
    result := (kind > $0000) and (kind < $0500);
end;

function TranslatorType.isMatchForVariable(): boolean;
begin
    result := (kind and $00ff) > 0;
end;

function TranslatorType.isMatchForReturnType(): boolean;
begin
    result := true;
end;

function TranslatorType.getAlignedSize(operandSize: int): int;
var
    typeSize: int;
begin
    if operandSize <= 0 then begin
        result := 0;
        exit;
    end;
    typeSize := kind and $00ff;
    if (typeSize mod operandSize) <= 0 then begin
        result := typeSize;
        exit;
    end;
    result := (typeSize and (-operandSize)) + operandSize;
end;

function TranslatorType.getKind(): int;
begin
    if kind >= $0500 then begin
        result := kind and $ff00;
    end else begin
        result := kind;
    end;
end;

function TranslatorType.getSize(): int;
begin
    result := kind and $ff;
end;

{ TranslatorTypePrimitive }

function TranslatorTypePrimitive.equals(obj: TObject): boolean;
begin
    result := (obj = self) or (obj is TranslatorTypePrimitive) and
            (TranslatorTypePrimitive(obj).kind = kind);
end;

function TranslatorTypePrimitive.getHashCode(): int;
begin
    result := kind;
end;

function TranslatorTypePrimitive.toString(): AnsiString;
begin
    case kind of
    KIND_VOID:
        result := 'void';
    KIND_BOOLEAN:
        result := 'boolean';
    KIND_CHAR:
        result := 'char';
    KIND_BYTE:
        result := 'byte';
    KIND_SHORT:
        result := 'short';
    KIND_INT:
        result := 'int';
    KIND_LONG:
        result := 'long';
    KIND_ULTRA:
        result := 'ultra';
    KIND_FLOAT:
        result := 'float';
    KIND_DOUBLE:
        result := 'double';
    KIND_REAL:
        result := 'real';
    KIND_XVECTOR:
        result := 'xvector';
    else
        result := '';
    end;
end;

function TranslatorTypePrimitive.possibleCastTo(typeForTest: TypeDescriptor): boolean;
var
    kind: int;
begin
    if typeForTest = nil then begin
        result := false;
        exit;
    end;
    kind := self.kind;
    case typeForTest.kind of
    KIND_BOOLEAN:
        result := (kind = KIND_BOOLEAN);
    KIND_CHAR, KIND_BYTE, KIND_SHORT, KIND_INT, KIND_LONG, KIND_ULTRA,
    KIND_FLOAT, KIND_DOUBLE, KIND_REAL, KIND_XVECTOR:
        result := (kind = KIND_CHAR) or (kind = KIND_BYTE) or (kind = KIND_SHORT) or
                (kind = KIND_INT) or (kind = KIND_LONG) or (kind = KIND_ULTRA) or
                (kind = KIND_FLOAT) or (kind = KIND_DOUBLE) or (kind = KIND_REAL) or
                (kind = KIND_XVECTOR);
    else
        result := false;
    end;
end;

function TranslatorTypePrimitive.possibleAssignTo(typeForTest: TypeDescriptor): boolean;
var
    kind: int;
begin
    if typeForTest = nil then begin
        result := false;
        exit;
    end;
    kind := self.kind;
    case typeForTest.kind of
    KIND_BOOLEAN:
        result := (kind = KIND_BOOLEAN);
    KIND_CHAR:
        result := (kind = KIND_CHAR);
    KIND_BYTE:
        result := (kind = KIND_BYTE);
    KIND_SHORT:
        result := (kind = KIND_BYTE) or (kind = KIND_SHORT);
    KIND_INT:
        result := (kind = KIND_CHAR) or (kind = KIND_BYTE) or (kind = KIND_SHORT) or
                (kind = KIND_INT);
    KIND_LONG:
        result := (kind = KIND_CHAR) or (kind = KIND_BYTE) or (kind = KIND_SHORT) or
                (kind = KIND_INT) or (kind = KIND_LONG);
    KIND_ULTRA:
        result := (kind = KIND_CHAR) or (kind = KIND_BYTE) or (kind = KIND_SHORT) or
                (kind = KIND_INT) or (kind = KIND_LONG) or (kind = KIND_ULTRA);
    KIND_FLOAT:
        result := (kind = KIND_CHAR) or (kind = KIND_BYTE) or (kind = KIND_SHORT) or
                (kind = KIND_FLOAT);
    KIND_DOUBLE:
        result := (kind = KIND_CHAR) or (kind = KIND_BYTE) or (kind = KIND_SHORT) or
                (kind = KIND_INT) or (kind = KIND_FLOAT) or (kind = KIND_DOUBLE);
    KIND_REAL:
        result := (kind = KIND_CHAR) or (kind = KIND_BYTE) or (kind = KIND_SHORT) or
                (kind = KIND_INT) or (kind = KIND_LONG) or (kind = KIND_FLOAT) or
                (kind = KIND_DOUBLE) or (kind = KIND_REAL);
    KIND_XVECTOR:
        result := (kind = KIND_CHAR) or (kind = KIND_BYTE) or (kind = KIND_SHORT) or
                (kind = KIND_FLOAT) or (kind = KIND_XVECTOR);
    else
        result := false;
    end;
end;

function TranslatorTypePrimitive.possibleAssignLong(value: long): boolean;
begin
    case kind of
    KIND_CHAR:
        result := (value >= $0000) and (value <= $ffff);
    KIND_BYTE:
        result := (value >= -$80) and (value <= $7f);
    KIND_SHORT:
        result := (value >= -$8000) and (value <= $7fff);
    KIND_INT:
        result := (value >= -$80000000) and (value <= $7fffffff);
    KIND_FLOAT, KIND_XVECTOR:
        result := (value >= -$01000000) and (value <= $01000000);
    KIND_DOUBLE:
        result := (value >= -$0020000000000000) and (value <= $0020000000000000);
    KIND_REAL, KIND_LONG, KIND_ULTRA:
        result := true;
    else
        result := false;
    end;
end;

{ TranslatorTypeArray }

constructor TranslatorTypeArray.create(operandSize: int; elementType: TypeDescriptor);
var
    dimensions: int;
    cellType: TypeDescriptor;
begin
    inherited create(KIND_ARRAY or (operandSize and $ff));
    dimensions := 1;
    cellType := elementType;
    while cellType is TypeArray do begin
        inc(dimensions);
        cellType := (cellType as TypeArray).elementType;
    end;
    self.dimensions := dimensions;
    self.cellType := cellType;
    self.elementType := elementType;
    self.textRepresentation := elementType.toString() + '[]';
end;

function TranslatorTypeArray.equals(obj: TObject): boolean;
begin
    result := (obj = self) or (obj is TranslatorTypeArray) and
            (TranslatorTypeArray(obj).elementType = elementType);
end;

function TranslatorTypeArray.getHashCode(): int;
begin
    result := cellType.getHashCode() xor (1 shl dimensions);
end;

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

function TranslatorTypeArray.possibleCastTo(typeForTest: TypeDescriptor): boolean;
var
    adim: int;
    tdim: int;
    acel: TypeDescriptor;
    tcel: TypeDescriptor;
    aarr: TypeArray;
begin
    if typeForTest = nil then begin
        result := false;
        exit;
    end;
    case typeForTest.kind of
    KIND_ARRAY: begin
        aarr := typeForTest as TypeArray;
        tcel := self.cellType;
        acel := aarr.cellType;
        tdim := self.dimensions;
        adim := aarr.dimensions;
        if adim < tdim then begin
            result := (acel is TypeStructure) and ((acel as TypeStructure).ancestor = nil);
        end else
        if adim = tdim then begin
            result := (acel <> nil) and (tcel <> nil) and (acel.size = tcel.size) and
                    (tcel.possibleAssignTo(acel) or acel.possibleAssignTo(tcel));
        end else begin
            result := false;
        end;
    end;
    KIND_STRUCT: begin
        result := (typeForTest as TypeStructure).ancestor = nil;
    end;
    else
        result := false;
    end;
end;

function TranslatorTypeArray.possibleAssignTo(typeForTest: TypeDescriptor): boolean;
var
    adim: int;
    tdim: int;
    acel: TypeDescriptor;
    tcel: TypeDescriptor;
    aarr: TypeArray;
begin
    if typeForTest = nil then begin
        result := false;
        exit;
    end;
    case typeForTest.kind of
    KIND_ARRAY: begin
        aarr := typeForTest as TypeArray;
        tcel := self.cellType;
        acel := aarr.cellType;
        tdim := self.dimensions;
        adim := aarr.dimensions;
        if adim < tdim then begin
            result := (acel is TypeStructure) and ((acel as TypeStructure).ancestor = nil);
        end else
        if adim = tdim then begin
            result := (acel <> nil) and (tcel <> nil) and (acel.size = tcel.size) and
                    tcel.possibleAssignTo(acel);
        end else begin
            result := false;
        end;
    end;
    KIND_STRUCT: begin
        result := (typeForTest as TypeStructure).ancestor = nil;
    end;
    else
        result := false;
    end;
end;

function TranslatorTypeArray.getDimensions(): int;
begin
    result := dimensions;
end;

function TranslatorTypeArray.getCellType(): TypeDescriptor;
begin
    result := cellType;
end;

function TranslatorTypeArray.getElementType(): TypeDescriptor;
begin
    result := elementType;
end;

{ TranslatorTypeFunction }

constructor TranslatorTypeFunction.create(operandSize: int; returnType: TypeDescriptor);
begin
    inherited create(KIND_FUNC or (operandSize and $ff));
    self.argSize := 0;
    self.argCount := 0;
    self.returnType := returnType;
    self.arguments := nil;
end;

function TranslatorTypeFunction.equals(obj: TObject): boolean;
var
    i: int;
    c: int;
    afunc: TranslatorTypeFunction;
    aargs: FunctionArgument_Array1d;
    targs: FunctionArgument_Array1d;
begin
    if obj = self then begin
        result := true;
        exit;
    end;
    if not (obj is TranslatorTypeFunction) then begin
        result := false;
        exit;
    end;
    afunc := TranslatorTypeFunction(obj);
    c := self.argCount;
    if (self.returnType <> afunc.returnType) or (c <> afunc.argCount) then begin
        result := false;
        exit;
    end;
    aargs := afunc.arguments;
    targs := self.arguments;
    for i := c - 1 downto 0 do begin
        if aargs[i].dataType <> targs[i].dataType then begin
            result := false;
            exit;
        end;
    end;
    result := true;
end;

function TranslatorTypeFunction.getHashCode(): int;
var
    i: int;
    c: int;
    returnType: TypeDescriptor;
    arguments: FunctionArgument_Array1d;
begin
    c := self.argCount - 1;
    returnType := self.returnType;
    arguments := self.arguments;
    if returnType <> nil then begin
        result := returnType.getHashCode();
    end else begin
        result := 0;
    end;
    for i := 0 to c do begin
        result := (31 * result) + arguments[i].dataType.getHashCode();
    end;
end;

function TranslatorTypeFunction.toString(): AnsiString;
var
    i: int;
    c: int;
    returnType: TypeDescriptor;
    arguments: FunctionArgument_Array1d;
begin
    c := self.argCount - 1;
    returnType := self.returnType;
    arguments := self.arguments;
    if returnType <> nil then begin
        result := returnType.toString();
    end else begin
        result := '<untyped>';
    end;
    result := result + '(';
    for i := 0 to c do begin
        result := result + arguments[i].dataType.toString();
        if i < c then begin
            result := result + ', ';
        end;
    end;
    result := result + ')';
end;

function TranslatorTypeFunction.possibleCastTo(typeForTest: TypeDescriptor): boolean;
begin
    if typeForTest = nil then begin
        result := false;
        exit;
    end;
    case typeForTest.kind of
    KIND_FUNC: begin
        result := equals(typeForTest as TObject);
    end;
    KIND_STRUCT: begin
        result := (typeForTest as TypeStructure).ancestor = nil;
    end;
    else
        result := false;
    end;
end;

function TranslatorTypeFunction.possibleAssignTo(typeForTest: TypeDescriptor): boolean;
begin
    if typeForTest = nil then begin
        result := false;
        exit;
    end;
    case typeForTest.kind of
    KIND_FUNC: begin
        result := equals(typeForTest as TObject);
    end;
    KIND_STRUCT: begin
        result := (typeForTest as TypeStructure).ancestor = nil;
    end;
    else
        result := false;
    end;
end;

function TranslatorTypeFunction.getArgumentsSize(): int;
begin
    result := argSize;
end;

function TranslatorTypeFunction.getArgumentsCount(): int;
begin
    result := argCount;
end;

function TranslatorTypeFunction.getReturnType(): TypeDescriptor;
begin
    result := returnType;
end;

function TranslatorTypeFunction.getArgument(index: int): FunctionArgument;
begin
    if (index < 0) or (index >= argCount) then begin
        raise IndexOutOfBoundsException.create(msgIndexOutOfBounds);
    end;
    result := arguments[index];
end;

function TranslatorTypeFunction.findArgument(const argName: UnicodeString): FunctionArgument;
var
    i: int;
    c: int;
    current: FunctionArgument;
    arguments: FunctionArgument_Array1d;
begin
    c := self.argCount - 1;
    arguments := self.arguments;
    for i := 0 to c do begin
        current := arguments[i];
        if current.name = argName then begin
            result := current;
            exit;
        end;
    end;
    result := nil;
end;

function TranslatorTypeFunction.addArgument(argType: TypeDescriptor;
        const argName: UnicodeString): FunctionArgument;
var
    c: int;
    arguments: FunctionArgument_Array1d;
    newarguments: FunctionArgument_Array1d;
begin
    if argType = nil then begin
        raise NullPointerException.create(msgNullPointer);
    end;
    c := self.argCount;
    arguments := self.arguments;
    if length(arguments) = c then begin
        newarguments := FunctionArgument_Array1d(Interface_Array1d_create((c shl 1) + 1));
        arraycopyInterfaces(arguments, 0, newarguments, 0, c);
        self.arguments := newarguments;
        arguments := newarguments;
    end;
    result := TranslatorFunctionArgument.create(argType, argName);
    inc(self.argSize, argType.getAlignedSize(kind and $ff));
    arguments[c] := result;
    self.argCount := c + 1;
end;

{ TranslatorTypeStructure }

constructor TranslatorTypeStructure.create(entryOwner: Namespace; entryPublic: boolean;
        const entryName: UnicodeString; operandSize: int; ancestorStructure: TypeStructure);
var
    representation: UnicodeString;
begin
    inherited create(KIND_STRUCT or (operandSize and $ff));
    if (entryOwner <> nil) and (length(entryName) > 0) then begin
        representation := entryOwner.name + '.' + entryName;
    end else begin
        representation := entryName;
    end;
    self.entryPublic := entryPublic;
    self.fldSize := 0;
    self.fldCount := 0;
    self.startPosition := -1;
    self.declarePosition := -1;
    self.entryOwner := entryOwner;
    self.ancestor := ancestorStructure;
    self.fields := nil;
    self.entryName := entryName;
    self.textRepresentation := stringToUTF8(representation);
end;

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

function TranslatorTypeStructure.possibleCastTo(typeForTest: TypeDescriptor): boolean;
var
    astr: TypeStructure;
begin
    if typeForTest = nil then begin
        result := false;
        exit;
    end;
    case typeForTest.kind of
    KIND_ARRAY, KIND_FUNC: begin
        result := ancestor = nil;
    end;
    KIND_STRUCT: begin
        astr := typeForTest as TypeStructure;
        result := astr.isInheritedFrom(self) or self.isInheritedFrom(astr);
    end;
    else
        result := false;
    end;
end;

function TranslatorTypeStructure.possibleAssignTo(typeForTest: TypeDescriptor): boolean;
begin
    result := (typeForTest <> nil) and (typeForTest is TypeStructure) and
            isInheritedFrom(typeForTest as TypeStructure);
end;

procedure TranslatorTypeStructure.clear();
begin
    fldSize := 0;
    fldCount := 0;
    fields := nil;
end;

procedure TranslatorTypeStructure.updateSize();
var
    ancestor: TypeStructure;
begin
    ancestor := self.ancestor;
    if ancestor <> nil then begin
        fldSize := ancestor.structureSize;
    end;
end;

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

function TranslatorTypeStructure.getStructureSize(): int;
begin
    result := fldSize;
end;

function TranslatorTypeStructure.getFieldsCount(): int;
begin
    result := fldCount;
end;

function TranslatorTypeStructure.getAncestor(): TypeStructure;
begin
    result := ancestor;
end;

function TranslatorTypeStructure.getField(index: int): StructureField;
begin
    if (index < 0) or (index >= fldCount) then begin
        raise IndexOutOfBoundsException.create(msgIndexOutOfBounds);
    end;
    result := fields[index];
end;

function TranslatorTypeStructure.findField(const fldName: UnicodeString;
        findInAncestors: boolean): StructureField;
var
    i: int;
    c: int;
    ancestor: TypeStructure;
    current: StructureField;
    fields: StructureField_Array1d;
begin
    c := self.fldCount - 1;
    fields := self.fields;
    for i := 0 to c do begin
        current := fields[i];
        if current.name = fldName then begin
            result := current;
            exit;
        end;
    end;
    ancestor := self.ancestor;
    if findInAncestors and (ancestor <> nil) then begin
        result := ancestor.findField(fldName, true);
        exit;
    end;
    result := nil;
end;

function TranslatorTypeStructure.addField(fldPublic: boolean; fldType: TypeDescriptor;
        const fldName: UnicodeString): StructureField;
var
    c: int;
    offset: int;
    fields: StructureField_Array1d;
    newfields: StructureField_Array1d;
begin
    if fldType = nil then begin
        raise NullPointerException.create(msgNullPointer);
    end;
    c := self.fldCount;
    offset := self.fldSize;
    fields := self.fields;
    if length(fields) = c then begin
        newfields := StructureField_Array1d(Interface_Array1d_create((c shl 1) + 1));
        arraycopyInterfaces(fields, 0, newfields, 0, c);
        self.fields := newfields;
        fields := newfields;
    end;
    result := TranslatorStructureField.create(self, offset, fldPublic, fldType, fldName);
    self.fldSize := offset + fldType.size;
    fields[c] := result;
    self.fldCount := c + 1;
end;

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

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

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

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

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

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

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

{ TranslatorNameAndTypeObject }

constructor TranslatorNameAndTypeObject.create(objType: TypeDescriptor;
        const objName: UnicodeString);
var
    representation: AnsiString;
begin
    inherited create();
    if objType <> nil then begin
        representation := objType.toString();
    end else begin
        representation := '<untyped>';
    end;
    self.startPosition := -1;
    self.declarePosition := -1;
    self.objType := objType;
    self.objName := objName;
    self.textRepresentation := representation + #$20 + stringToUTF8(objName);
end;

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

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

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

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

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

function TranslatorNameAndTypeObject.getName(): UnicodeString;
begin
    result := objName;
end;

function TranslatorNameAndTypeObject.getDataType(): TypeDescriptor;
begin
    result := objType;
end;

{ TranslatorLocalVariable }

constructor TranslatorLocalVariable.create(varType: TypeDescriptor; const varName: UnicodeString);
begin
    inherited create(varType, varName);
end;

{ TranslatorStructureField }

constructor TranslatorStructureField.create(fldOwner: TypeStructure; fldOffset: int;
        fldPublic: boolean; fldType: TypeDescriptor; const fldName: UnicodeString);
var
    ownedEntry: NamespaceEntry;
    ownedNamespace: Namespace;
    representation: UnicodeString;
begin
    inherited create(fldType, fldName);
    if fldOwner is NamespaceEntry then begin
        ownedEntry := fldOwner as NamespaceEntry;
        ownedNamespace := ownedEntry.owner;
        if ownedNamespace <> nil then begin
            representation := ownedNamespace.name + '.' + ownedEntry.name + '.' + fldName;
        end else begin
            representation := ownedEntry.name + '.' + fldName;
        end;
    end else begin
        representation := fldName;
    end;
    if fldType <> nil then begin
        representation := stringToUTF16(fldType.toString() + #$20) + representation;
    end else begin
        representation := '<untyped> ' + representation;
    end;
    self.fldPublic := fldPublic;
    self.fldOffset := fldOffset;
    self.fldOwner := fldOwner;
    self.textRepresentation := stringToUTF8(representation);
end;

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

function TranslatorStructureField.isPublic(): boolean;
begin
    result := fldPublic;
end;

function TranslatorStructureField.getOffset(): int;
begin
    result := fldOffset;
end;

function TranslatorStructureField.getOwner(): TypeStructure;
begin
    result := fldOwner;
end;

{ TranslatorFunctionArgument }

constructor TranslatorFunctionArgument.create(argType: TypeDescriptor;
        const argName: UnicodeString);
begin
    inherited create(argType, argName);
end;

end.