{
Компилятор языка программирования
Объектно-ориентированный продвинутый векторный транслятор
Copyright © 2021, 2024, 2026 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
}
unit ru.malik.elaborarer.avtoo.compiler;
{$MODE OBJFPC}
interface
{%region} uses
pascalx.lang,
pascalx.lang.math.avo,
pascalx.lang.math.vcoverage,
pascalx.lang.table,
pascalx.io,
platform.independent.filesystem,
platform.independent.osservices,
platform.independent.streamformat,
ru.malik.elaborarer.avtoo.lang;
{%endregion}
{$TYPEINFO ON}
{$CALLING REGISTER}
const UNIT_NAME = 'ru.malik.elaborarer.avtoo.compiler';
{%region} type
CompilerRunnable = interface;
CompilerThreadObjectCreator = interface;
AnsiStringHolder = interface;
OperatorHolder = interface;
TypeHolder = interface;
PackageHolder = interface;
ObjectVector = class;
UnicodeStringArray = class;
Lexer = class;
LanguageLexer = class;
DocumentLexer = class;
RecompilableElement = class;
PackageElement = class;
TypeElement = class;
TypedMemberElement = class;
FieldElement = class;
CallableElement = class;
PropertyElement = class;
CompilerParallelWorker = class;
Project = class;
TableBuilder = class;
ImmediateBuilder = class;
ImmediateBuilderItemHolder = class;
IllegalParallelWorkerState = class;
CompilerRunnable = interface(RefCountInterface) ['{62DCBE06-FB75-4E4A-8417-0F76887F0A79}']
procedure run(target: TObject);
end;
CompilerThreadObjectCreator = interface(CompilerRunnable) ['{62DCBE06-FB75-4E4A-8417-0F76887F0A7A}']
function createThreadObject(): TObject;
end;
AnsiStringHolder = interface(RawInterface) ['{62DCBE06-FB75-4E4A-8417-0F76887F0A7B}']
procedure appendResultString(const suffix: AnsiString);
end;
OperatorHolder = interface(RawInterface) ['{62DCBE06-FB75-4E4A-8417-0F76887F0A7C}']
procedure setResultKind(newResultKind: int);
function getResultKind(): int;
property resultKind: int read getResultKind write setResultKind;
end;
TypeHolder = interface(RawInterface) ['{62DCBE06-FB75-4E4A-8417-0F76887F0A7D}']
procedure setResultType(newResultType: &Type);
function isHelpersAllowed(): boolean;
function getResultType(): &Type;
property helpersAllowed: boolean read isHelpersAllowed;
property resultType: &Type read getResultType write setResultType;
end;
PackageHolder = interface(RawInterface) ['{62DCBE06-FB75-4E4A-8417-0F76887F0A7E}']
procedure setResultPack(newResultPack: Package);
function getResultPack(): Package;
property resultPack: Package read getResultPack write setResultPack;
end;
ObjectVector = class(&Object, Measureable, ObjectArray)
strict private
fldOwned: boolean;
protected
fldLength: int;
fldArray: TObject_Array1d;
public
constructor create(owned: boolean);
constructor create(owned: boolean; const items: TObject_Array1d; length: int);
constructor create(owned: boolean; const items: ISimple_Array1d; length: int);
destructor destroy; override;
procedure clear(); virtual;
procedure append(const item: TObject);
procedure insert(index: int; const item: TObject);
function getLength(): int;
function readComponent(index: int): TObject;
function indexOf(const item: TObject): int;
function clone(): TObject_Array1d;
end;
UnicodeStringArray = class(ru.malik.elaborarer.avtoo.lang.UnicodeStringArray)
private
fldHashs: long_Array1d;
public
constructor create();
procedure clear(); virtual;
procedure append(const item: AnsiString); virtual;
procedure append(const item: UnicodeString); virtual;
function contains(const item: AnsiString): boolean; virtual;
function contains(const item: UnicodeString): boolean; virtual;
end;
Lexer = class abstract(AVTOOConstants)
public
procedure split(const text: uchar_Array2d; const locationBegin, locationEnd: int2; sequence: LexemeSequence); virtual; abstract;
end;
LanguageLexer = class(Lexer)
strict private const
UCMP = long($8000000000000000);
BLIMIT = long($8000000000000000);
OLIMIT = long($2000000000000000);
DLIMIT = long($1999999999999999);
XLIMIT = long($1000000000000000);
ILIMIT = long($0000000100000000);
strict private class var
symbols: uchar_Array1d;
lexemes: UnicodeString_Array1d;
defaultDocumentationLexer: DocumentLexer;
strict private
class function parseName(lineIndex: int; const line: uchar_Array1d; charIndex: int; chr: uchar; sequence: LexemeSequence): int; static;
class function parseChar(lineIndex: int; const line: uchar_Array1d; charIndex: int; chr: uchar; sequence: LexemeSequence): int; static;
class function parseString(lineIndex: int; const line: uchar_Array1d; charIndex: int; chr: uchar; sequence: LexemeSequence): int; static;
class function parseNumeric(lineIndex: int; const line: uchar_Array1d; charIndex: int; chr: uchar; sequence: LexemeSequence): int; static;
class function parseOperator(lineIndex: int; const line: uchar_Array1d; charIndex: int; chr: uchar; sequence: LexemeSequence): int; static;
class function parseStringChar(const line: uchar_Array1d; charIndex: int; chr: uchar): int2; static;
class function pow2(power: int): real; static;
private
class procedure initialize(); static;
class procedure finalize(); static;
strict private
function parseComment(const text: uchar_Array2d; lineIndexBegin, lineIndexEnd: int; last, line: uchar_Array1d; charIndexBegin: int; chr: uchar; sequence: LexemeSequence): int2;
protected
fldDocumentationEnabled: boolean;
fldDocumentationLexer: DocumentLexer;
procedure setDocumentationEnabled(newDocumentationEnabled: boolean); virtual;
procedure setDocumentationLexer(newDocumentationLexer: DocumentLexer); virtual;
function newDocumentLexemeSequence(): LexemeSequence; virtual;
public
constructor create();
constructor create(__documentationLexer: DocumentLexer);
procedure split(const text: uchar_Array2d; const locationBegin, locationEnd: int2; sequence: LexemeSequence); override;
property documentationEnabled: boolean read fldDocumentationEnabled write setDocumentationEnabled;
property documentationLexer: DocumentLexer read fldDocumentationLexer write setDocumentationLexer;
end;
DocumentLexer = class(Lexer)
strict private class var
symbols: uchar_Array1d;
lexemes: UnicodeString_Array1d;
strict private
class function parseChar(lineIndex: int; const line: uchar_Array1d; charIndex: int; chr: uchar; sequence: LexemeSequence): int; static;
class function parseName(lineIndex: int; const line: uchar_Array1d; charIndex: int; chr: uchar; sequence: LexemeSequence): int; static;
class function parseText(lineIndex: int; const line: uchar_Array1d; charIndex: int; chr: uchar; sequence: LexemeSequence): int; static;
private
class procedure initialize(); static;
protected
fldLineEndingEnabled: boolean;
procedure setLineEndingEnabled(newLineEndingEnabled: boolean); virtual;
public
constructor create();
procedure split(const text: uchar_Array2d; const locationBegin, locationEnd: int2; sequence: LexemeSequence); override;
property lineEndingEnabled: boolean read fldLineEndingEnabled write setLineEndingEnabled;
end;
RecompilableElement = class abstract(&Object)
protected
fldConstants: TObject_Array1d;
fldProgramme: Programme;
public
constructor create(__programme: Programme);
function getItem(): ReflectItem; virtual; abstract;
property constants: TObject_Array1d write fldConstants;
end;
PackageElement = class sealed(RecompilableElement)
strict private
fldPackage: Package;
fldRecompilableName: int;
public
constructor create(__programme: Programme; __recompilableName: int);
function getItem(): Package; override;
end;
TypeElement = class(RecompilableElement)
strict private
fldType: &Type;
fldRecompilableName: int;
protected
function parseRecompilableName(const name: AnsiString): &Type; virtual;
public
constructor create(__programme: Programme; __recompilableName: int);
function getItem(): &Type; override;
end;
TypedMemberElement = class abstract(RecompilableElement)
public
function getItem(): Member; override; abstract;
function getTypedMember(): TypedMember;
end;
FieldElement = class sealed(TypedMemberElement)
strict private
fldField: Field;
fldParentType: int;
fldRecompilableName: int;
public
constructor create(__programme: Programme; __parentType, __recompilableName: int);
function getItem(): Field; override;
end;
CallableElement = class sealed(TypedMemberElement)
strict private
fldCallable: Callable;
fldParentType: int;
fldRecompilableName: int;
fldArgumentTypes: int_Array1d;
public
constructor create(__programme: Programme; __parentType, __recompilableName: int; const __argumentTypes: int_Array1d);
function getItem(): Callable; override;
end;
PropertyElement = class sealed(TypedMemberElement)
strict private
fldProperty: &Property;
fldParentType: int;
fldRecompilableName: int;
public
constructor create(__programme: Programme; __parentType, __recompilableName: int);
function getItem(): &Property; override;
end;
CompilerParallelWorker = class(&Object)
strict private type
HashtableOfValueToTObject = specialize Hashtable<Value, TObject>;
strict private
fldIndex: int;
fldTerminates: int;
fldMaxThreads: int;
fldContext: Thread;
fldException: Exception;
fldTargets: ObjectArray;
fldMonitor: Monitor;
fldObjects: HashtableOfValueToTObject;
private
procedure terminate(__exception: Exception);
function nextTarget(): TObject;
protected
procedure setTargets(newTargets: ObjectArray); virtual;
public
constructor create(__maxThreads: int);
destructor destroy; override;
procedure run(handler: CompilerRunnable); virtual;
function threadObject(): TObject;
property maxThreads: int read fldMaxThreads;
property targets: ObjectArray read fldTargets write setTargets;
end;
Project = class abstract(Programme)
public const
PROGRAMME_DESTINATION_PATH = 'dst';
BINARY_SOURCE_PATH = 'bin';
ASSEMBLER_SOURCE_PATH = 'src.asm';
TEXT_SOURCE_MAIN_PATH = 'src.avt';
TEXT_SOURCE_ALTERNATIVE_PATH = 'src';
PACKAGE_SOURCE_EXTENSION = '.avtpack';
BINARY_SOURCE_EXTENSION = '.avtoo-recompilable';
TYPE_SOURCE_EXTENSION = '.avt';
public
class function isPackageSourceFileName(const fileName: UnicodeString): boolean; static;
class function isBinarySourceFileName(const fileName: UnicodeString): boolean; static;
class function isTypeSourceFileName(const fileName: UnicodeString): boolean; static;
strict private
fldMaxThreads: int;
fldExcludes: UnicodeStringArray;
protected
procedure prefetchSupertypesForPrimitiveArray(&array: ArrayType); override; abstract;
procedure prefetchSupertypesForObjectArray(&array: ArrayType); override; abstract;
procedure prefetchSupertypesForReferenceArray(&array: ArrayType); override; abstract;
procedure createMembersForPrimitiveArray(&array: ArrayType); override; abstract;
procedure createMembersForObjectArray(&array: ArrayType); override; abstract;
procedure setMaxThreads(newMaxThreads: int); virtual;
function getSourceType(__library: &Library): AnsiString; virtual; abstract;
public
constructor create();
destructor destroy; override;
procedure compile(); override;
property maxThreads: int read fldMaxThreads write setMaxThreads;
property excludes: UnicodeStringArray read fldExcludes;
end;
TableBuilder = class(Project)
public const
PACKNAME_ARRAY = PACKNAME_LANG + '.array';
public const
TYPENAME_RAW_DATA = 'RawData';
TYPENAME_CLONEABLE = 'Cloneable';
TYPENAME_MEASUREABLE = 'Measureable';
TYPENAME_IMMUTABLE_OBJECT = 'ImmutableObject';
TYPENAME_MUTABLE_MEASUREABLE = 'MutableMeasureable';
TYPENAME_IMMUTABLE_MEASUREABLE = 'ImmutableMeasureable';
strict private
class procedure appendImpliedSuperservices(const __classes: ClassType_Array1d); static;
class procedure appendImpliedMembers(const __classes: ClassType_Array1d); static;
class procedure checkMembers(const __classes: ClassType_Array1d); static;
class procedure checkSuperservices(const __classes: ClassType_Array1d); static;
class procedure checkSuperclasses(const __classes, __buffer: ClassType_Array1d); static;
class procedure checkOverriddable(current: ClassType; overridding, overridden: OverriddableMember); static;
class function isCompatibleTypes(overriddableA, overriddableB: OverriddableMember): boolean; static;
class function skipPropertySpecifier(source: TextSource; position: int): int; static;
class function packArguments(const arguments: Local_Array1d): Local_Array1d; static;
class function toTypedItemArray(const arguments: Local_Array1d): TypedItem_Array1d; static;
strict private
fldProject: &Library;
fldLanguageLexer: LanguageLexer;
fldDocumentationLexer: DocumentLexer;
procedure setDocumentationEnabled(newDocumentationEnabled: boolean);
function isDocumentationEnabled(): boolean;
function parseAllocatableMembers(source: TextSource; position: int; enclosing: ClassType; container: AllocatableFactory): int;
function parseArgumentsClause(source: TextSource; position: int; enclosing: ClassType; const arguments: Local_Array1d): int;
function parseThrowsClause(source: TextSource; position: int; enclosing: ClassType; method: Method): int;
private
function parsePackageName(source: TextSource; position: int; specialCanonicalName: AnsiStringHolder): int;
function parseClassName(source: TextSource; position: int; enclosing: ClassType; parsed: TypeHolder): int;
function parseTypeName(source: TextSource; position: int; enclosing: ClassType; parsed: TypeHolder): int;
function parseOperator(source: TextSource; position: int; parsed: OperatorHolder): int;
protected
procedure prefetchSupertypesForPrimitiveArray(&array: ArrayType); override;
procedure prefetchSupertypesForObjectArray(&array: ArrayType); override;
procedure prefetchSupertypesForReferenceArray(&array: ArrayType); override;
procedure createMembersForPrimitiveArray(&array: ArrayType); override;
procedure createMembersForObjectArray(&array: ArrayType); override;
function createDocumentLexer(): DocumentLexer; virtual;
function createLanguageLexer(__documentationLexer: DocumentLexer): LanguageLexer; virtual;
function newSource(parentLibrary: &Library; const relativePath: UnicodeString; const &type: AnsiString): Source; override; final;
function getSourceType(__library: &Library): AnsiString; override; final;
public
procedure afterConstruction(); override;
procedure beforeDestruction(); override;
procedure compile(); override;
procedure clear(); override;
function createLibrary(fileSystem: FileSystem; const directoryPath: UnicodeString; application: boolean): &Library; override;
property documentationEnabled: boolean read isDocumentationEnabled write setDocumentationEnabled;
property documentationLexer: DocumentLexer read fldDocumentationLexer;
property languageLexer: LanguageLexer read fldLanguageLexer;
property project: &Library read fldProject;
end;
ImmediateBuilder = class(TableBuilder)
strict private type
HashtableOfAnsiStringToLocal = specialize HashtableOfAnsiString<Local>;
strict private
class procedure requiresValue(value: Node); static;
class procedure defineAttainability(const attainability: byte_Array1d; __code: Code; length: int); static;
class procedure appendPropertyIndexCode(position: int; parent: Node; __constant: Constant; __member: TypedMember); static;
class function isLogicalConditionNode(__node: Node): boolean; static;
class function isHandledException(__type: ClassType; parent: Node; __callable: Callable): boolean; static;
class function invokeInstructionFor(foundCallable: Member; foundPlace: ClassType): int; static;
class function getUnhandledException(__method: Method; parent: Node; __callable: Callable): ClassType; static;
class function cast(value: Node; newType: &Type): Node; static;
strict private
fldLibrary: boolean;
fldStaticFieldsOnly: boolean;
fldTypeNull: NullType;
fldTypeClass: ClassType;
fldTypeObject: ClassType;
fldTypeString: ClassType;
fldTypePackage: ClassType;
fldTypeThrowable: ClassType;
fldTypeVoid: PrimitiveType;
fldTypeBoolean: PrimitiveType;
fldTypeInt: PrimitiveType;
fldTypeLong: PrimitiveType;
fldConstantFactory: ConstantFactory;
fldThreadItemHolder: CompilerParallelWorker;
fldGlobalItemHolder: ImmediateBuilderItemHolder;
procedure buildPropertySpecifiers(__property: &Property);
procedure parsePropertySpecifiers(__property: &Property);
procedure parseStaticFieldValue(__field: Field; staticBlock: ClassInit);
function parsePostfix(parent: Node; source: TextSource; position: int; isStaticOnly, isImplicitPeriod: boolean): int;
function parsePrimary(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
function parsePrefix(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
function parseMultiplicative(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
function parseAdditive(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
function parseShift(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
function parseRelational(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
function parseEquality(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
function parseBitAnd(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
function parseBitXor(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
function parseBitOr(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
function parseBoolAnd(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
function parseBoolOr(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
function parseConditional(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
function parseExpression(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
function parseDeclareLocal(parent: Node; source: TextSource; position: int; isLocalAllowed: boolean): int;
function parseDeclareWith(parent: Node; source: TextSource; position: int; isSynchronized: boolean): int;
function parseBlock(control: Node; source: TextSource; position: int): int;
function parseBreak(control: Node; source: TextSource; position: int): int;
function parseContinue(control: Node; source: TextSource; position: int): int;
function parseDo(control: Node; source: TextSource; position: int): int;
function parseFor(control: Node; source: TextSource; position: int): int;
function parseIf(control: Node; source: TextSource; position: int): int;
function parseReturn(control: Node; source: TextSource; position: int): int;
function parseSwitch(control: Node; source: TextSource; position: int): int;
function parseSynchronized(control: Node; source: TextSource; position: int): int;
function parseThrow(control: Node; source: TextSource; position: int): int;
function parseTry(control: Node; source: TextSource; position: int): int;
function parseWhile(control: Node; source: TextSource; position: int): int;
function parseWith(control: Node; source: TextSource; position: int): int;
function parseControl(parent: Node; source: TextSource; position: int): int;
function tryParseName(parent: Node; source: TextSource; position: int; const name: AnsiString; parsed: ImmediateBuilderItemHolder): int;
function tryParsePackageName(source: TextSource; position: int; enclosing: ClassType; parsed: PackageHolder): int;
function tryParseClassName(source: TextSource; position: int; enclosing: ClassType; parsed: TypeHolder): int;
function tryParseTypeName(source: TextSource; position: int; enclosing: ClassType; parsed: TypeHolder): int;
function appendIncrementCode(parent: Node; argumentType: PrimitiveType; isUseIncrement: boolean): Node;
function getAdditionalOperand(operand: int; locals: HashtableOfAnsiStringToLocal; constants: ObjectArray; index: int): TableItem;
function getAdditionalConstant(constants: ObjectArray; index: int): Constant;
function getItemHolder(): ImmediateBuilderItemHolder;
private
procedure readCallableBody(__callable: Callable);
procedure parseCallableBody(__callable: Callable);
protected
function isStaticFieldsOnly(): boolean; virtual;
function isLibrary(): boolean; virtual;
public
constructor create();
constructor create(__staticFieldsOnly: boolean);
constructor create(__staticFieldsOnly, __library: boolean);
destructor destroy; override;
procedure compile(); override;
procedure clear(); override;
property staticFieldsOnly: boolean read isStaticFieldsOnly;
property &library: boolean read isLibrary;
end;
ImmediateBuilderItemHolder = class(&Object, TypeHolder, OperatorHolder, PackageHolder)
protected
fldHelpersAllowed: boolean;
fldResultKind: int;
fldResultType: &Type;
fldResultPack: Package;
fldResultWith: Local;
fldResultItem: TableItem;
procedure setResultWith(newResultWith: Local); virtual;
procedure setResultItem(newResultItem: TableItem); virtual;
function getResultWith(): Local; virtual;
function getResultItem(): TableItem; virtual;
public
procedure setHelpersAllowed(newHelpersAllowed: boolean); virtual;
procedure setResultKind(newResultKind: int); virtual;
procedure setResultType(newResultType: &Type); virtual;
procedure setResultPack(newResultPack: Package); virtual;
function isHelpersAllowed(): boolean; virtual;
function getResultKind(): int; virtual;
function getResultType(): &Type; virtual;
function getResultPack(): Package; virtual;
property helpersAllowed: boolean read isHelpersAllowed write setHelpersAllowed;
property resultKind: int read getResultKind write setResultKind;
property resultType: &Type read getResultType write setResultType;
property resultPack: Package read getResultPack write setResultPack;
property resultWith: Local read getResultWith write setResultWith;
property resultItem: TableItem read getResultItem write setResultItem;
end;
IllegalParallelWorkerState = class(IllegalStateException);
{%endregion}
implementation
{$R *.res}
{$TYPEINFO OFF}
{$CALLING REGISTER}
{%region} type
CompilerParallelWorkerRunnable = class;
ProjectSourcesLoader = class;
TableBuilderAnsiStringHolder = class;
TableBuilderBinarySource = class;
TableBuilderClassTypeHolder = class;
TableBuilderOperatorAndTypeHolder = class;
TableBuilderSourcesLexer = class;
TableBuilderSourcesParser = class;
TableBuilderSourcesReader = class;
TableBuilderTextSource = class;
TableBuilderVectorAndTypeHolder = class;
ImmediateBuilderForBinarySources = class;
ImmediateBuilderForTextSources = class;
ImmediateBuilderUnaryOperation = class;
CompilerParallelWorkerRunnable = class sealed(&Object, Runnable)
strict private
fldParentWorker: CompilerParallelWorker;
fldHandler: CompilerRunnable;
public
constructor create(parentWorker: CompilerParallelWorker; handler: CompilerRunnable);
procedure run();
end;
ProjectSourcesLoader = class sealed(RefCountObject, CompilerRunnable)
strict private
fldParentProject: Project;
procedure findBinarySources(__library: &Library; const __relativePath: UnicodeString);
procedure findTypeSources(__library: &Library; const __relativePath: UnicodeString);
procedure findPackageSources(__library: &Library);
public
constructor create(parentProject: Project);
procedure run(target: TObject);
end;
TableBuilderAnsiStringHolder = class(&Object, AnsiStringHolder)
protected
fldResultString: AnsiString;
public
procedure appendResultString(const suffix: AnsiString); virtual;
procedure clear(); virtual;
function toString(): AnsiString; override;
end;
TableBuilderBinarySource = class(BinarySource)
public
destructor destroy; override;
end;
TableBuilderClassTypeHolder = class(&Object, TypeHolder)
protected
fldResultClassType: ClassType;
procedure setResultClassType(newResultClassType: ClassType); virtual;
function getResultClassType(): ClassType; virtual;
public
procedure setResultType(newResultType: &Type); virtual;
function isHelpersAllowed(): boolean; virtual;
function getResultType(): &Type; virtual;
property helpersAllowed: boolean read isHelpersAllowed;
property resultType: &Type read getResultType write setResultType;
property resultClassType: ClassType read getResultClassType write setResultClassType;
end;
TableBuilderOperatorAndTypeHolder = class(&Object, OperatorHolder, TypeHolder)
protected
fldResultKind: int;
fldResultType: &Type;
public
procedure setResultKind(newResultKind: int); virtual;
procedure setResultType(newResultType: &Type); virtual;
function isHelpersAllowed(): boolean; virtual;
function getResultKind(): int; virtual;
function getResultType(): &Type; virtual;
property helpersAllowed: boolean read isHelpersAllowed;
property resultKind: int read getResultKind write setResultKind;
property resultType: &Type read getResultType write setResultType;
end;
TableBuilderSourcesLexer = class sealed(RefCountObject, CompilerRunnable)
strict private
fldLexer: Lexer;
public
constructor create(__lexer: Lexer);
procedure run(target: TObject);
end;
TableBuilderSourcesParser = class sealed(RefCountObject, CompilerRunnable)
public
procedure run(target: TObject);
end;
TableBuilderSourcesReader = class sealed(RefCountObject, CompilerRunnable)
strict private
fldProgramme: Programme;
public
constructor create(__programme: Programme);
procedure run(target: TObject);
end;
TableBuilderTextSource = class(TextSource)
strict private
fldParsingTree: int_Array2d;
public
property parsingTree: int_Array2d read fldParsingTree write fldParsingTree;
end;
TableBuilderVectorAndTypeHolder = class(UnicodeStringArray, TypeHolder)
protected
fldResultType: &Type;
public
procedure setResultType(newResultType: &Type); virtual;
function isHelpersAllowed(): boolean; virtual;
function getResultType(): &Type; virtual;
property helpersAllowed: boolean read isHelpersAllowed;
property resultType: &Type read getResultType write setResultType;
end;
ImmediateBuilderForBinarySources = class sealed(RefCountObject, CompilerRunnable)
strict private
fldParent: ImmediateBuilder;
public
constructor create(parent: ImmediateBuilder);
procedure run(target: TObject);
end;
ImmediateBuilderForTextSources = class sealed(RefCountObject, CompilerRunnable, CompilerThreadObjectCreator)
strict private
fldParent: ImmediateBuilder;
public
constructor create(parent: ImmediateBuilder);
procedure run(target: TObject);
function createThreadObject(): TObject;
end;
ImmediateBuilderUnaryOperation = class sealed(&Object)
strict private
fldPosition: int;
fldOperation: int;
fldNewType: &Type;
public
constructor create(__position, __operation: int);
constructor create(__position, __operation: int; __newType: &Type);
property position: int read fldPosition;
property operation: int read fldOperation;
property newType: &Type read fldNewType;
end;
{%endregion}
{%region ObjectVector }
constructor ObjectVector.create(owned: boolean);
begin
inherited create();
fldOwned := owned;
fldArray := &Array.newTObject1d($0f);
end;
constructor ObjectVector.create(owned: boolean; const items: TObject_Array1d; length: int);
var
capacity: int;
__array: TObject_Array1d;
begin
inherited create();
capacity := system.length(items);
if length < 0 then length := 0;
if length > capacity then length := capacity;
__array := &Array.newTObject1d(AVTOOService.getBestArrayCapacity(length));
&Array.copyObjects(items, 0, __array, 0, length);
fldOwned := owned;
fldLength := length;
fldArray := __array;
end;
constructor ObjectVector.create(owned: boolean; const items: ISimple_Array1d; length: int);
var
index: int;
capacity: int;
__array: TObject_Array1d;
begin
inherited create();
capacity := system.length(items);
if length < 0 then length := 0;
if length > capacity then length := capacity;
__array := &Array.newTObject1d(AVTOOService.getBestArrayCapacity(length));
for index := length - 1 downto 0 do __array[index] := Lang.cast(items[index], TObject);
fldOwned := owned;
fldLength := length;
fldArray := __array;
end;
destructor ObjectVector.destroy;
var
index: int;
&array: TObject_Array1d;
begin
if fldOwned then begin
&array := fldArray;
for index := fldLength - 1 downto 0 do begin
&array[index].free();
&array[index] := nil;
end;
end;
inherited destroy;
end;
procedure ObjectVector.clear();
var
index: int;
&array: TObject_Array1d;
begin
if fldOwned then begin
&array := fldArray;
for index := fldLength - 1 downto 0 do begin
&array[index].free();
&array[index] := nil;
end;
end;
fldLength := 0;
end;
procedure ObjectVector.append(const item: TObject);
begin
insert(CoInt.MAX_VALUE, item);
end;
procedure ObjectVector.insert(index: int; const item: TObject);
var
length: int;
__array: TObject_Array1d;
__buffer: TObject_Array1d;
begin
length := fldLength;
__array := fldArray;
if length = system.length(__array) then begin
if length = CoInt.MAX_VALUE then begin
raise BufferTooLargeError.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, '!error.buffer-too-large'));
end;
__buffer := &Array.newTObject1d((length shl 1) or 1);
&Array.copyObjects(__array, 0, __buffer, 0, length);
fldArray := __buffer;
__array := __buffer;
end;
if index < 0 then index := 0;
if index > length then index := length;
&Array.copyObjects(__array, index, __array, index + 1, length - index);
__array[index] := item;
fldLength := length + 1;
end;
function ObjectVector.getLength(): int;
begin
result := fldLength;
end;
function ObjectVector.readComponent(index: int): TObject;
begin
if (index < 0) or (index >= fldLength) then begin
raise ArrayIndexOutOfBoundsException.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'out-of-bounds.array-index'));
end;
result := fldArray[index];
end;
function ObjectVector.indexOf(const item: TObject): int;
var
index: int;
length: int;
__array: TObject_Array1d;
begin
length := fldLength;
if item = nil then begin
if length <= 0 then begin
result := -1;
exit;
end;
result := &Array.indexOf(nil, fldArray, 0, length);
exit;
end;
__array := fldArray;
for index := 0 to length - 1 do if item.equals(__array[index]) then begin
result := index;
exit;
end;
result := -1;
end;
function ObjectVector.clone(): TObject_Array1d;
var
length: int;
begin
length := fldLength;
result := &Array.newTObject1d(length);
&Array.copyObjects(fldArray, 0, result, 0, length);
end;
{%endregion}
{%region UnicodeStringArray }
constructor UnicodeStringArray.create();
begin
inherited create(&Array.newUnicodeString1d($0f));
fldLength := 0;
fldHashs := &Array.newLong1d($0f);
end;
procedure UnicodeStringArray.clear();
begin
&Array.fillStrings(fldArray, 0, fldLength, '');
fldLength := 0;
end;
procedure UnicodeStringArray.append(const item: AnsiString);
begin
append(item.toUTF16());
end;
procedure UnicodeStringArray.append(const item: UnicodeString);
var
capacity: int;
length: int;
shashs: long_Array1d;
bhashs: long_Array1d;
sarray: UnicodeString_Array1d;
barray: UnicodeString_Array1d;
begin
length := fldLength;
shashs := fldHashs;
sarray := fldArray;
if length = system.length(sarray) then begin
if length = CoInt.MAX_VALUE then begin
raise BufferTooLargeError.create(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, '!error.buffer-too-large'));
end;
capacity := (length shl 1) or 1;
bhashs := &Array.newLong1d(capacity);
barray := &Array.newUnicodeString1d(capacity);
&Array.copyPrimitives(shashs, 0, bhashs, 0, length);
&Array.copyStrings(sarray, 0, barray, 0, length);
fldHashs := bhashs;
fldArray := barray;
shashs := bhashs;
sarray := barray;
end;
shashs[length] := (CoUnicodeString.create(item) as RefCountInterface).getHashCode();
sarray[length] := item;
fldLength := length + 1;
end;
function UnicodeStringArray.contains(const item: AnsiString): boolean;
begin
result := contains(item.toUTF16());
end;
function UnicodeStringArray.contains(const item: UnicodeString): boolean;
var
length: int;
index: int;
hash: long;
__hashs: long_Array1d;
__array: UnicodeString_Array1d;
begin
length := fldLength;
if length <= 0 then begin
result := false;
exit;
end;
hash := (CoUnicodeString.create(item) as RefCountInterface).getHashCode();
__hashs := fldHashs;
__array := fldArray;
index := -1;
repeat
index := &Array.indexOf(hash, __hashs, index + 1, length - index - 1);
if index < 0 then break;
if item = __array[index] then begin
result := true;
exit;
end;
until false;
result := false;
end;
{%endregion}
{%region Lexer }
{%endregion}
{%region LanguageLexer }
class function LanguageLexer.parseName(lineIndex: int; const line: uchar_Array1d; charIndex: int; chr: uchar; sequence: LexemeSequence): int;
label
break_label0;
var
index: int;
length: int;
lastIndex: int;
parsed: UnicodeString;
lexeme: UnicodeString;
exception: TextSourceException;
begin
if ((chr < 'A') or (chr > 'Z')) and ((chr < 'a') or (chr > 'z')) and (chr <> '_') then begin
result := charIndex;
exit;
end;
lastIndex := charIndex + 1;
length := 1;
repeat
chr := line[lastIndex];
if ((chr < 'A') or (chr > 'Z')) and ((chr < 'a') or (chr > 'z')) and ((chr < '0') or (chr > '9')) and (chr <> '_') then break;
inc(length);
if length > LIMIT_NAME_LENGTH then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.name.too-long'));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
inc(lastIndex);
until false;
parsed := UnicodeString.create(line, charIndex, length);
begin
if length <= 12 then begin
index := KEYWORDS_LENGTH;
repeat
index := &Array.lastIndexOfNon(nil, lexemes, index - 1, 0);
if index < 0 then break;
lexeme := lexemes[index];
if (lexeme.length = length) and (lexeme = parsed) then case index of
EXP_TRUE, EXP_FALSE: begin
sequence.appendLexeme(lineIndex, charIndex, L_BOOLEAN, index <> EXP_FALSE);
goto break_label0;
end;
else
sequence.appendLexeme(lineIndex, charIndex, index, lexeme);
goto break_label0;
end;
until false;
end;
sequence.appendLexeme(lineIndex, charIndex, L_NAME, parsed);
end;
break_label0:
result := lastIndex;
end;
class function LanguageLexer.parseChar(lineIndex: int; const line: uchar_Array1d; charIndex: int; chr: uchar; sequence: LexemeSequence): int;
var
lastIndex: int;
code: int;
ic: int2;
exception: TextSourceException;
begin
if chr <> #$0027 then begin
result := charIndex;
exit;
end;
lastIndex := charIndex + 1;
ic := parseStringChar(line, lastIndex, line[lastIndex]);
code := ic[1];
lastIndex := ic[0];
if (code < 0) or (line[lastIndex] <> #$0027) then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.type'), [
CoAnsiString.create('char')
]));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
sequence.appendLexeme(lineIndex, charIndex, L_CHAR, uchar(code));
result := lastIndex + 1;
end;
class function LanguageLexer.parseString(lineIndex: int; const line: uchar_Array1d; charIndex: int; chr: uchar; sequence: LexemeSequence): int;
var
lastIndex: int;
capacity: int;
length: int;
code: int;
ic: int2;
parsed: uchar_Array1d;
buffer: uchar_Array1d;
exception: TextSourceException;
begin
if chr <> #$0022 then begin
result := charIndex;
exit;
end;
lastIndex := charIndex + 1;
length := 0;
capacity := $7f;
parsed := &Array.newUChar1d(capacity);
repeat
chr := line[lastIndex];
if chr = #$0022 then break;
ic := parseStringChar(line, lastIndex, chr);
code := ic[1];
lastIndex := ic[0];
if code < 0 then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.type'), [
CoAnsiString.create(PACKNAME_LANG + '.' + TYPENAME_STRING)
]));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
if length = capacity then begin
if length = ((CoShort.MAX_VALUE shl 1) or 1) then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.too-long'), [
CoAnsiString.create(PACKNAME_LANG + '.' + TYPENAME_STRING)
]));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
capacity := (capacity shl 1) or 1;
buffer := &Array.newUChar1d(capacity);
&Array.copyPrimitives(parsed, 0, buffer, 0, length);
parsed := buffer;
end;
parsed[length] := uchar(code);
inc(length);
until false;
sequence.appendLexeme(lineIndex, charIndex, L_STRING, UnicodeString.create(parsed, 0, length));
result := lastIndex + 1;
end;
class function LanguageLexer.parseNumeric(lineIndex: int; const line: uchar_Array1d; charIndex: int; chr: uchar; sequence: LexemeSequence): int;
label
break_label0,
break_label1,
continue_label2;
var
hasFractionPart: boolean;
hasOverflow: boolean;
hasOrder: boolean;
isNegative: boolean;
isRounded: boolean;
isSigned: boolean;
dgt: uchar;
lengthOfFractionPart: int;
lastIndex: int;
shift: int;
digit: int;
order: int;
index: int;
rawNumber: long;
bufNumber: long;
floatNumber: float;
doubleNumber: double;
realNumber: real;
exception: TextSourceException;
begin
if ((chr < '0') or (chr > '9')) and (chr <> '.') then begin
result := charIndex;
exit;
end;
hasOverflow := false;
lastIndex := charIndex + 1;
rawNumber := 0;
{ префикс системы счисления }
if chr = '0' then begin
begin
case line[lastIndex] of
'B', 'b': begin
chr := line[lastIndex + 1];
if (chr < '0') or (chr > '1') then begin
sequence.appendLexeme(lineIndex, charIndex, L_BYTE, byte(0));
result := lastIndex;
exit;
end;
if (chr = '1') and (line[lastIndex + 2] = '.') then begin
shift := 63;
inc(lastIndex, 3);
chr := line[lastIndex];
repeat
if (chr >= '0') and (chr <= '1') then begin
digit := int(chr) - int('0');
end else
if (chr = 'P') or (chr = 'p') then begin
goto break_label1;
end else begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.numeric'));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
if shift >= 0 then begin
rawNumber := rawNumber or (long(digit) shl shift);
dec(shift, 1);
end;
inc(lastIndex);
chr := line[lastIndex];
until false;
end;
inc(lastIndex);
repeat
if (chr >= '0') and (chr <= '1') then begin
digit := int(chr) - int('0');
end else begin
break;
end;
if rawNumber - UCMP >= BLIMIT - UCMP then begin
hasOverflow := true;
end else begin
rawNumber := (rawNumber shl 1) or digit;
end;
inc(lastIndex);
chr := line[lastIndex];
until false;
end;
'O', 'o': begin
chr := line[lastIndex + 1];
if (chr < '0') or (chr > '7') then begin
sequence.appendLexeme(lineIndex, charIndex, L_BYTE, byte(0));
result := lastIndex;
exit;
end;
if (chr = '1') and (line[lastIndex + 2] = '.') then begin
shift := 61;
inc(lastIndex, 3);
chr := line[lastIndex];
repeat
if (chr >= '0') and (chr <= '7') then begin
digit := int(chr) - int('0');
end else
if (chr = 'P') or (chr = 'p') then begin
goto break_label1;
end else begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.numeric'));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
if shift >= 0 then begin
rawNumber := rawNumber or (long(digit) shl shift);
dec(shift, 3);
end;
inc(lastIndex);
chr := line[lastIndex];
until false;
end;
inc(lastIndex);
repeat
if (chr >= '0') and (chr <= '7') then begin
digit := int(chr) - int('0');
end else begin
break;
end;
if rawNumber + UCMP >= OLIMIT + UCMP then begin
hasOverflow := true;
end else begin
rawNumber := (rawNumber shl 3) or digit;
end;
inc(lastIndex);
chr := line[lastIndex];
until false;
end;
'X', 'x': begin
chr := line[lastIndex + 1];
if ((chr < '0') or (chr > '9')) and ((chr < 'a') or (chr > 'f')) and ((chr < 'A') or (chr > 'F')) then begin
sequence.appendLexeme(lineIndex, charIndex, L_BYTE, byte(0));
result := lastIndex;
exit;
end;
if (chr = '1') and (line[lastIndex + 2] = '.') then begin
shift := 60;
inc(lastIndex, 3);
chr := line[lastIndex];
repeat
if (chr >= '0') and (chr <= '9') then begin
digit := int(chr) - int('0');
end else
if (chr >= 'a') and (chr <= 'f') then begin
digit := int(chr) - (int('a') - $0a);
end else
if (chr >= 'A') and (chr <= 'F') then begin
digit := int(chr) - (int('A') - $0a);
end else
if (chr = 'P') or (chr = 'p') then begin
goto break_label1;
end else begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.numeric'));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
if shift >= 0 then begin
rawNumber := rawNumber or (long(digit) shl shift);
dec(shift, 4);
end;
inc(lastIndex);
chr := line[lastIndex];
until false;
end;
inc(lastIndex);
repeat
if (chr >= '0') and (chr <= '9') then begin
digit := int(chr) - int('0');
end else
if (chr >= 'a') and (chr <= 'f') then begin
digit := int(chr) - (int('a') - $0a);
end else
if (chr >= 'A') and (chr <= 'F') then begin
digit := int(chr) - (int('A') - $0a);
end else begin
break;
end;
if rawNumber + UCMP >= XLIMIT + UCMP then begin
hasOverflow := true;
end else begin
rawNumber := (rawNumber shl 4) or digit;
end;
inc(lastIndex);
chr := line[lastIndex];
until false;
end;
else
goto break_label0;
end;
{ тип целого числа }
case chr of
'S', 's': begin
bufNumber := rawNumber;
rawNumber := int(rawNumber);
if (bufNumber + UCMP >= ILIMIT + UCMP) or (rawNumber < CoShort.MIN_VALUE) or (rawNumber > CoShort.MAX_VALUE) then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.type'), [
CoAnsiString.create('short')
]));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
inc(lastIndex);
sequence.appendLexeme(lineIndex, charIndex, L_SHORT, short(rawNumber));
end;
'I', 'i': begin
if rawNumber + UCMP >= ILIMIT + UCMP then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.type'), [
CoAnsiString.create('int')
]));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
inc(lastIndex);
sequence.appendLexeme(lineIndex, charIndex, L_INT, int(rawNumber));
end;
'L', 'l': begin
if hasOverflow then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.type'), [
CoAnsiString.create('long')
]));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
inc(lastIndex);
sequence.appendLexeme(lineIndex, charIndex, L_LONG, rawNumber);
end;
else
if rawNumber + UCMP >= ILIMIT + UCMP then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.type'), [
CoAnsiString.create('int')
]));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
rawNumber := int(rawNumber);
if (rawNumber >= CoByte.MIN_VALUE) and (rawNumber <= CoByte.MAX_VALUE) then begin
sequence.appendLexeme(lineIndex, charIndex, L_BYTE, byte(rawNumber));
end else
if (rawNumber >= CoShort.MIN_VALUE) and (rawNumber <= CoShort.MAX_VALUE) then begin
sequence.appendLexeme(lineIndex, charIndex, L_SHORT, short(rawNumber));
end else begin
sequence.appendLexeme(lineIndex, charIndex, L_INT, int(rawNumber));
end;
end;
result := lastIndex;
exit;
end;
break_label1:
{ порядок действительного числа }
order := 0;
begin
inc(lastIndex);
chr := line[lastIndex];
isNegative := chr = '-';
isSigned := isNegative or (chr = '+');
if isSigned or (chr >= '0') and (chr <= '9') then begin
if isSigned then begin
index := lastIndex + 1;
end else begin
index := lastIndex;
end;
dgt := line[index];
if (dgt >= '0') and (dgt <= '9') then begin
repeat
order := (order * 10) + (int(dgt) - int('0'));
if order > 99999 then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.numeric'));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
inc(index);
dgt := line[index];
until (dgt < '0') or (dgt > '9');
if isNegative then order := -order;
lastIndex := index;
chr := dgt;
end;
end;
end;
{ само действительное число }
realNumber := CoReal.build($3fff, (long(1) shl 63) or (rawNumber shr 1)) * pow2(order);
{ тип действительного числа }
case chr of
'F', 'f': begin
floatNumber := CoReal.toFloat(realNumber);
if CoFloat.isInfinite(floatNumber) then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.type'), [
CoAnsiString.create('float')
]));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
inc(lastIndex);
sequence.appendLexeme(lineIndex, charIndex, L_FLOAT, floatNumber);
end;
'D', 'd': begin
doubleNumber := CoReal.toDouble(realNumber);
if CoDouble.isInfinite(doubleNumber) then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.type'), [
CoAnsiString.create('double')
]));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
inc(lastIndex);
sequence.appendLexeme(lineIndex, charIndex, L_DOUBLE, doubleNumber);
end;
else
if (chr = 'R') or (chr = 'r') then inc(lastIndex);
if CoReal.isInfinite(realNumber) then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.type'), [
CoAnsiString.create('real')
]));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
sequence.appendLexeme(lineIndex, charIndex, L_REAL, realNumber);
end;
result := lastIndex;
exit;
end;
break_label0:
{ точка }
hasFractionPart := false;
lengthOfFractionPart := 0;
if chr = '.' then begin
chr := line[lastIndex];
if (chr < '0') or (chr > '9') then begin
sequence.appendLexeme(lineIndex, charIndex, PERIOD, lexemes[PERIOD]);
result := lastIndex;
exit;
end;
lengthOfFractionPart := 1;
hasFractionPart := true;
inc(lastIndex);
end;
{ мантисса числа }
isRounded := false;
rawNumber := int(chr) - int('0');
repeat
chr := line[lastIndex];
if chr = '.' then begin
if hasFractionPart then break;
hasFractionPart := true;
goto continue_label2;
end;
if (chr < '0') or (chr > '9') then break;
digit := int(chr) - int('0');
if (rawNumber + UCMP < DLIMIT + UCMP) or (rawNumber = DLIMIT) and (digit < 6) then begin
rawNumber := rawNumber * 10 + digit;
if hasFractionPart then inc(lengthOfFractionPart);
goto continue_label2;
end;
if hasFractionPart then begin
if not isRounded and (digit >= 5) and (rawNumber <> $ffffffffffffffff) then inc(rawNumber);
isRounded := true;
goto continue_label2;
end;
hasOverflow := true;
dec(lengthOfFractionPart);
continue_label2:
inc(lastIndex);
until false;
{ порядок числа }
hasOrder := false;
order := 0;
if (chr = 'E') or (chr = 'e') then begin
isNegative := false;
index := lastIndex + 1;
dgt := line[index];
case dgt of
'-': begin
isNegative := true;
inc(index);
dgt := line[index];
end;
'+': begin
inc(index);
dgt := line[index];
end;
end;
if (dgt >= '0') and (dgt <= '9') then begin
repeat
order := (order * 10) + (int(dgt) - int('0'));
if order > 9999 then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.numeric'));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
inc(index);
dgt := line[index];
until (dgt < '0') or (dgt > '9');
if isNegative then order := -order;
hasOrder := true;
lastIndex := index;
chr := dgt;
end;
end;
{ само число }
if (hasFractionPart or hasOrder) and (rawNumber <> 0) then while CoLong.remUnsigned(rawNumber, 10) = 0 do begin
dec(lengthOfFractionPart);
rawNumber := CoLong.divUnsigned(rawNumber, 10);
end;
realNumber := RealRepresenter.pow10(real(rawNumber + UCMP) - real(UCMP), order - lengthOfFractionPart);
{ тип числа }
case chr of
'S', 's': begin
if hasFractionPart or hasOrder or hasOverflow or (rawNumber + UCMP > CoShort.MAX_VALUE + UCMP) then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.type'), [
CoAnsiString.create('short')
]));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
inc(lastIndex);
sequence.appendLexeme(lineIndex, charIndex, L_SHORT, short(rawNumber));
end;
'I', 'i': begin
if hasFractionPart or hasOrder or hasOverflow or (rawNumber + UCMP > CoInt.MAX_VALUE + UCMP) then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.type'), [
CoAnsiString.create('int')
]));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
inc(lastIndex);
sequence.appendLexeme(lineIndex, charIndex, L_INT, int(rawNumber));
end;
'L', 'l': begin
if hasFractionPart or hasOrder or hasOverflow or (rawNumber + UCMP > CoLong.MAX_VALUE + UCMP) then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.type'), [
CoAnsiString.create('long')
]));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
inc(lastIndex);
sequence.appendLexeme(lineIndex, charIndex, L_LONG, rawNumber);
end;
'F', 'f': begin
floatNumber := CoReal.toFloat(realNumber);
if CoFloat.isInfinite(floatNumber) then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.type'), [
CoAnsiString.create('float')
]));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
inc(lastIndex);
sequence.appendLexeme(lineIndex, charIndex, L_FLOAT, floatNumber);
end;
'D', 'd': begin
doubleNumber := CoReal.toDouble(realNumber);
if CoDouble.isInfinite(doubleNumber) then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.type'), [
CoAnsiString.create('double')
]));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
inc(lastIndex);
sequence.appendLexeme(lineIndex, charIndex, L_DOUBLE, doubleNumber);
end;
'R', 'r': begin
if CoReal.isInfinite(realNumber) then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.type'), [
CoAnsiString.create('real')
]));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
inc(lastIndex);
sequence.appendLexeme(lineIndex, charIndex, L_REAL, realNumber);
end;
else
if hasFractionPart or hasOrder then begin
if CoReal.isInfinite(realNumber) then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.type'), [
CoAnsiString.create('real')
]));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
sequence.appendLexeme(lineIndex, charIndex, L_REAL, realNumber);
end else
if rawNumber + UCMP > CoInt.MAX_VALUE + UCMP then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.literal.type'), [
CoAnsiString.create('int')
]));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end else
if rawNumber <= CoByte.MAX_VALUE then begin
sequence.appendLexeme(lineIndex, charIndex, L_BYTE, byte(rawNumber));
end else
if rawNumber <= CoShort.MAX_VALUE then begin
sequence.appendLexeme(lineIndex, charIndex, L_SHORT, short(rawNumber));
end else begin
sequence.appendLexeme(lineIndex, charIndex, L_INT, int(rawNumber));
end;
end;
result := lastIndex;
end;
class function LanguageLexer.parseOperator(lineIndex: int; const line: uchar_Array1d; charIndex: int; chr: uchar; sequence: LexemeSequence): int;
label
break_label0;
var
lastIndex: int;
length: int;
index: int;
parsed: UnicodeString;
lexeme: UnicodeString;
exception: TextSourceException;
begin
if &Array.indexOf(chr, symbols, 0, 0) < 0 then begin
result := charIndex;
exit;
end;
lastIndex := charIndex + 1;
length := 1;
chr := line[lastIndex];
while (length < 6) and (&Array.indexOf(chr, symbols, 0, 0) >= 0) do begin
inc(lastIndex);
chr := line[lastIndex];
inc(length);
end;
while length > 0 do begin
parsed := UnicodeString.create(line, charIndex, length);
index := LEXEMES_LENGTH;
repeat
index := &Array.lastIndexOfNon(nil, lexemes, index - 1, 0);
if index < KEYWORDS_LENGTH then break;
lexeme := lexemes[index];
if (lexeme.length = length) and (lexeme = parsed) then begin
sequence.appendLexeme(lineIndex, charIndex, index, lexeme);
goto break_label0;
end;
until false;
dec(lastIndex);
if lastIndex = charIndex then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.operator'));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
dec(length);
end;
break_label0:
result := lastIndex;
end;
class function LanguageLexer.parseStringChar(const line: uchar_Array1d; charIndex: int; chr: uchar): int2;
var
lastIndex: int;
digit: int;
code: int;
cci: int;
begin
case chr of
'\': ;
#$0000, '"', '''': begin
result := Vector.newInt2(charIndex, -1);
exit;
end;
else
result := Vector.newInt2(charIndex + 1, int(chr));
exit;
end;
lastIndex := charIndex + 1;
case line[lastIndex] of
'u': begin
inc(lastIndex);
end;
'0': begin
result := Vector.newInt2(lastIndex + 1, $0000);
exit;
end;
'b': begin
result := Vector.newInt2(lastIndex + 1, $0008);
exit;
end;
't': begin
result := Vector.newInt2(lastIndex + 1, $0009);
exit;
end;
'n': begin
result := Vector.newInt2(lastIndex + 1, $000a);
exit;
end;
'f': begin
result := Vector.newInt2(lastIndex + 1, $000c);
exit;
end;
'r': begin
result := Vector.newInt2(lastIndex + 1, $000d);
exit;
end;
'"': begin
result := Vector.newInt2(lastIndex + 1, $0022);
exit;
end;
'''': begin
result := Vector.newInt2(lastIndex + 1, $0027);
exit;
end;
'\': begin
result := Vector.newInt2(lastIndex + 1, $005c);
exit;
end;
else
result := Vector.newInt2(charIndex, -1);
exit;
end;
code := 0;
for cci := 3 downto 0 do begin
chr := line[lastIndex];
inc(lastIndex);
if (chr >= '0') and (chr <= '9') then begin
digit := int(chr) - int('0');
end else
if (chr >= 'a') and (chr <= 'f') then begin
digit := int(chr) - (int('a') - $0a);
end else
if (chr >= 'A') and (chr <= 'F') then begin
digit := int(chr) - (int('A') - $0a);
end else begin
result := Vector.newInt2(charIndex, -1);
exit;
end;
code := (code shl 4) or digit;
end;
result := Vector.newInt2(lastIndex, code);
end;
class function LanguageLexer.pow2(power: int): real;
begin
inc(power, $3fff);
if power < -62 then begin
result := 0;
exit;
end;
if power < $0001 then begin
result := CoReal.build($0000, long(1) shl (power + 62));
exit;
end;
if power < $7fff then begin
result := CoReal.build(power, long(1) shl 63);
exit;
end;
result := CoReal.POSITIVE_INFINITY;
end;
class procedure LanguageLexer.initialize();
begin
symbols := UnicodeString('.,:;`?=()[]{}<>!~&^|+-*/%#@').toUCharArray();
lexemes := &Array.newUnicodeString1d(LEXEMES_LENGTH);
lexemes[VIS_PRIVATE ] := 'private';
lexemes[VIS_PACKAGE ] := 'package';
lexemes[VIS_PROTECTED ] := 'protected';
lexemes[VIS_PUBLIC ] := 'public';
lexemes[VIS_PUBLISHED ] := 'published';
lexemes[DCL_IMPORT ] := 'import';
lexemes[DCL_UNION ] := 'union';
lexemes[DCL_ABSTRACT ] := 'abstract';
lexemes[DCL_FINAL ] := 'final';
lexemes[DCL_CLASS ] := 'class';
lexemes[DCL_STRUCT ] := 'struct';
lexemes[DCL_SERVICE ] := 'service';
lexemes[DCL_INTERFACE ] := 'interface';
lexemes[DCL_HELPER ] := 'helper';
lexemes[DCL_STATIC ] := 'static';
lexemes[DCL_NATIVE ] := 'native';
lexemes[DCL_INTERRUPT ] := 'interrupt';
lexemes[DCL_SYNCHRONIZED] := 'synchronized';
lexemes[DCL_OPERATOR ] := 'operator';
lexemes[DCL_THROWS ] := 'throws';
lexemes[EXP_FALSE ] := 'false';
lexemes[EXP_TRUE ] := 'true';
lexemes[EXP_NULL ] := 'null';
lexemes[EXP_NEW ] := 'new';
lexemes[EXP_SUPER ] := 'super';
lexemes[EXP_THIS ] := 'this';
lexemes[EXP_INSTANCEOF ] := 'instanceof';
lexemes[TYP_VOID ] := 'void';
lexemes[TYP_BOOLEAN ] := 'boolean';
lexemes[TYP_CHAR ] := 'char';
lexemes[TYP_REAL ] := 'real';
lexemes[TYP_DOUBLE ] := 'double';
lexemes[TYP_DOUBLE2 ] := 'double2';
lexemes[TYP_DOUBLE4 ] := 'double4';
lexemes[TYP_DOUBLE8 ] := 'double8';
lexemes[TYP_FLOAT ] := 'float';
lexemes[TYP_FLOAT2 ] := 'float2';
lexemes[TYP_FLOAT4 ] := 'float4';
lexemes[TYP_FLOAT8 ] := 'float8';
lexemes[TYP_BYTE ] := 'byte';
lexemes[TYP_BYTE2 ] := 'byte2';
lexemes[TYP_BYTE4 ] := 'byte4';
lexemes[TYP_BYTE8 ] := 'byte8';
lexemes[TYP_SHORT ] := 'short';
lexemes[TYP_SHORT2 ] := 'short2';
lexemes[TYP_SHORT4 ] := 'short4';
lexemes[TYP_SHORT8 ] := 'short8';
lexemes[TYP_INT ] := 'int';
lexemes[TYP_INT2 ] := 'int2';
lexemes[TYP_INT4 ] := 'int4';
lexemes[TYP_INT8 ] := 'int8';
lexemes[TYP_LONG ] := 'long';
lexemes[TYP_LONG2 ] := 'long2';
lexemes[TYP_LONG4 ] := 'long4';
lexemes[TYP_LONG8 ] := 'long8';
lexemes[FCT_WITH ] := 'with';
lexemes[FCT_IF ] := 'if';
lexemes[FCT_ELSE ] := 'else';
lexemes[FCT_SWITCH ] := 'switch';
lexemes[FCT_CASE ] := 'case';
lexemes[FCT_DEFAULT ] := 'default';
lexemes[FCT_DO ] := 'do';
lexemes[FCT_FOR ] := 'for';
lexemes[FCT_WHILE ] := 'while';
lexemes[FCT_BREAK ] := 'break';
lexemes[FCT_CONTINUE ] := 'continue';
lexemes[FCT_RETURN ] := 'return';
lexemes[FCT_THROW ] := 'throw';
lexemes[FCT_TRY ] := 'try';
lexemes[FCT_CATCH ] := 'catch';
lexemes[FCT_FINALLY ] := 'finally';
lexemes[INC_LOCAL ] := '++';
lexemes[DEC_LOCAL ] := '--';
lexemes[BOOL_NOT ] := '!';
lexemes[BOOL_AND ] := '&&';
lexemes[BOOL_OR ] := '||';
lexemes[O_BIT_NOT ] := '~';
lexemes[O_BIT_AND ] := '&';
lexemes[O_BIT_OR ] := '|';
lexemes[O_BIT_XOR ] := '^';
lexemes[O_SCAL_MUL ] := '*';
lexemes[O_SCAL_DIV ] := '/';
lexemes[O_SCAL_DIVU ] := '//';
lexemes[O_SCAL_REM ] := '%';
lexemes[O_SCAL_REMU ] := '%%';
lexemes[O_SCAL_ADD ] := '+';
lexemes[O_SCAL_SUB ] := '-';
lexemes[O_SCAL_SHR ] := '>>';
lexemes[O_SCAL_SHRU ] := '>>>';
lexemes[O_SCAL_SHL ] := '<<';
lexemes[O_SCAL_GT ] := '>';
lexemes[O_SCAL_GE ] := '>=';
lexemes[O_SCAL_LT ] := '<';
lexemes[O_SCAL_LE ] := '<=';
lexemes[O_SCAL_EQ ] := '==';
lexemes[O_SCAL_NE ] := '!=';
lexemes[O_VECT_LUP ] := '####';
lexemes[O_VECT_UUP ] := '^^^^';
lexemes[O_VECT_PCK ] := '@@@@';
lexemes[O_VECT_MUL ] := '****';
lexemes[O_VECT_DIV ] := '////';
lexemes[O_VECT_ADD ] := '++++';
lexemes[O_VECT_SUB ] := '----';
lexemes[O_VECT_SHR ] := '>>>>';
lexemes[O_VECT_SHRU ] := '>>>>>';
lexemes[O_VECT_SHL ] := '<<<<';
lexemes[O_VECT_GT ] := '|>>|';
lexemes[O_VECT_GE ] := '|>=|';
lexemes[O_VECT_LT ] := '|<<|';
lexemes[O_VECT_LE ] := '|<=|';
lexemes[O_VECT_EQ ] := '|==|';
lexemes[O_VECT_NE ] := '|!=|';
lexemes[O_VECT_HMUL ] := '|**|';
lexemes[O_VECT_HMULU ] := '#**#';
lexemes[O_VECT_SADD ] := '|++|';
lexemes[O_VECT_SADDU ] := '#++#';
lexemes[O_VECT_SSUB ] := '|--|';
lexemes[O_VECT_SSUBU ] := '#--#';
lexemes[A_BIT_AND ] := '&=';
lexemes[A_BIT_OR ] := '|=';
lexemes[A_BIT_XOR ] := '^=';
lexemes[A_SCAL_MUL ] := '*=';
lexemes[A_SCAL_DIV ] := '/=';
lexemes[A_SCAL_DIVU ] := '//=';
lexemes[A_SCAL_REM ] := '%=';
lexemes[A_SCAL_REMU ] := '%%=';
lexemes[A_SCAL_ADD ] := '+=';
lexemes[A_SCAL_SUB ] := '-=';
lexemes[A_SCAL_SHR ] := '>>=';
lexemes[A_SCAL_SHRU ] := '>>>=';
lexemes[A_SCAL_SHL ] := '<<=';
lexemes[A_VECT_MUL ] := '****=';
lexemes[A_VECT_DIV ] := '////=';
lexemes[A_VECT_ADD ] := '++++=';
lexemes[A_VECT_SUB ] := '----=';
lexemes[A_VECT_SHR ] := '>>>>=';
lexemes[A_VECT_SHRU ] := '>>>>>=';
lexemes[A_VECT_SHL ] := '<<<<=';
lexemes[A_VECT_GT ] := '|>>|=';
lexemes[A_VECT_GE ] := '|>=|=';
lexemes[A_VECT_LT ] := '|<<|=';
lexemes[A_VECT_LE ] := '|<=|=';
lexemes[A_VECT_EQ ] := '|==|=';
lexemes[A_VECT_NE ] := '|!=|=';
lexemes[A_VECT_HMUL ] := '|**|=';
lexemes[A_VECT_HMULU ] := '#**#=';
lexemes[A_VECT_SADD ] := '|++|=';
lexemes[A_VECT_SADDU ] := '#++#=';
lexemes[A_VECT_SSUB ] := '|--|=';
lexemes[A_VECT_SSUBU ] := '#--#=';
lexemes[PARENTH_OPENED ] := '(';
lexemes[PARENTH_CLOSED ] := ')';
lexemes[BRACKET_OPENED ] := '[';
lexemes[BRACKET_CLOSED ] := ']';
lexemes[CURLY_OPENED ] := '{';
lexemes[CURLY_CLOSED ] := '}';
lexemes[EQUAL ] := '=';
lexemes[QUESTION ] := '?';
lexemes[REVERSE ] := '`';
lexemes[PERIOD ] := '.';
lexemes[COMMA ] := ',';
lexemes[COLON ] := ':';
lexemes[SEMICOLON ] := ';';
defaultDocumentationLexer := DocumentLexer.create();
defaultDocumentationLexer.lineEndingEnabled := true;
end;
class procedure LanguageLexer.finalize();
begin
defaultDocumentationLexer.free();
end;
function LanguageLexer.parseComment(const text: uchar_Array2d; lineIndexBegin, lineIndexEnd: int; last, line: uchar_Array1d; charIndexBegin: int; chr: uchar; sequence: LexemeSequence): int2;
label
break_label0;
var
isDocumentation: boolean;
charIndexContent: int;
lineIndexResult: int;
charIndexResult: int;
charIndexEnd: int;
lexer: DocumentLexer;
documentation: LexemeSequence;
begin
if (chr <> '/') or (line[charIndexBegin + 1] <> '*') then begin
result := Vector.newInt2(lineIndexBegin, charIndexBegin);
exit;
end;
charIndexContent := charIndexBegin + 2;
lineIndexResult := lineIndexBegin;
charIndexResult := charIndexContent;
isDocumentation := (line[charIndexResult] = '*') and (line[charIndexResult + 1] <> '/');
while lineIndexResult <= lineIndexEnd do begin
repeat
charIndexEnd := &Array.indexOf('*', line, charIndexResult, 0);
if charIndexEnd < 0 then begin
if lineIndexResult < lineIndexEnd then break;
charIndexResult := system.length(line) - 1;
goto break_label0;
end;
if line[charIndexEnd + 1] = '/' then begin
charIndexResult := charIndexEnd;
goto break_label0;
end;
charIndexResult := charIndexEnd + 1;
until false;
charIndexResult := 0;
inc(lineIndexResult);
if lineIndexResult >= lineIndexEnd then begin
line := last;
end else begin
line := text[lineIndexResult];
end;
end;
break_label0:
if isDocumentation and fldDocumentationEnabled then begin
lexer := fldDocumentationLexer;
if lexer = nil then lexer := defaultDocumentationLexer;
documentation := newDocumentLexemeSequence();
if documentation = nil then documentation := LexemeSequence.create();
lexer.split(text, Vector.newInt2(lineIndexBegin, charIndexContent), Vector.newInt2(lineIndexResult, charIndexResult), documentation);
sequence.appendLexeme(lineIndexBegin, charIndexBegin, L_DOC, documentation);
end;
if line[charIndexResult] = '*' then inc(charIndexResult, 2);
result := Vector.newInt2(lineIndexResult, charIndexResult);
end;
procedure LanguageLexer.setDocumentationEnabled(newDocumentationEnabled: boolean);
begin
fldDocumentationEnabled := newDocumentationEnabled;
end;
procedure LanguageLexer.setDocumentationLexer(newDocumentationLexer: DocumentLexer);
begin
fldDocumentationLexer := newDocumentationLexer;
end;
function LanguageLexer.newDocumentLexemeSequence(): LexemeSequence;
begin
result := nil;
end;
constructor LanguageLexer.create();
begin
inherited create();
end;
constructor LanguageLexer.create(__documentationLexer: DocumentLexer);
begin
inherited create();
fldDocumentationLexer := __documentationLexer;
end;
procedure LanguageLexer.split(const text: uchar_Array2d; const locationBegin, locationEnd: int2; sequence: LexemeSequence);
label
break_label0;
var
chr: uchar;
lineIndexBegin: int;
charIndexBegin: int;
lineIndexEnd: int;
charIndexEnd: int;
lineIndex: int;
charIndex: int;
bufIndex: int;
limit: int;
count: int;
location: int2;
last: uchar_Array1d;
line: uchar_Array1d;
buffer: uchar_Array1d;
exception: TextSourceException;
begin
if sequence = nil then begin
raise NullPointerException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'null-pointer.argument'), [ CoAnsiString.create('sequence') ]));
end;
limit := system.length(text);
if limit <= 0 then begin
sequence.appendLexeme(0, 0, L_END);
exit;
end;
dec(limit);
lineIndexBegin := locationBegin[0];
charIndexBegin := locationBegin[1];
lineIndexEnd := locationEnd[0];
charIndexEnd := locationEnd[1];
count := system.length(text[limit]) - 1;
if lineIndexBegin < 0 then begin
lineIndexBegin := 0;
charIndexBegin := 0;
end;
if lineIndexBegin > limit then begin
lineIndexBegin := limit;
charIndexBegin := count;
end;
if lineIndexEnd < 0 then begin
lineIndexEnd := 0;
charIndexEnd := 0;
end;
if lineIndexEnd > limit then begin
lineIndexEnd := limit;
charIndexEnd := count;
end;
if charIndexBegin < 0 then begin
charIndexBegin := 0;
end;
count := system.length(text[lineIndexBegin]) - 1;
if charIndexBegin > count then begin
charIndexBegin := count;
end;
if charIndexEnd < 0 then begin
charIndexEnd := 0;
end;
count := system.length(text[lineIndexEnd]) - 1;
if charIndexEnd > count then begin
charIndexEnd := count;
end;
last := text[lineIndexEnd];
if charIndexEnd < system.length(last) - 1 then begin
buffer := &Array.newUChar1d(charIndexEnd + 1);
&Array.copyPrimitives(last, 0, buffer, 0, charIndexEnd);
last := buffer;
end;
lineIndex := lineIndexBegin;
while lineIndex <= lineIndexEnd do begin
if lineIndex <= lineIndexBegin then begin
charIndex := charIndexBegin;
end else begin
charIndex := 0;
end;
if lineIndex >= lineIndexEnd then begin
line := last;
end else begin
line := text[lineIndex];
end;
chr := line[charIndex];
while chr > #$0000 do begin
while chr <= #$0020 do begin
inc(charIndex);
chr := line[charIndex];
if chr <= #$0000 then goto break_label0;
end;
location := parseComment(text, lineIndex, lineIndexEnd, last, line, charIndex, chr, sequence);
if Vector.lt(Vector.newInt2(lineIndex, charIndex), location) <> 0 then begin
lineIndex := location[0];
charIndex := location[1];
if lineIndex >= lineIndexEnd then begin
line := last;
end else begin
line := text[lineIndex];
end;
chr := line[charIndex];
continue;
end;
bufIndex := charIndex;
charIndex := parseName(lineIndex, line, charIndex, chr, sequence);
if bufIndex < charIndex then begin
chr := line[charIndex];
continue;
end;
bufIndex := charIndex;
charIndex := parseChar(lineIndex, line, charIndex, chr, sequence);
if bufIndex < charIndex then begin
chr := line[charIndex];
continue;
end;
bufIndex := charIndex;
charIndex := parseString(lineIndex, line, charIndex, chr, sequence);
if bufIndex < charIndex then begin
chr := line[charIndex];
continue;
end;
bufIndex := charIndex;
charIndex := parseNumeric(lineIndex, line, charIndex, chr, sequence);
if bufIndex < charIndex then begin
chr := line[charIndex];
continue;
end;
bufIndex := charIndex;
charIndex := parseOperator(lineIndex, line, charIndex, chr, sequence);
if bufIndex < charIndex then begin
chr := line[charIndex];
continue;
end;
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'lexer.character'));
if sequence is TextSource then exception.source := TextSource(sequence);
exception.lineIndex := lineIndex;
exception.charIndex := charIndex;
raise exception;
end;
break_label0:
inc(lineIndex);
end;
sequence.appendLexeme(lineIndexEnd, charIndexEnd, L_END);
end;
{%endregion}
{%region DocumentLexer }
class function DocumentLexer.parseChar(lineIndex: int; const line: uchar_Array1d; charIndex: int; chr: uchar; sequence: LexemeSequence): int;
label
break_label0;
var
lastIndex: int;
length: int;
index: int;
parsed: UnicodeString;
lexeme: UnicodeString;
begin
if &Array.indexOf(chr, symbols, 0, 0) < 0 then begin
result := charIndex;
exit;
end;
lastIndex := charIndex + 1;
length := 1;
chr := line[lastIndex];
while (length < 7) and ((&Array.indexOf(chr, symbols, 0, 0) >= 0) or (chr >= 'a') and (chr <= 'z')) do begin
inc(lastIndex);
chr := line[lastIndex];
inc(length);
end;
while length > 0 do begin
parsed := UnicodeString.create(line, charIndex, length);
index := D_LEXEMES_LENGTH;
repeat
index := &Array.lastIndexOfNon(nil, lexemes, index - 1, 0);
if index < 0 then break;
lexeme := lexemes[index];
if (lexeme.length = length) and (lexeme = parsed) then begin
sequence.appendLexeme(lineIndex, charIndex, index, lexeme);
goto break_label0;
end;
until false;
dec(lastIndex);
dec(length);
end;
break_label0:
result := lastIndex;
end;
class function DocumentLexer.parseName(lineIndex: int; const line: uchar_Array1d; charIndex: int; chr: uchar; sequence: LexemeSequence): int;
var
lastIndex: int;
begin
if ((chr < 'A') or (chr > 'Z')) and ((chr < 'a') or (chr > 'z')) and (chr <> '_') then begin
result := charIndex;
exit;
end;
lastIndex := charIndex + 1;
repeat
chr := line[lastIndex];
if ((chr < 'A') or (chr > 'Z')) and ((chr < 'a') or (chr > 'z')) and ((chr < '0') or (chr > '9')) and (chr <> '_') then break;
inc(lastIndex);
until false;
sequence.appendLexeme(lineIndex, charIndex, D_NAME, UnicodeString.create(line, charIndex, lastIndex - charIndex));
result := lastIndex;
end;
class function DocumentLexer.parseText(lineIndex: int; const line: uchar_Array1d; charIndex: int; chr: uchar; sequence: LexemeSequence): int;
var
lastIndex: int;
begin
if chr <= #$0000 then begin
result := charIndex;
exit;
end;
lastIndex := charIndex + 1;
repeat
chr := line[lastIndex];
if (chr <= #$0020) or (&Array.indexOf(chr, symbols, 0, 0) >= 0) or (chr >= 'A') and (chr <= 'Z') or (chr >= 'a') and (chr <= 'z') or (chr = '_') then break;
inc(lastIndex);
until false;
sequence.appendLexeme(lineIndex, charIndex, D_TEXT, UnicodeString.create(line, charIndex, lastIndex - charIndex));
result := lastIndex;
end;
class procedure DocumentLexer.initialize();
begin
symbols := UnicodeString('.,`"=()[]{}<>!~&^|+-*/%#@').toUCharArray();
lexemes := &Array.newUnicodeString1d(D_LEXEMES_LENGTH);
lexemes[D_ALINK ] := '@link';
lexemes[D_APARAM ] := '@param';
lexemes[D_ARETURN ] := '@return';
lexemes[D_ATHROWS ] := '@throws';
lexemes[D_ASINCE ] := '@since';
lexemes[D_ASEE ] := '@see';
lexemes[D_SCAL_DIVU ] := '//';
lexemes[D_SCAL_REMU ] := '%%';
lexemes[D_SCAL_SHR ] := '>>';
lexemes[D_SCAL_SHRU ] := '>>>';
lexemes[D_SCAL_SHL ] := '<<';
lexemes[D_SCAL_GE ] := '>=';
lexemes[D_SCAL_LE ] := '<=';
lexemes[D_SCAL_EQ ] := '==';
lexemes[D_SCAL_NE ] := '!=';
lexemes[D_VECT_LUP ] := '####';
lexemes[D_VECT_UUP ] := '^^^^';
lexemes[D_VECT_PCK ] := '@@@@';
lexemes[D_VECT_MUL ] := '****';
lexemes[D_VECT_DIV ] := '////';
lexemes[D_VECT_ADD ] := '++++';
lexemes[D_VECT_SUB ] := '----';
lexemes[D_VECT_SHR ] := '>>>>';
lexemes[D_VECT_SHRU ] := '>>>>>';
lexemes[D_VECT_SHL ] := '<<<<';
lexemes[D_VECT_GT ] := '|>>|';
lexemes[D_VECT_GE ] := '|>=|';
lexemes[D_VECT_LT ] := '|<<|';
lexemes[D_VECT_LE ] := '|<=|';
lexemes[D_VECT_EQ ] := '|==|';
lexemes[D_VECT_NE ] := '|!=|';
lexemes[D_VECT_HMUL ] := '|**|';
lexemes[D_VECT_HMULU ] := '#**#';
lexemes[D_VECT_SADD ] := '|++|';
lexemes[D_VECT_SADDU ] := '#++#';
lexemes[D_VECT_SSUB ] := '|--|';
lexemes[D_VECT_SSUBU ] := '#--#';
lexemes[D_PARENTH_OPENED] := '(';
lexemes[D_PARENTH_CLOSED] := ')';
lexemes[D_BRACKET_OPENED] := '[';
lexemes[D_BRACKET_CLOSED] := ']';
lexemes[D_CURLY_OPENED ] := '{';
lexemes[D_CURLY_CLOSED ] := '}';
lexemes[D_TAG_OPENED ] := '<';
lexemes[D_TAG_CLOSED ] := '>';
lexemes[D_EQUAL ] := '=';
lexemes[D_GRAVE_ACCENT ] := '`';
lexemes[D_PERIOD ] := '.';
lexemes[D_COMMA ] := ',';
lexemes[D_QUOTE ] := '"';
lexemes[D_EXCLAM_MARK ] := '!';
lexemes[D_VERTICAL_LINE ] := '|';
lexemes[D_AMPERSAND ] := '&';
lexemes[D_TILDE ] := '~';
lexemes[D_POUND_SIGN ] := '#';
lexemes[D_CIRCUMFLEX_ACC] := '^';
lexemes[D_ASTERISK ] := '*';
lexemes[D_SOLIDUS ] := '/';
lexemes[D_PERCENT ] := '%';
lexemes[D_PLUS ] := '+';
lexemes[D_MINUS ] := '-';
lexemes[D_AT ] := '@';
end;
procedure DocumentLexer.setLineEndingEnabled(newLineEndingEnabled: boolean);
begin
fldLineEndingEnabled := newLineEndingEnabled;
end;
constructor DocumentLexer.create();
begin
inherited create();
fldLineEndingEnabled := true;
end;
procedure DocumentLexer.split(const text: uchar_Array2d; const locationBegin, locationEnd: int2; sequence: LexemeSequence);
var
isLineEnding: boolean;
isLineEmpty: boolean;
chr: uchar;
lineIndexBegin: int;
charIndexBegin: int;
lineIndexEnd: int;
charIndexEnd: int;
lineIndex: int;
charIndex: int;
bufIndex: int;
limit: int;
count: int;
last: uchar_Array1d;
line: uchar_Array1d;
buffer: uchar_Array1d;
begin
if sequence = nil then begin
raise NullPointerException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'null-pointer.argument'), [ CoAnsiString.create('sequence') ]));
end;
limit := system.length(text);
if limit <= 0 then begin
sequence.appendLexeme(0, 0, D_END);
exit;
end;
dec(limit);
lineIndexBegin := locationBegin[0];
charIndexBegin := locationBegin[1];
lineIndexEnd := locationEnd[0];
charIndexEnd := locationEnd[1];
count := system.length(text[limit]) - 1;
if lineIndexBegin < 0 then begin
lineIndexBegin := 0;
charIndexBegin := 0;
end;
if lineIndexBegin > limit then begin
lineIndexBegin := limit;
charIndexBegin := count;
end;
if lineIndexEnd < 0 then begin
lineIndexEnd := 0;
charIndexEnd := 0;
end;
if lineIndexEnd > limit then begin
lineIndexEnd := limit;
charIndexEnd := count;
end;
if charIndexBegin < 0 then begin
charIndexBegin := 0;
end;
count := system.length(text[lineIndexBegin]) - 1;
if charIndexBegin > count then begin
charIndexBegin := count;
end;
if charIndexEnd < 0 then begin
charIndexEnd := 0;
end;
count := system.length(text[lineIndexEnd]) - 1;
if charIndexEnd > count then begin
charIndexEnd := count;
end;
last := text[lineIndexEnd];
if charIndexEnd < system.length(last) - 1 then begin
buffer := &Array.newUChar1d(charIndexEnd + 1);
&Array.copyPrimitives(last, 0, buffer, 0, charIndexEnd);
last := buffer;
end;
isLineEnding := fldLineEndingEnabled;
lineIndex := lineIndexBegin;
while lineIndex <= lineIndexEnd do begin
if lineIndex <= lineIndexBegin then begin
charIndex := charIndexBegin;
end else begin
charIndex := 0;
end;
if lineIndex >= lineIndexEnd then begin
line := last;
end else begin
line := text[lineIndex];
end;
repeat
chr := line[charIndex];
if (chr <= #$0000) or (chr > #$0020) then break;
inc(charIndex);
until false;
if chr = '*' then begin
inc(charIndex);
chr := line[charIndex];
end;
isLineEmpty := true;
while chr > #$0000 do begin
if chr <= #$0020 then repeat
inc(charIndex);
chr := line[charIndex];
until (chr <= #$0000) or (chr > #$0020);
bufIndex := charIndex;
charIndex := parseChar(lineIndex, line, charIndex, chr, sequence);
if bufIndex < charIndex then begin
chr := line[charIndex];
isLineEmpty := false;
continue;
end;
bufIndex := charIndex;
charIndex := parseName(lineIndex, line, charIndex, chr, sequence);
if bufIndex < charIndex then begin
chr := line[charIndex];
isLineEmpty := false;
continue;
end;
bufIndex := charIndex;
charIndex := parseText(lineIndex, line, charIndex, chr, sequence);
if bufIndex < charIndex then begin
chr := line[charIndex];
isLineEmpty := false;
end;
end;
if isLineEmpty then begin
sequence.appendLexeme(lineIndex, charIndex, D_EOP);
end else
if isLineEnding then begin
sequence.appendLexeme(lineIndex, charIndex, D_EOL);
end;
inc(lineIndex);
end;
sequence.appendLexeme(lineIndexEnd, charIndexEnd, D_END);
end;
{%%endregion}
{%region RecompilableElement }
constructor RecompilableElement.create(__programme: Programme);
begin
inherited create();
fldProgramme := __programme;
end;
{%endregion}
{%region PackageElement }
constructor PackageElement.create(__programme: Programme; __recompilableName: int);
begin
inherited create(__programme);
fldRecompilableName := __recompilableName;
end;
function PackageElement.getItem(): Package;
var
name: AnsiString;
__package: Package;
begin
__package := fldPackage;
if __package = nil then begin
name := (fldConstants[fldRecompilableName] as CoUnicodeString).asAnsiString();
__package := fldProgramme.getPackage(name);
fldPackage := __package;
end;
result := __package;
end;
{%endregion}
{%region TypeElement }
function TypeElement.parseRecompilableName(const name: AnsiString): &Type;
var
length: int;
dimCount: int;
begin
length := name.length;
if length > 0 then case name[1] of
'[': begin
dimCount := 1;
while (dimCount < AVTOOConstants.LIMIT_DIMENSIONS_COUNT) and (dimCount < length) and (name[dimCount + 1] = '[') do inc(dimCount);
result := fldProgramme.acquireArrayType(parseRecompilableName(name.substring(dimCount + 1)), dimCount);
exit;
end;
'L': begin
result := fldProgramme.getClassType(name.substring(2));
exit;
end;
else
result := fldProgramme.getPrimitiveType(PrimitiveType.recompilableNameToKind(name));
exit;
end;
result := nil;
end;
constructor TypeElement.create(__programme: Programme; __recompilableName: int);
begin
inherited create(__programme);
fldRecompilableName := __recompilableName;
end;
function TypeElement.getItem(): &Type;
var
name: AnsiString;
__type: &Type;
begin
__type := fldType;
if __type = nil then begin
name := (fldConstants[fldRecompilableName] as CoUnicodeString).asAnsiString();
__type := parseRecompilableName(name);
fldType := __type;
end;
result := __type;
end;
{%endregion}
{%region TypedMemberElement }
function TypedMemberElement.getTypedMember(): TypedMember;
begin
result := getItem() as TypedMember;
end;
{%endregion}
{%region FieldElement }
constructor FieldElement.create(__programme: Programme; __parentType, __recompilableName: int);
begin
inherited create(__programme);
fldParentType := __parentType;
fldRecompilableName := __recompilableName;
end;
function FieldElement.getItem(): Field;
var
name: AnsiString;
__constants: TObject_Array1d;
__type: TypeElement;
__field: Field;
begin
__field := fldField;
if __field = nil then begin
__constants := fldConstants;
__type := __constants[fldParentType] as TypeElement;
name := (__constants[fldRecompilableName] as CoUnicodeString).asAnsiString();
__field := Field(Lang.cast((__type.getItem() as ru.malik.elaborarer.avtoo.lang.ClassType).getChildFieldoid(name), Field));
fldField := __field;
end;
result := __field;
end;
{%endregion}
{%region CallableElement }
constructor CallableElement.create(__programme: Programme; __parentType, __recompilableName: int; const __argumentTypes: int_Array1d);
begin
inherited create(__programme);
fldParentType := __parentType;
fldRecompilableName := __recompilableName;
fldArgumentTypes := __argumentTypes;
end;
function CallableElement.getItem(): Callable;
var
index: int;
length: int;
name: AnsiString;
args: Type_Array1d;
arguments: int_Array1d;
__constants: TObject_Array1d;
__type: TypeElement;
__callable: Callable;
begin
__callable := fldCallable;
if __callable = nil then begin
arguments := fldArgumentTypes;
__constants := fldConstants;
__type := __constants[fldParentType] as TypeElement;
name := (__constants[fldRecompilableName] as CoUnicodeString).asAnsiString();
length := system.length(arguments);
args := Type_Array1d(&Array.newTObject1d(length));
for index := 0 to length - 1 do args[index] := (__constants[arguments[index]] as TypeElement).getItem();
__callable := (__type.getItem() as ru.malik.elaborarer.avtoo.lang.ClassType).getChildCallable(name, args);
fldCallable := __callable;
end;
result := __callable;
end;
{%endregion}
{%region PropertyElement }
constructor PropertyElement.create(__programme: Programme; __parentType, __recompilableName: int);
begin
inherited create(__programme);
fldParentType := __parentType;
fldRecompilableName := __recompilableName;
end;
function PropertyElement.getItem(): &Property;
var
name: AnsiString;
__constants: TObject_Array1d;
__type: TypeElement;
__property: &Property;
begin
__property := fldProperty;
if __property = nil then begin
__constants := fldConstants;
__type := __constants[fldParentType] as TypeElement;
name := (__constants[fldRecompilableName] as CoUnicodeString).asAnsiString();
__property := &Property(Lang.cast((__type.getItem() as ru.malik.elaborarer.avtoo.lang.ClassType).getChildFieldoid(name), &Property));
fldProperty := __property;
end;
result := __property;
end;
{%endregion}
{%region CompilerParallelWorker }
procedure CompilerParallelWorker.terminate(__exception: Exception);
var
terminates: int;
begin
with fldMonitor do begin
beginSynchronized();
try
if (fldException = nil) and (__exception <> nil) then begin
fldException := __exception.clone() as Exception;
end;
terminates := fldTerminates - 1;
fldTerminates := terminates;
if terminates <= 0 then notify();
finally
endSynchronized();
end;
end;
end;
function CompilerParallelWorker.nextTarget(): TObject;
var
index: int;
target: TObject;
__targets: ObjectArray;
begin
target := nil;
with fldMonitor do begin
beginSynchronized();
try
if fldException = nil then begin
index := fldIndex;
__targets := fldTargets;
if (__targets <> nil) and (index < __targets.getLength()) then begin
target := __targets.readComponent(index);
fldIndex := index + 1;
end;
end;
finally
endSynchronized();
end;
end;
result := target;
end;
procedure CompilerParallelWorker.setTargets(newTargets: ObjectArray);
begin
if fldContext <> Thread.current() then begin
raise IllegalParallelWorkerState.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'parallelworker.modify'));
end;
fldIndex := 0;
fldTargets := newTargets;
end;
constructor CompilerParallelWorker.create(__maxThreads: int);
begin
inherited create();
if __maxThreads < 1 then __maxThreads := 1;
fldMaxThreads := __maxThreads;
fldContext := Thread.current();
fldMonitor := Monitor.create();
fldObjects := HashtableOfValueToTObject.create();
end;
destructor CompilerParallelWorker.destroy;
var
index: int;
__objects: HashtableOfValueToTObject;
hash: Value;
begin
__objects := fldObjects;
for index := __objects.length - 1 downto 0 do begin
hash := __objects.keyAt(index);
__objects[hash].free();
end;
fldObjects.free();
fldMonitor.free();
inherited destroy;
end;
procedure CompilerParallelWorker.run(handler: CompilerRunnable);
var
index: int;
count: int;
__maxThreads: int;
__exception: Exception;
__runnable: CompilerParallelWorkerRunnable;
__objects: HashtableOfValueToTObject;
__thread: Thread;
creator: CompilerThreadObjectCreator;
hash: Value;
begin
if fldContext <> Thread.current() then begin
raise IllegalParallelWorkerState.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'parallelworker.run'));
end;
count := SystemInfo.getProcessorNumberOfCores();
count := (count shr 1) + (count and 1);
__maxThreads := fldMaxThreads;
if __maxThreads > count then __maxThreads := count;
__runnable := CompilerParallelWorkerRunnable.create(self, handler);
try
fldIndex := 0;
fldException := nil;
fldTerminates := __maxThreads;
__objects := fldObjects;
for index := __objects.length - 1 downto 0 do begin
hash := __objects.keyAt(index);
__objects[hash].free();
end;
__objects.clear();
if handler is CompilerThreadObjectCreator then begin
creator := handler as CompilerThreadObjectCreator;
for count := __maxThreads - 1 downto 0 do begin
__thread := Thread.create(__runnable);
hash := CoLong.create(__thread.getHashCode());
__objects[hash] := creator.createThreadObject();
__thread.start();
end;
end else begin
for count := __maxThreads - 1 downto 0 do begin
(Thread.create(__runnable)).start();
end;
end;
with fldMonitor do begin
beginSynchronized();
try
repeat
wait();
until fldTerminates <= 0;
finally
endSynchronized();
end;
end;
finally
__runnable.free();
end;
__exception := fldException;
fldException := nil;
if __exception is IOException then begin
raise IOException(__exception);
end;
if __exception is CompilerException then begin
raise CompilerException(__exception);
end;
if __exception is RuntimeException then begin
raise RuntimeException(__exception);
end;
__exception.free();
end;
function CompilerParallelWorker.threadObject(): TObject;
var
hash: Value;
begin
hash := CoLong.create(Thread.current().getHashCode());
result := fldObjects[hash];
end;
{%endregion}
{%region Project }
class function Project.isPackageSourceFileName(const fileName: UnicodeString): boolean;
begin
result := fileName.substring(fileName.length - UnicodeString(PACKAGE_SOURCE_EXTENSION).length + 1).equalsIgnoreCase(PACKAGE_SOURCE_EXTENSION);
end;
class function Project.isBinarySourceFileName(const fileName: UnicodeString): boolean;
begin
result := fileName.substring(fileName.length - UnicodeString(BINARY_SOURCE_EXTENSION).length + 1).equalsIgnoreCase(BINARY_SOURCE_EXTENSION);
end;
class function Project.isTypeSourceFileName(const fileName: UnicodeString): boolean;
begin
result := fileName.substring(fileName.length - UnicodeString(TYPE_SOURCE_EXTENSION).length + 1).equalsIgnoreCase(TYPE_SOURCE_EXTENSION);
end;
procedure Project.setMaxThreads(newMaxThreads: int);
begin
if newMaxThreads < 1 then newMaxThreads := 1;
fldMaxThreads := newMaxThreads;
end;
constructor Project.create();
begin
inherited create();
fldMaxThreads := CoInt.MAX_VALUE;
fldExcludes := UnicodeStringArray.create();
end;
destructor Project.destroy;
begin
fldExcludes.free();
inherited destroy;
end;
procedure Project.compile();
begin
{ 1. Стадия загрузки данных. Поиск и чтение файлов исходного кода. }
with CompilerParallelWorker.create(maxThreads) do try
targets := libraries;
run(ProjectSourcesLoader.create(self));
finally
free();
end;
end;
{%endregion}
{%region TableBuilder }
class procedure TableBuilder.appendImpliedSuperservices(const __classes: ClassType_Array1d);
var
index: int;
begin
for index := 0 to system.length(__classes) - 1 do __classes[index].appendImpliedSuperservices();
end;
class procedure TableBuilder.appendImpliedMembers(const __classes: ClassType_Array1d);
label
continue_label0;
var
isClass: boolean;
hasNoConstructor: boolean;
ssi: int;
ssj: int;
cindex: int;
mindex: int;
tindex: int;
slength: int;
position: int;
__member: Member;
__method: Method;
source: LexemeSequence;
overriddableA: OverriddableMember;
overriddableB: OverriddableMember;
current: ru.malik.elaborarer.avtoo.lang.ClassType;
superservice: ru.malik.elaborarer.avtoo.lang.ClassType;
begin
for cindex := 0 to system.length(__classes) - 1 do begin
current := __classes[cindex];
if current.isStruct() or current.isHelper() then continue;
isClass := current.isClass();
hasNoConstructor := isClass and not current.isArray();
source := LexemeSequence(Lang.cast(current.source, LexemeSequence));
for mindex := 0 to current.getLength() - 1 do begin
__member := current.readComponent(mindex);
if __member is OverriddableMember then begin
if __member.isSpecial() and (__member is InstInit) then hasNoConstructor := false;
continue;
end;
if __member is AllocatableMember then begin
position := __member.implementationPosition;
if (position >= 0) and (source.getLexemeKind(position) = EQUAL) and (current.getStaticBlock() = nil) then begin
current.createStaticBlock(VIS_PUBLIC or ATTR_STATIC or ATTR_SYNTHETIC, -1, -1);
end;
end;
end;
if hasNoConstructor then begin
current.createConstructor(VIS_PUBLIC or ATTR_SYNTHETIC, nil, -1, -1);
end;
if not isClass and (current.isAbstract() or not current.isService()) then continue;
slength := current.getSuperservicesLength();
for ssi := 0 to slength - 1 do begin
superservice := current.getSuperserviceTypeAt(ssi);
for mindex := 0 to superservice.getLength() - 1 do begin
__member := superservice.readComponent(mindex);
if not __member.isAbstract() then continue;
overriddableA := __member as OverriddableMember;
for ssj := 0 to slength - 1 do if ssi <> ssj then begin
overriddableB := overriddableA.overridesIn(current.getSuperserviceTypeAt(ssj), Method.CURRENT_TYPE);
if (overriddableB <> nil) and overriddableB.isVisibleFrom(current, current) then goto continue_label0;
end;
overriddableB := overriddableA.overridesIn(current, Method.CURRENT_TYPE or Method.SUPERCLASSES);
if (overriddableB <> nil) and overriddableB.isVisibleFrom(current, current) then continue;
if __member is Method then with Method(__member) do begin
__method := current.createMethod(attributes or ATTR_SYNTHETIC, &type, specialSimpleName, arguments.clone(true), -1, -1);
for tindex := 0 to getThrowablesLength() - 1 do __method.appendThrowable(getThrowableTypeAt(tindex), -1);
continue;
end;
if __member is &Operator then with &Operator(__member) do begin
current.createOperator(attributes or ATTR_SYNTHETIC, &type, kind, arguments.clone(true), -1, -1);
continue;
end;
with __member as &Property do begin
current.createProperty(attributes or ATTR_SYNTHETIC, &type, specialSimpleName, -1, -1);
end;
continue_label0:
end;
end;
end;
end;
class procedure TableBuilder.checkMembers(const __classes: ClassType_Array1d);
label
break_label0,
break_label1,
break_label2;
var
isHelper: boolean;
ssi: int;
ssj: int;
cindex: int;
mindex: int;
sindex: int;
impl: AnsiString;
incm: AnsiString;
hmember: Member;
tmember: Member;
__member: Member;
source: TextSource;
overriddableA: OverriddableMember;
overriddableB: OverriddableMember;
target: ru.malik.elaborarer.avtoo.lang.ClassType;
current: ru.malik.elaborarer.avtoo.lang.ClassType;
superclass: ru.malik.elaborarer.avtoo.lang.ClassType;
superservice: ru.malik.elaborarer.avtoo.lang.ClassType;
superserviceA: ru.malik.elaborarer.avtoo.lang.ClassType;
superserviceB: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
for cindex := 0 to system.length(__classes) - 1 do begin
current := __classes[cindex];
isHelper := current.isHelper();
impl := '';
for ssi := current.getSuperservicesLength() - 1 downto 0 do begin
superserviceA := current.getSuperserviceTypeAt(ssi);
for mindex := superserviceA.getLength() - 1 downto 0 do begin
__member := superserviceA.readComponent(mindex);
if __member.isSynthetic() or __member.isStatic() or not __member.isVisibleFrom(current, current) or not(__member is OverriddableMember) then continue;
overriddableA := OverriddableMember(__member);
for ssj := ssi - 1 downto 0 do begin
superserviceB := current.getSuperserviceTypeAt(ssj);
overriddableB := overriddableA.overridesIn(superserviceB, Method.CURRENT_TYPE);
if (overriddableB = nil) or not overriddableB.isVisibleFrom(current, current) then continue;
incm := '';
begin
if not isCompatibleTypes(overriddableA, overriddableB) then begin
if __member is Method then with Method(__member) do begin
incm := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'incompatible-services.method'), [
CoAnsiString.create(superserviceB.specialCanonicalName), CoAnsiString.create(superserviceA.specialCanonicalName),
CoAnsiString.create(current.specialSimpleName), CoAnsiString.create(specialSimpleName + arguments.toString())
]);
goto break_label0;
end;
if __member is &Operator then with &Operator(__member) do begin
incm := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'incompatible-services.operator'), [
CoAnsiString.create(superserviceB.specialCanonicalName), CoAnsiString.create(superserviceA.specialCanonicalName),
CoAnsiString.create(current.specialSimpleName), CoAnsiString.create(symbol + arguments.toString())
]);
goto break_label0;
end;
incm := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'incompatible-services.property'), [
CoAnsiString.create(superserviceB.specialCanonicalName), CoAnsiString.create(superserviceA.specialCanonicalName),
CoAnsiString.create(current.specialSimpleName), CoAnsiString.create(__member.specialSimpleName)
]);
goto break_label0;
end;
if impl.length <= 0 then begin
overriddableB := overriddableA.overridesIn(current, Method.CURRENT_TYPE or Method.SUPERCLASSES);
if (overriddableB = nil) or not overriddableB.isVisibleFrom(current, current) then begin
if __member is Method then with Method(__member) do begin
impl := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-also-implemented.method'), [
CoAnsiString.create(superserviceB.specialCanonicalName), CoAnsiString.create(superserviceA.specialCanonicalName),
CoAnsiString.create(current.specialSimpleName), CoAnsiString.create(specialSimpleName + arguments.toString())
]);
continue;
end;
if __member is &Operator then with &Operator(__member) do begin
impl := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-also-implemented.operator'), [
CoAnsiString.create(superserviceB.specialCanonicalName), CoAnsiString.create(superserviceA.specialCanonicalName),
CoAnsiString.create(current.specialSimpleName), CoAnsiString.create(symbol + arguments.toString())
]);
continue;
end;
impl := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-also-implemented.property'), [
CoAnsiString.create(superserviceB.specialCanonicalName), CoAnsiString.create(superserviceA.specialCanonicalName),
CoAnsiString.create(current.specialSimpleName), CoAnsiString.create(__member.specialSimpleName)
]);
continue;
end;
end;
end;
break_label0:
if incm.length > 0 then begin
source := TextSource(Lang.cast(current.source, TextSource));
if source = nil then begin
raise SourceException.create(incm);
end;
exception := TextSourceException.create(incm);
exception.source := source;
exception.position := current.declarationPosition;
raise exception;
end;
end;
end;
end;
if impl.length > 0 then begin
source := TextSource(Lang.cast(current.source, TextSource));
if source = nil then begin
raise SourceException.create(impl);
end;
exception := TextSourceException.create(impl);
exception.source := source;
exception.position := current.declarationPosition;
raise exception;
end;
begin
superclass := current.getSuperclassType();
if superclass <> nil then for mindex := current.getLength() - 1 downto 0 do begin
__member := current.readComponent(mindex);
if __member.isSpecial() or __member.isSynthetic() or __member.isStatic() or not(__member is OverriddableMember) then continue;
overriddableA := OverriddableMember(__member);
overriddableB := overriddableA.overridesIn(superclass, Method.CURRENT_TYPE or Method.SUPERCLASSES);
if (overriddableB <> nil) and overriddableB.isVisibleFrom(current, current) then checkOverriddable(current, overriddableA, overriddableB);
end;
end;
for sindex := current.getSuperservicesLength() - 1 downto 0 do begin
superservice := current.getSuperserviceTypeAt(sindex);
for mindex := superservice.getLength() - 1 downto 0 do begin
__member := superservice.readComponent(mindex);
if __member.isSynthetic() or __member.isStatic() or not __member.isVisibleFrom(current, current) or not(__member is OverriddableMember) then continue;
overriddableA := OverriddableMember(__member);
overriddableB := overriddableA.overridesIn(current, Method.CURRENT_TYPE or Method.SUPERCLASSES);
if (overriddableB <> nil) and overriddableB.isVisibleFrom(current, current) then checkOverriddable(current, overriddableB, overriddableA);
end;
end;
if not isHelper and not current.isAbstract() then begin
superclass := current;
repeat
for mindex := 0 to superclass.getLength() - 1 do begin
__member := superclass.readComponent(mindex);
if
__member.isAbstract() and
__member.isVisibleFrom(current, current) and
(__member as OverriddableMember).overridesIn(current, Method.CURRENT_TYPE or Method.SUPERCLASSES).isAbstract()
then begin
source := TextSource(Lang.cast(current.source, TextSource));
impl := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-be.abstract-type'), [
CoAnsiString.create(current.specialSimpleName)
]);
if source = nil then begin
raise SourceException.create(impl);
end;
exception := TextSourceException.create(impl);
exception.source := source;
exception.position := current.declarationPosition;
raise exception;
end;
end;
superclass := superclass.getSuperclassType();
until superclass = nil;
end;
begin
superclass := current.getSuperclassType();
while superclass <> nil do begin
for mindex := 0 to superclass.getLength() - 1 do begin
__member := superclass.readComponent(mindex);
if not __member.isAbstract() or __member.isVisibleFrom(current, current) then continue;
begin
if __member is Method then with Method(__member) do begin
impl := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-implement.method'), [
CoAnsiString.create(current.specialSimpleName), CoAnsiString.create(superclass.specialCanonicalName),
CoAnsiString.create(specialSimpleName + arguments.toString())
]);
goto break_label1;
end;
if __member is &Operator then with &Operator(__member) do begin
impl := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-implement.operator'), [
CoAnsiString.create(current.specialSimpleName), CoAnsiString.create(superclass.specialCanonicalName),
CoAnsiString.create(symbol + arguments.toString())
]);
goto break_label1;
end;
impl := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-implement.property'), [
CoAnsiString.create(current.specialSimpleName), CoAnsiString.create(superclass.specialCanonicalName),
CoAnsiString.create(__member.specialSimpleName)
]);
end;
break_label1:
if impl.length > 0 then begin
source := TextSource(Lang.cast(current.source, TextSource));
if source = nil then begin
raise SourceException.create(impl);
end;
exception := TextSourceException.create(impl);
exception.source := source;
exception.position := current.declarationPosition;
raise exception;
end;
end;
superclass := superclass.getSuperclassType();
end;
end;
if isHelper then begin
target := current.getHelperForType();
for mindex := 0 to current.getLength() - 1 do begin
hmember := current.readComponent(mindex);
if not hmember.isStatic() and (hmember is OverriddableMember) then begin
tmember := OverriddableMember(hmember).overridesIn(target, Method.CURRENT_TYPE or Method.SUPERTYPES);
end else
if hmember is Callable then begin
tmember := target.getChildCallable(hmember.specialSimpleName, Callable(hmember).arguments.clone());
end else begin
tmember := target.getChildMember(hmember.specialSimpleName);
end;
if (tmember = nil) or not tmember.isVisibleFrom(current, current) then continue;
begin
if hmember is Method then with Method(hmember) do begin
impl := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-reference.method'), [
CoAnsiString.create(target.specialSimpleName), CoAnsiString.create(specialSimpleName + arguments.toString())
]);
goto break_label2;
end;
if hmember is &Operator then with &Operator(hmember) do begin
impl := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-reference.operator'), [
CoAnsiString.create(target.specialSimpleName), CoAnsiString.create(symbol + arguments.toString())
]);
goto break_label2;
end;
if hmember is &Property then begin
impl := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-reference.property');
end else begin
impl := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-reference.field');
end;
impl := AnsiString.format(impl, [ CoAnsiString.create(target.specialSimpleName), CoAnsiString.create(hmember.specialSimpleName) ]);
end;
break_label2:
if impl.length > 0 then begin
source := TextSource(Lang.cast(current.source, TextSource));
if source = nil then begin
raise SourceException.create(impl);
end;
exception := TextSourceException.create(impl);
exception.source := source;
exception.position := hmember.declarationPosition;
raise exception;
end;
end;
end;
end;
end;
class procedure TableBuilder.checkSuperservices(const __classes: ClassType_Array1d);
var
ssi: int;
ssj: int;
cindex: int;
sindex: int;
slength: int;
position: int;
source: TObject;
binary: BinarySource;
current: ru.malik.elaborarer.avtoo.lang.ClassType;
superclassA: ru.malik.elaborarer.avtoo.lang.ClassType;
superclassB: ru.malik.elaborarer.avtoo.lang.ClassType;
superserviceA: ru.malik.elaborarer.avtoo.lang.ClassType;
superserviceB: ru.malik.elaborarer.avtoo.lang.ClassType;
bexception: BinarySourceException;
texception: TextSourceException;
begin
for cindex := 0 to system.length(__classes) - 1 do begin
current := __classes[cindex];
if current.isService() then begin
sindex := current.getSuperserviceIndex(current);
if sindex < 0 then continue;
source := Lang.cast(current.source, TObject);
if source is BinarySource then begin
binary := BinarySource(source);
bexception := BinarySourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'cyclic-inheritance'), [
CoAnsiString.create(current.specialCanonicalName)
]));
bexception.source := binary;
bexception.offset := binary.chunks.readComponent(current.declarationPosition).dataOffsetToSourceOffset(7 + (sindex shl 1));
raise bexception;
end;
if source is TextSource then begin
position := current.getSuperservicePositionAt(sindex);
while (position < 0) and (sindex >= 0) do begin
dec(sindex);
if sindex < 0 then begin
if current.getSuperclassType().isSuperservice(current) then position := current.getSuperclassPosition();
end else begin
if current.getSuperserviceTypeAt(sindex).isSuperservice(current) then position := current.getSuperservicePositionAt(sindex);
end;
end;
texception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'cyclic-inheritance'), [
CoAnsiString.create(current.specialCanonicalName)
]));
texception.source := TextSource(source);
texception.position := position;
raise texception;
end;
raise SourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'cyclic-inheritance'), [
CoAnsiString.create(current.specialCanonicalName)
]));
end;
slength := current.getSuperservicesLength();
for ssi := slength - 1 downto 1 do begin
superserviceA := current.getSuperserviceTypeAt(ssi);
superclassA := superserviceA.getSuperclassType();
for ssj := ssi - 1 downto 0 do begin
superserviceB := current.getSuperserviceTypeAt(ssj);
superclassB := superserviceB.getSuperclassType();
if (superclassA = superclassB) or superclassA.isSuperclass(superclassB) or superclassB.isSuperclass(superclassA) then continue;
source := Lang.cast(current.source, TObject);
if source is BinarySource then begin
binary := BinarySource(source);
bexception := BinarySourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'incompatible-services.superclass'), [
CoAnsiString.create(superserviceB.specialCanonicalName), CoAnsiString.create(superserviceA.specialCanonicalName),
CoAnsiString.create(superclassB.specialCanonicalName), CoAnsiString.create(superclassA.specialCanonicalName)
]
));
bexception.source := binary;
bexception.offset := binary.chunks.readComponent(current.declarationPosition).dataOffsetToSourceOffset(3);
raise bexception;
end;
if source is TextSource then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'incompatible-services.superclass'), [
CoAnsiString.create(superserviceB.specialCanonicalName), CoAnsiString.create(superserviceA.specialCanonicalName),
CoAnsiString.create(superclassB.specialCanonicalName), CoAnsiString.create(superclassA.specialCanonicalName)
]
));
texception.source := TextSource(source);
texception.position := current.declarationPosition + 1;
raise texception;
end;
raise SourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'incompatible-services.superclass'), [
CoAnsiString.create(superserviceB.specialCanonicalName), CoAnsiString.create(superserviceA.specialCanonicalName),
CoAnsiString.create(superclassB.specialCanonicalName), CoAnsiString.create(superclassA.specialCanonicalName)
]
));
end;
end;
if slength > 0 then begin
superclassA := current.getSuperserviceTypeAt(0).getSuperclassType();
for sindex := 1 to slength - 1 do begin
superclassB := current.getSuperserviceTypeAt(sindex).getSuperclassType();
if superclassB.isSuperclass(superclassA) then superclassA := superclassB;
end;
superclassB := current.getSuperclassType();
if (superclassB = superclassA) or superclassB.isSuperclass(superclassA) then continue;
source := Lang.cast(current.source, TObject);
if source is BinarySource then begin
binary := BinarySource(source);
bexception := BinarySourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-be.superclass'), [
CoAnsiString.create(superclassA.specialCanonicalName)
]));
bexception.source := binary;
bexception.offset := binary.chunks.readComponent(current.declarationPosition).dataOffsetToSourceOffset(5);
raise bexception;
end;
if source is TextSource then begin
texception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-be.superclass'), [
CoAnsiString.create(superclassA.specialCanonicalName)
]));
texception.source := TextSource(source);
texception.position := current.declarationPosition + 2;
raise texception;
end;
raise SourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-be.superclass'), [
CoAnsiString.create(superclassA.specialCanonicalName)
]));
end;
end;
end;
class procedure TableBuilder.checkSuperclasses(const __classes, __buffer: ClassType_Array1d);
var
cindex: int;
blength: int;
source: TObject;
binary: BinarySource;
current: ru.malik.elaborarer.avtoo.lang.ClassType;
superclass: ru.malik.elaborarer.avtoo.lang.ClassType;
bexception: BinarySourceException;
texception: TextSourceException;
begin
for cindex := 0 to system.length(__classes) - 1 do begin
current := __classes[cindex];
blength := 1;
__buffer[0] := current;
superclass := current.getSuperclassType();
while superclass <> nil do begin
if &Array.indexOf(superclass, __buffer, 0, blength) >= 0 then begin
source := Lang.cast(superclass.source, TObject);
if source is BinarySource then begin
binary := BinarySource(source);
bexception := BinarySourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'cyclic-inheritance'), [
CoAnsiString.create(superclass.specialCanonicalName)
]));
bexception.source := binary;
bexception.offset := binary.chunks.readComponent(superclass.declarationPosition).dataOffsetToSourceOffset(3);
raise bexception;
end;
if source is TextSource then begin
texception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'cyclic-inheritance'), [
CoAnsiString.create(superclass.specialCanonicalName)
]));
texception.source := TextSource(source);
texception.position := superclass.getSuperclassPosition();
raise texception;
end;
raise SourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'cyclic-inheritance'), [
CoAnsiString.create(superclass.specialCanonicalName)
]));
end;
__buffer[blength] := superclass;
inc(blength);
superclass := superclass.getSuperclassType();
end;
end;
end;
class procedure TableBuilder.checkOverriddable(current: ClassType; overridding, overridden: OverriddableMember);
label
break_label0,
break_label1,
break_label2;
var
fails: boolean;
tindex: int;
position: int;
name: AnsiString;
ovrr: AnsiString;
source: TextSource;
__method: Method;
__property: &Property;
__type: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
{ overridding – переопределяющий член }
{ overridden – переопределённый член }
ovrr := '';
position := -1;
begin
__property := nil;
if overridding.visibility < overridden.visibility then begin
if overridding is Method then with Method(overridding) do begin
ovrr := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'override.incompatible-visibility.method'), [
CoAnsiString.create(overridden.parentType.specialCanonicalName), CoAnsiString.create(current.specialSimpleName),
CoAnsiString.create(specialSimpleName + arguments.toString())
]);
goto break_label0;
end;
if overridding is &Operator then with &Operator(overridding) do begin
ovrr := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'override.incompatible-visibility.operator'), [
CoAnsiString.create(overridden.parentType.specialCanonicalName), CoAnsiString.create(current.specialSimpleName),
CoAnsiString.create(symbol + arguments.toString())
]);
goto break_label0;
end;
ovrr := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'override.incompatible-visibility.property'), [
CoAnsiString.create(overridden.parentType.specialCanonicalName), CoAnsiString.create(current.specialSimpleName),
CoAnsiString.create(overridding.specialSimpleName)
]);
goto break_label0;
end;
if overridden.isFinal() then begin
if overridding is Method then with Method(overridding) do begin
ovrr := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'override.final.method'), [
CoAnsiString.create(overridden.parentType.specialCanonicalName), CoAnsiString.create(current.specialSimpleName),
CoAnsiString.create(specialSimpleName + arguments.toString())
]);
goto break_label0;
end;
if overridding is &Operator then with &Operator(overridding) do begin
ovrr := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'override.final.operator'), [
CoAnsiString.create(overridden.parentType.specialCanonicalName), CoAnsiString.create(current.specialSimpleName),
CoAnsiString.create(symbol + arguments.toString())
]);
goto break_label0;
end;
ovrr := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'override.final.property'), [
CoAnsiString.create(overridden.parentType.specialCanonicalName), CoAnsiString.create(current.specialSimpleName),
CoAnsiString.create(overridding.specialSimpleName)
]);
goto break_label0;
end;
begin
if overridden is &Property then begin
__property := &Property(overridden);
if __property.hasWrite() then begin
fails := overridden.&type <> overridding.&type;
goto break_label1;
end;
end;
fails := not overridden.&type.isAssignableFrom(overridding.&type);
end;
break_label1:
if fails then begin
if overridding is Method then with Method(overridding) do begin
ovrr := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'override.incompatible-type.method'), [
CoAnsiString.create(overridden.parentType.specialCanonicalName), CoAnsiString.create(current.specialSimpleName),
CoAnsiString.create(specialSimpleName + arguments.toString())
]);
goto break_label0;
end;
if overridding is &Operator then with &Operator(overridding) do begin
ovrr := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'override.incompatible-type.operator'), [
CoAnsiString.create(overridden.parentType.specialCanonicalName), CoAnsiString.create(current.specialSimpleName),
CoAnsiString.create(symbol + arguments.toString())
]);
goto break_label0;
end;
ovrr := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'override.incompatible-type.property'), [
CoAnsiString.create(overridden.parentType.specialCanonicalName), CoAnsiString.create(current.specialSimpleName),
CoAnsiString.create(overridding.specialSimpleName)
]);
goto break_label0;
end;
if overridding is Method then with Method(overridding) do begin
name := '';
begin
__method := overridden as Method;
for tindex := 0 to getThrowablesLength() - 1 do begin
__type := getThrowableTypeAt(tindex);
if not __method.canThrown(__type) then begin
name := __type.specialCanonicalName;
position := getThrowablePositionAt(tindex);
goto break_label2;
end;
end;
exit;
end;
break_label2:
ovrr := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'override.can-not.throws.method'), [
CoAnsiString.create(overridden.parentType.specialCanonicalName), CoAnsiString.create(current.specialSimpleName),
CoAnsiString.create(specialSimpleName + arguments.toString()), CoAnsiString.create(name)
]);
goto break_label0;
end;
if overridding is &Property then with &Property(overridding) do begin
if not hasRead() and __property.hasRead() then begin
ovrr := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'override.must-have.property.read'), [
CoAnsiString.create(overridden.parentType.specialCanonicalName), CoAnsiString.create(current.specialSimpleName), CoAnsiString.create(specialSimpleName)
]);
goto break_label0;
end;
if not hasWrite() and __property.hasWrite() then begin
ovrr := AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'override.must-have.property.write'), [
CoAnsiString.create(overridden.parentType.specialCanonicalName), CoAnsiString.create(current.specialSimpleName), CoAnsiString.create(specialSimpleName)
]);
goto break_label0;
end;
end;
end;
break_label0:
if ovrr.length > 0 then begin
source := TextSource(Lang.cast(current.source, TextSource));
if position < 0 then begin
position := overridding.declarationPosition;
if (current <> overridding.parentType) or (position < 0) then position := current.declarationPosition;
end;
if source = nil then begin
raise SourceException.create(ovrr);
end;
exception := TextSourceException.create(ovrr);
exception.source := source;
exception.position := position;
raise exception;
end;
end;
class function TableBuilder.isCompatibleTypes(overriddableA, overriddableB: OverriddableMember): boolean;
begin
if overriddableA is &Property then begin
if &Property(overriddableA).hasWrite() then begin
if (overriddableB as &Property).hasWrite() then begin
result := overriddableA.&type = overriddableB.&type;
exit;
end;
result := overriddableB.&type.isAssignableFrom(overriddableA.&type);
exit;
end;
if (overriddableB as &Property).hasWrite() then begin
result := overriddableA.&type.isAssignableFrom(overriddableB.&type);
exit;
end;
end;
result := overriddableA.&type.isCompatibleWith(overriddableB.&type);
end;
class function TableBuilder.skipPropertySpecifier(source: TextSource; position: int): int;
var
kind: int;
curly: int;
bracket: int;
parenth: int;
exception: TextSourceException;
begin
kind := source.getLexemeKind(position);
if (kind = COMMA) or (kind = CURLY_CLOSED) then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.property-specifier'));
exception.source := source;
exception.position := position;
raise exception;
end;
curly := 0;
bracket := 0;
parenth := 0;
while (kind <> COMMA) and (kind <> CURLY_CLOSED) or ((curly or bracket or parenth) <> 0) do begin
case kind of
CURLY_OPENED: begin
inc(curly);
end;
CURLY_CLOSED: begin
if curly = 0 then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'extra.curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
dec(curly);
end;
BRACKET_OPENED: begin
inc(bracket);
end;
BRACKET_CLOSED: begin
if bracket = 0 then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'extra.bracket'));
exception.source := source;
exception.position := position;
raise exception;
end;
dec(bracket);
end;
PARENTH_OPENED: begin
inc(parenth);
end;
PARENTH_CLOSED: begin
if parenth = 0 then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'extra.parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
dec(parenth);
end;
L_END: begin
if curly > 0 then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-closed.curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
if bracket > 0 then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-closed.bracket'));
exception.source := source;
exception.position := position;
raise exception;
end;
if parenth > 0 then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-closed.parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unexpected-end.source'));
exception.source := source;
exception.position := position;
raise exception;
end;
end;
inc(position);
kind := source.getLexemeKind(position);
end;
result := position;
end;
class function TableBuilder.packArguments(const arguments: Local_Array1d): Local_Array1d;
var
length: int;
buffer: Local_Array1d;
begin
length := &Array.indexOf(nil, arguments, 0, 0);
if length < 0 then begin
result := arguments;
exit;
end;
if length = 0 then begin
result := nil;
exit;
end;
buffer := Local_Array1d(&Array.newTObject1d(length));
&Array.copyObjects(arguments, 0, buffer, 0, length);
result := buffer;
end;
class function TableBuilder.toTypedItemArray(const arguments: Local_Array1d): TypedItem_Array1d;
var
index: int;
length: int;
buffer: TypedItem_Array1d;
begin
length := &Array.indexOf(nil, arguments, 0, 0);
if length < 0 then begin
length := system.length(arguments);
end;
if length <= 0 then begin
result := nil;
exit;
end;
buffer := TypedItem_Array1d(&Array.newISimple1d(length));
for index := 0 to length - 1 do begin
buffer[index] := arguments[index];
end;
result := buffer;
end;
procedure TableBuilder.setDocumentationEnabled(newDocumentationEnabled: boolean);
begin
fldLanguageLexer.documentationEnabled := newDocumentationEnabled;
end;
function TableBuilder.isDocumentationEnabled(): boolean;
begin
result := fldLanguageLexer.documentationEnabled;
end;
function TableBuilder.parseAllocatableMembers(source: TextSource; position: int; enclosing: ClassType; container: AllocatableFactory): int;
label
continue_label0;
var
kind: int;
capacity: int;
declarationPosition: int;
documentationPosition: int;
specialSimpleName: AnsiString;
__type: &Type;
exception: TextSourceException;
begin
repeat
kind := source.getLexemeKind(position);
if kind = CURLY_CLOSED then break;
{ документация }
documentationPosition := -1;
if kind = L_DOC then begin
documentationPosition := position;
inc(position);
kind := source.getLexemeKind(position);
end;
case kind of
{ вложенная структура }
DCL_STRUCT: begin
declarationPosition := position;
inc(position);
if source.getLexemeKind(position) <> CURLY_OPENED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
position := parseAllocatableMembers(source, position + 1, enclosing, container.createNestedStruct(declarationPosition, documentationPosition));
goto continue_label0;
end;
{ вложенное объединение }
DCL_UNION: begin
declarationPosition := position;
inc(position);
if source.getLexemeKind(position) <> CURLY_OPENED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
position := parseAllocatableMembers(source, position + 1, enclosing, container.createNestedUnion(declarationPosition, documentationPosition));
goto continue_label0;
end;
{ видимость }
VIS_PRIVATE,
VIS_PACKAGE,
VIS_PROTECTED: begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-visibility.struct-field'));
exception.source := source;
exception.position := position;
raise exception;
end;
VIS_PUBLIC,
VIS_PUBLISHED: begin
inc(position);
kind := source.getLexemeKind(position);
end;
end;
{ тип }
if (kind < TYP_VOID) or (kind > TYP_VOID + PRIMITIVES_LENGTH) or not isPrimitiveKind(kind) then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.primitive-type'));
exception.source := source;
exception.position := position;
raise exception;
end;
__type := getPrimitiveType(kind);
if __type.isVoid() then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'type.not-suitable.field'), [
CoObject.create(__type)
]));
exception.source := source;
exception.position := position;
raise exception;
end;
{ ёмкость }
capacity := 0;
inc(position);
kind := source.getLexemeKind(position);
if kind = BRACKET_OPENED then begin
inc(position);
kind := source.getLexemeKind(position);
if (kind <> L_BYTE) and (kind <> L_SHORT) and (kind <> L_INT) then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.number-of-int'));
exception.source := source;
exception.position := position;
raise exception;
end;
capacity := source.getLexemeInt(position);
if (capacity < 1) or (capacity > LIMIT_FIELD_LENGTH) then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'struct-field.capacity'), [
CoAnsiString.create(CoInt.toString(LIMIT_FIELD_LENGTH))
]));
exception.source := source;
exception.position := position;
raise exception;
end;
inc(position);
if source.getLexemeKind(position) <> BRACKET_CLOSED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-bracket'));
exception.source := source;
exception.position := position;
raise exception;
end;
__type := getArrayType(__type);
inc(position);
kind := source.getLexemeKind(position);
end;
{ название }
specialSimpleName := '';
declarationPosition := -1;
if kind = L_NAME then begin
specialSimpleName := source.getLexemeString(position).toUTF8();
if enclosing.getChildMember(specialSimpleName) <> nil then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'duplicate.name.field'), [
CoAnsiString.create(specialSimpleName)
]));
exception.source := source;
exception.position := position;
raise exception;
end;
declarationPosition := position;
inc(position);
kind := source.getLexemeKind(position);
end;
{ обязательная точка с запятой }
if kind <> SEMICOLON then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.semicolon'));
exception.source := source;
exception.position := position;
raise exception;
end;
{ создание поля }
container.createStructField(__type, capacity, specialSimpleName, declarationPosition, documentationPosition);
continue_label0:
inc(position);
until false;
result := position;
end;
function TableBuilder.parseArgumentsClause(source: TextSource; position: int; enclosing: ClassType; const arguments: Local_Array1d): int;
label
break_label0;
var
isFinal: boolean;
index: int;
length: int;
before: int;
argumentName: UnicodeString;
argumentType: &Type;
universalHolder: TableBuilderVectorAndTypeHolder;
exception: TextSourceException;
begin
length := system.length(arguments);
universalHolder := nil;
try
if source.getLexemeKind(position) = PARENTH_CLOSED then begin
inc(position);
end else begin
universalHolder := TableBuilderVectorAndTypeHolder.create();
for index := 0 to length - 1 do begin
isFinal := false;
if source.getLexemeKind(position) = DCL_FINAL then begin
isFinal := true;
inc(position);
end;
before := position;
position := parseTypeName(source, position, enclosing, universalHolder);
argumentType := universalHolder.resultType;
if argumentType.isVoid() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'type.not-suitable.argument'), [
CoObject.create(argumentType)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if source.getLexemeKind(position) <> L_NAME then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.name.argument'));
exception.source := source;
exception.position := position;
raise exception;
end;
argumentName := source.getLexemeString(position);
if universalHolder.contains(argumentName) then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'duplicate.name.argument'), [
CoUnicodeString.create(argumentName)
]));
exception.source := source;
exception.position := position;
raise exception;
end;
universalHolder.append(argumentName);
arguments[index] := createLocal(isFinal, argumentType, argumentName.toUTF8(), nil, source, position);
inc(position);
case source.getLexemeKind(position) of
PARENTH_CLOSED: begin
inc(position);
goto break_label0;
end;
COMMA: begin
inc(position);
end;
else
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.comma-or-closed-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
end;
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'too-many.arguments'));
exception.source := source;
exception.position := position;
raise exception;
end;
break_label0:
finally
universalHolder.free();
end;
result := position;
end;
function TableBuilder.parseThrowsClause(source: TextSource; position: int; enclosing: ClassType; method: Method): int;
var
before: int;
name: AnsiString;
__type: ru.malik.elaborarer.avtoo.lang.ClassType;
throwTypeHolder: TableBuilderClassTypeHolder;
exception: TextSourceException;
begin
throwTypeHolder := TableBuilderClassTypeHolder.create();
try
repeat
before := position;
position := parseClassName(source, position, enclosing, throwTypeHolder);
__type := throwTypeHolder.resultClassType;
name := __type.specialCanonicalName;
if (name <> PACKNAME_LANG + '.' + TYPENAME_THROWABLE) and not __type.isSuperclass(PACKNAME_LANG + '.' + TYPENAME_THROWABLE) then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.thrown'), [
CoAnsiString.create(name), CoAnsiString.create(PACKNAME_LANG + '.' + TYPENAME_THROWABLE)
]));
exception.source := source;
exception.position := before;
raise exception;
end;
if method.isThrows(__type) then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'duplicate.exception.type'), [
CoAnsiString.create(name)
]));
exception.source := source;
exception.position := before;
raise exception;
end;
method.appendThrowable(__type, before);
if source.getLexemeKind(position) <> COMMA then break;
inc(position);
until false;
finally
throwTypeHolder.free();
end;
result := position;
end;
function TableBuilder.parsePackageName(source: TextSource; position: int; specialCanonicalName: AnsiStringHolder): int;
var
exception: TextSourceException;
begin
if source.getLexemeKind(position) <> L_NAME then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.name.package'));
exception.source := source;
exception.position := position;
raise exception;
end;
specialCanonicalName.appendResultString(source.getLexemeString(position).toUTF8());
repeat
inc(position);
if source.getLexemeKind(position) <> PERIOD then break;
inc(position);
if source.getLexemeKind(position) <> L_NAME then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.continue.package'));
exception.source := source;
exception.position := position;
raise exception;
end;
specialCanonicalName.appendResultString('.' + source.getLexemeString(position).toUTF8());
until false;
result := position;
end;
function TableBuilder.parseClassName(source: TextSource; position: int; enclosing: ClassType; parsed: TypeHolder): int;
label
break_label0;
var
start: int;
length: int;
name: AnsiString;
foundTypes: ClassType_Array1d;
specialCanonicalName: TableBuilderAnsiStringHolder;
resultClassType: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
if source.getLexemeKind(position) <> L_NAME then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.name.package-or-type'));
exception.source := source;
exception.position := position;
raise exception;
end;
specialCanonicalName := nil;
try
begin
start := position;
name := source.getLexemeString(position).toUTF8();
inc(position);
{ поиск среди типов в исходном коде }
resultClassType := source.getDeclaredType(name);
if resultClassType <> nil then goto break_label0;
resultClassType := source.getImportedType(name);
if resultClassType <> nil then goto break_label0;
{ поиск в родительском пакете }
resultClassType := source.owner.getChildType(name) as ru.malik.elaborarer.avtoo.lang.ClassType;
if (resultClassType <> nil) and resultClassType.isVisibleFrom(enclosing) then goto break_label0;
{ поиск среди неявно импортированных типов }
foundTypes := source.findImplicitlyImportedTypes(name, enclosing);
length := system.length(foundTypes);
if length > 0 then begin
resultClassType := foundTypes[0];
if resultClassType.isVisibleFrom(enclosing) then begin
if length > 1 then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.type'), [
CoAnsiString.create(name)
]));
exception.source := source;
exception.position := start;
raise exception;
end;
goto break_label0;
end;
end;
{ поиск в языковом пакете }
resultClassType := getLanguagePackage().getChildType(name) as ru.malik.elaborarer.avtoo.lang.ClassType;
if (resultClassType <> nil) and resultClassType.isVisibleFrom(enclosing) then goto break_label0;
{ распознавание канонического имени типа }
specialCanonicalName := TableBuilderAnsiStringHolder.create();
specialCanonicalName.appendResultString(name);
while source.getLexemeKind(position) = PERIOD do begin
inc(position);
if source.getLexemeKind(position) <> L_NAME then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.name.package-or-type'));
exception.source := source;
exception.position := position;
raise exception;
end;
specialCanonicalName.appendResultString('.' + source.getLexemeString(position).toUTF8());
inc(position);
name := specialCanonicalName.toString();
resultClassType := getClassType(name);
if resultClassType <> nil then begin
if not resultClassType.isVisibleFrom(enclosing) then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.type'), [
CoAnsiString.create(name)
]));
exception.source := source;
exception.position := start;
raise exception;
end;
goto break_label0;
end;
end;
{ не найдено? }
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-found.type'), [
CoObject.create(specialCanonicalName)
]));
exception.source := source;
exception.position := start;
raise exception;
end;
break_label0:
finally
specialCanonicalName.free();
end;
if not parsed.helpersAllowed and resultClassType.isHelper() then begin
exception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'helper.reference'), [
CoAnsiString.create(resultClassType.specialCanonicalName)
]));
exception.source := source;
exception.position := position;
raise exception;
end;
parsed.resultType := resultClassType;
result := position;
end;
function TableBuilder.parseTypeName(source: TextSource; position: int; enclosing: ClassType; parsed: TypeHolder): int;
var
kind: int;
dimCount: int;
resultType: &Type;
begin
kind := source.getLexemeKind(position);
if kind = TYP_VOID then begin
parsed.resultType := getPrimitiveType(TYP_VOID);
result := position + 1;
exit;
end;
if (kind > TYP_VOID) and (kind < TYP_VOID + PRIMITIVES_LENGTH) and isPrimitiveKind(kind) then begin
inc(position);
resultType := getPrimitiveType(kind);
end else begin
position := parseClassName(source, position, enclosing, parsed);
resultType := parsed.resultType;
if resultType.isHelper() then begin
parsed.resultType := resultType;
result := position;
exit;
end;
end;
dimCount := 0;
while (dimCount < LIMIT_DIMENSIONS_COUNT) and (source.getLexemeKind(position) = BRACKET_OPENED) and (source.getLexemeKind(position + 1) = BRACKET_CLOSED) do begin
resultType := acquireArrayType(resultType);
inc(position, 2);
inc(dimCount);
end;
parsed.resultType := resultType;
result := position;
end;
function TableBuilder.parseOperator(source: TextSource; position: int; parsed: OperatorHolder): int;
var
resultKind: int;
exception: TextSourceException;
begin
resultKind := source.getLexemeKind(position);
case resultKind of
BRACKET_OPENED: begin
inc(position);
if source.getLexemeKind(position) <> BRACKET_CLOSED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-bracket'));
exception.source := source;
exception.position := position;
raise exception;
end;
inc(position);
if source.getLexemeKind(position) <> EQUAL then begin
resultKind := READ_COMPONENT;
end else begin
resultKind := WRITE_COMPONENT;
inc(position);
end;
end;
PARENTH_OPENED: begin
inc(position);
if source.getLexemeKind(position) <> PARENTH_CLOSED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
resultKind := INVOKE_VIRTUAL;
inc(position);
end;
O_BIT_AND,
O_BIT_OR,
O_BIT_XOR,
O_SCAL_MUL,
O_SCAL_DIV,
O_SCAL_DIVU,
O_SCAL_REM,
O_SCAL_REMU,
O_SCAL_ADD,
O_SCAL_SUB,
O_SCAL_SHR,
O_SCAL_SHRU,
O_SCAL_SHL,
O_SCAL_GT,
O_SCAL_GE,
O_SCAL_LT,
O_SCAL_LE,
O_VECT_MUL,
O_VECT_DIV,
O_VECT_ADD,
O_VECT_SUB,
O_VECT_SHR,
O_VECT_SHRU,
O_VECT_SHL,
O_VECT_GT,
O_VECT_GE,
O_VECT_LT,
O_VECT_LE,
O_VECT_EQ,
O_VECT_NE,
O_VECT_HMUL,
O_VECT_SADD,
O_VECT_SSUB,
O_VECT_HMULU,
O_VECT_SADDU,
O_VECT_SSUBU: begin
inc(position);
if source.getLexemeKind(position) = REVERSE then begin
inc(resultKind, R_DELTA);
inc(position);
end;
end;
O_BIT_NOT,
O_SCAL_POS,
O_SCAL_NEG,
O_VECT_POS,
O_VECT_NEG,
O_VECT_LUP,
O_VECT_UUP,
O_VECT_PCK: begin
inc(position);
end;
else
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.valid-operator'));
exception.source := source;
exception.position := position;
raise exception;
end;
parsed.resultKind := resultKind;
result := position;
end;
procedure TableBuilder.prefetchSupertypesForPrimitiveArray(&array: ArrayType);
var
index: int;
name: AnsiString;
names: AnsiString_Array1d;
supertype: ru.malik.elaborarer.avtoo.lang.ClassType;
begin
name := &array.componentType.specialSimpleName;
name := CoChar.toUpperCase(name[1]) + name.substring(2) + 'Array';
names := [
PACKNAME_LANG + '.' + TYPENAME_RAW_DATA,
PACKNAME_LANG + '.' + TYPENAME_CLONEABLE,
PACKNAME_ARRAY + '.' + TYPENAME_MEASUREABLE,
PACKNAME_ARRAY + '.' + TYPENAME_MUTABLE_MEASUREABLE,
PACKNAME_ARRAY + '.Resizeable' + name,
PACKNAME_ARRAY + '.Mutable' + name,
PACKNAME_ARRAY + '.' + name
];
&array.initSuperclass(getClassType(PACKNAME_LANG + '.' + TYPENAME_OBJECT), -1);
for index := 0 to system.length(names) - 1 do begin
supertype := getClassType(names[index]);
if (supertype <> nil) and ((supertype.attributes and (VIS_PUBLIC or ATTR_SERVICE)) = (VIS_PUBLIC or ATTR_SERVICE)) then &array.appendSuperservice(supertype, -1);
end;
end;
procedure TableBuilder.prefetchSupertypesForObjectArray(&array: ArrayType);
var
index: int;
name: AnsiString;
names: AnsiString_Array1d;
supertype: ru.malik.elaborarer.avtoo.lang.ClassType;
begin
name := &array.componentType.specialSimpleName;
name := CoChar.toUpperCase(name[1]) + name.substring(2) + 'Array';
names := [
PACKNAME_LANG + '.' + TYPENAME_IMMUTABLE_OBJECT,
PACKNAME_LANG + '.' + TYPENAME_CLONEABLE,
PACKNAME_ARRAY + '.' + TYPENAME_MEASUREABLE,
PACKNAME_ARRAY + '.' + TYPENAME_MUTABLE_MEASUREABLE,
PACKNAME_ARRAY + '.' + TYPENAME_IMMUTABLE_MEASUREABLE,
PACKNAME_ARRAY + '.Resizeable' + name,
PACKNAME_ARRAY + '.Immutable' + name,
PACKNAME_ARRAY + '.Mutable' + name,
PACKNAME_ARRAY + '.' + name
];
&array.initSuperclass(getClassType(PACKNAME_LANG + '.' + TYPENAME_OBJECT), -1);
for index := 0 to system.length(names) - 1 do begin
supertype := getClassType(names[index]);
if (supertype <> nil) and ((supertype.attributes and (VIS_PUBLIC or ATTR_SERVICE)) = (VIS_PUBLIC or ATTR_SERVICE)) then &array.appendSuperservice(supertype, -1);
end;
end;
procedure TableBuilder.prefetchSupertypesForReferenceArray(&array: ArrayType);
begin
&array.initSuperclass(getClassType(PACKNAME_LANG + '.' + TYPENAME_OBJECT + '[]'), -1);
end;
procedure TableBuilder.createMembersForPrimitiveArray(&array: ArrayType);
var
typeInt: &Type;
typeLong: &Type;
typeVoid: &Type;
classStruct: &Type;
componentType: &Type;
fieldLength: TypedMember;
fieldCapacity: TypedMember;
methodSetLength: TypedMember;
propertyLength: &Property;
propertyCapacity: &Property;
begin
typeInt := getPrimitiveType(TYP_INT);
typeLong := getPrimitiveType(TYP_LONG);
typeVoid := getPrimitiveType(TYP_VOID);
classStruct := getType(PACKNAME_LANG + '.' + TYPENAME_STRUCT);
componentType := &array.componentType;
fieldLength := &array.createClassField(VIS_PRIVATE, typeInt, 'fldLength', -1, -1);
&array.createClassField(VIS_PRIVATE, typeInt, 'fldLengthZeroContinuation', -1, -1);
fieldCapacity := &array.createClassField(VIS_PRIVATE, typeInt, 'fldCapacity', -1, -1);
&array.createClassField(VIS_PRIVATE, typeInt, 'fldCapacityZeroContinuation', -1, -1);
&array.createClassField(VIS_PRIVATE, classStruct, 'fldParentStruct', -1, -1);
&array.createClassField(VIS_PRIVATE, typeLong, 'fldOffset', -1, -1);
if componentType.isChar() then &array.createMethod(VIS_PUBLIC or ATTR_NATIVE, getType(PACKNAME_LANG + '.' + TYPENAME_STRING), 'toString', nil, -1, -1);
&array.createMethod(VIS_PUBLIC or ATTR_NATIVE, typeLong, 'getPointer', nil, -1, -1);
&array.createMethod(VIS_PUBLIC or ATTR_NATIVE, typeLong, 'getLength', nil, -1, -1);
&array.createMethod(VIS_PUBLIC or ATTR_NATIVE, &array, 'clone', nil, -1, -1);
propertyLength := &array.createProperty(VIS_PUBLIC, typeInt, 'length', -1, -1);
propertyCapacity := &array.createProperty(VIS_PUBLIC, typeInt, 'capacity', -1, -1);
&array.createOperator(VIS_PUBLIC or ATTR_NATIVE, typeVoid, WRITE_COMPONENT, [
createLocal(false, typeInt, 'index', nil, nil, -1),
createLocal(false, componentType, 'component', nil, nil, -1)
], -1, -1);
&array.createOperator(VIS_PUBLIC or ATTR_NATIVE, componentType, READ_COMPONENT, [
createLocal(false, typeInt, 'index', nil, nil, -1)
], -1, -1);
methodSetLength := &array.createMethod(VIS_PRIVATE or ATTR_NATIVE, typeVoid, 'setLength', [
createLocal(false, typeInt, 'newLength', nil, nil, -1)
], -1, -1);
&array.createMethod(VIS_PUBLIC or ATTR_SYNTHETIC, typeInt, propertyLength.specialSimpleName + ('.' + MEMBER_SUFFIX_READ), nil, -1, -1);
&array.createMethod(VIS_PUBLIC or ATTR_SYNTHETIC, typeVoid, propertyLength.specialSimpleName + ('.' + MEMBER_SUFFIX_WRITE), [
createLocal(false, typeInt, SPECNAME_VALUE, nil, nil, -1)
], -1, -1);
&array.createMethod(VIS_PUBLIC or ATTR_SYNTHETIC, typeInt, propertyCapacity.specialSimpleName + ('.' + MEMBER_SUFFIX_READ), nil, -1, -1);
propertyLength.readMember := fieldLength;
propertyLength.writeMember := methodSetLength;
propertyCapacity.readMember := fieldCapacity;
end;
procedure TableBuilder.createMembersForObjectArray(&array: ArrayType);
var
typeInt: &Type;
typeLong: &Type;
typeVoid: &Type;
typeBoolean: &Type;
componentType: &Type;
fieldLength: TypedMember;
fieldCapacity: TypedMember;
methodSetLength: TypedMember;
propertyLength: &Property;
propertyCapacity: &Property;
begin
typeInt := getPrimitiveType(TYP_INT);
typeLong := getPrimitiveType(TYP_LONG);
typeVoid := getPrimitiveType(TYP_VOID);
typeBoolean := getPrimitiveType(TYP_BOOLEAN);
componentType := &array.componentType;
fieldLength := &array.createClassField(VIS_PRIVATE, typeInt, 'fldLength', -1, -1);
&array.createClassField(VIS_PRIVATE, typeInt, 'fldLengthZeroContinuation', -1, -1);
fieldCapacity := &array.createClassField(VIS_PRIVATE, typeInt, 'fldCapacity', -1, -1);
&array.createClassField(VIS_PRIVATE, typeInt, 'fldCapacityZeroContinuation', -1, -1);
&array.createClassField(VIS_PRIVATE, typeLong, 'fldReserved30', -1, -1);
&array.createClassField(VIS_PRIVATE, typeLong, 'fldOffset', -1, -1);
&array.createMethod(VIS_PUBLIC or ATTR_NATIVE, typeVoid, 'finalize', nil, -1, -1);
&array.createMethod(VIS_PUBLIC or ATTR_NATIVE, typeBoolean, 'isMutable', nil, -1, -1);
&array.createMethod(VIS_PUBLIC or ATTR_NATIVE, &array, 'clone', nil, -1, -1);
propertyLength := &array.createProperty(VIS_PUBLIC, typeInt, 'length', -1, -1);
propertyCapacity := &array.createProperty(VIS_PUBLIC, typeInt, 'capacity', -1, -1);
&array.createOperator(VIS_PUBLIC or ATTR_NATIVE, typeVoid, WRITE_COMPONENT, [
createLocal(false, typeInt, 'index', nil, nil, -1),
createLocal(false, componentType, 'component', nil, nil, -1)
], -1, -1);
&array.createOperator(VIS_PUBLIC or ATTR_NATIVE, componentType, READ_COMPONENT, [
createLocal(false, typeInt, 'index', nil, nil, -1)
], -1, -1);
methodSetLength := &array.createMethod(VIS_PRIVATE or ATTR_NATIVE, typeVoid, 'setLength', [
createLocal(false, typeInt, 'newLength', nil, nil, -1)
], -1, -1);
&array.createMethod(VIS_PUBLIC or ATTR_SYNTHETIC, typeInt, propertyLength.specialSimpleName + ('.' + MEMBER_SUFFIX_READ), nil, -1, -1);
&array.createMethod(VIS_PUBLIC or ATTR_SYNTHETIC, typeVoid, propertyLength.specialSimpleName + ('.' + MEMBER_SUFFIX_WRITE), [
createLocal(false, typeInt, SPECNAME_VALUE, nil, nil, -1)
], -1, -1);
&array.createMethod(VIS_PUBLIC or ATTR_SYNTHETIC, typeInt, propertyCapacity.specialSimpleName + ('.' + MEMBER_SUFFIX_READ), nil, -1, -1);
propertyLength.readMember := fieldLength;
propertyLength.writeMember := methodSetLength;
propertyCapacity.readMember := fieldCapacity;
end;
function TableBuilder.createDocumentLexer(): DocumentLexer;
begin
result := nil;
end;
function TableBuilder.createLanguageLexer(__documentationLexer: DocumentLexer): LanguageLexer;
begin
result := nil;
end;
function TableBuilder.newSource(parentLibrary: &Library; const relativePath: UnicodeString; const &type: AnsiString): Source;
begin
if &type = BINARY_SOURCE then begin
result := TableBuilderBinarySource.create(parentLibrary, relativePath);
exit;
end;
if &type = TEXT_SOURCE then begin
result := TableBuilderTextSource.create(parentLibrary, relativePath);
exit;
end;
result := inherited newSource(parentLibrary, relativePath, &type);
end;
function TableBuilder.getSourceType(__library: &Library): AnsiString;
begin
if __library = fldProject then begin
result := TEXT_SOURCE;
exit;
end;
result := BINARY_SOURCE;
end;
procedure TableBuilder.afterConstruction();
var
__languageLexer: ru.malik.elaborarer.avtoo.compiler.LanguageLexer;
__documentationLexer: ru.malik.elaborarer.avtoo.compiler.DocumentLexer;
begin
inherited afterConstruction();
__documentationLexer := createDocumentLexer();
if __documentationLexer = nil then __documentationLexer := ru.malik.elaborarer.avtoo.compiler.DocumentLexer.create();
fldDocumentationLexer := __documentationLexer;
__languageLexer := createLanguageLexer(__documentationLexer);
if __languageLexer = nil then __languageLexer := ru.malik.elaborarer.avtoo.compiler.LanguageLexer.create(__documentationLexer);
fldLanguageLexer := __languageLexer;
end;
procedure TableBuilder.beforeDestruction();
begin
fldLanguageLexer.free();
fldDocumentationLexer.free();
inherited beforeDestruction();
end;
procedure TableBuilder.compile();
label
case_public,
case_package,
case_private,
break_label0,
break_label1,
continue_label0;
var
hasRead: boolean;
hasWrite: boolean;
isPackage: boolean;
isAbstract: boolean;
hasSuperclass: boolean;
kind: int;
value: int;
index: int;
cindex: int;
lindex: int;
nindex: int;
pindex: int;
sindex: int;
tindex: int;
length: int;
__type: int;
llength: int;
nlength: int;
slength: int;
capacity: int;
position: int;
__offset: int;
attributes: int;
visibility: int;
readMember: int;
writeMember: int;
indexMember: int;
storedMember: int;
operatorKind: int;
argumentType: int;
argumentName: int;
parentPackage: int;
detailsPosition: int;
bindingPosition: int;
slengthOfLibrary: int;
slengthOfProject: int;
supertypePosition: int;
argumentsPosition: int;
visibilityPosition: int;
returnTypePosition: int;
declarationPosition: int;
documentationPosition: int;
implementationPosition: int;
__methodName: AnsiString;
specialSimpleName: AnsiString;
specialCanonicalName: AnsiString;
textSourcePath: UnicodeString;
tree: int_Array2d;
chars: uchar_Array1d;
positions: int_Array1d;
sources: Source_Array1d;
arguments: Local_Array1d;
__arrays: ClassType_Array1d;
__buffer: ClassType_Array1d;
__classes: ClassType_Array1d;
__libraries: Library_Array1d;
sourcesBuffer: Source_Array1d;
sourcesOfLibrary: Source_Array1d;
sourcesOfProject: Source_Array1d;
found: Member;
pack: Package;
owner: Package;
typeInt: &Type;
typeVoid: &Type;
typeBoolean: &Type;
element: TObject;
chunks: ChunkArray;
txtsource: TextSource;
binsource: BinarySource;
constants: ObjectVector;
factory: ConstantFactory;
declared: ClassTypeArray;
item: RequiredReflectItem;
returnTypeReference: &Type;
objectsHolder: ObjectVector;
conflictItem: RequiredReflectItem;
tbtsource: TableBuilderTextSource;
name: TableBuilderAnsiStringHolder;
supertypeHolder: TableBuilderClassTypeHolder;
universalHolder: TableBuilderOperatorAndTypeHolder;
enclosing: ru.malik.elaborarer.avtoo.lang.ClassType;
throwable: ru.malik.elaborarer.avtoo.lang.ClassType;
typeObject: ru.malik.elaborarer.avtoo.lang.ClassType;
typeStruct: ru.malik.elaborarer.avtoo.lang.ClassType;
supertypeReference: ru.malik.elaborarer.avtoo.lang.ClassType;
__field: Field;
__method: Method;
__library: &Library;
__project: &Library;
__operator: &Operator;
__property: &Property;
texception: TextSourceException;
bexception: BinarySourceException;
begin
{ -- предыдущие стадии -- }
inherited compile();
name := nil;
supertypeHolder := nil;
universalHolder := nil;
try
{ 2. Стадия чтения и анализа исходных кодов }
__libraries := libraries.clone();
llength := system.length(__libraries);
if llength <= 0 then begin
raise CompilerException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-specified.project'));
end;
slengthOfLibrary := 0;
sourcesOfLibrary := nil;
sourcesOfProject := nil;
__project := fldProject;
for lindex := 0 to llength - 1 do begin
__library := __libraries[lindex];
sources := __library.sources.clone();
slength := system.length(sources);
if __library = __project then begin
slengthOfProject := slength;
sourcesOfProject := sources;
end else
if sourcesOfLibrary = nil then begin
slengthOfLibrary := slength;
sourcesOfLibrary := Source_Array1d(&Array.newISimple1d(getBestArrayCapacity(slengthOfLibrary)));
&Array.copySimples(sources, 0, sourcesOfLibrary, 0, slengthOfLibrary);
end else begin
nlength := slengthOfLibrary + slength;
if system.length(sourcesOfLibrary) < nlength then begin
sourcesBuffer := Source_Array1d(&Array.newISimple1d(getBestArrayCapacity(nlength)));
&Array.copySimples(sourcesOfLibrary, 0, sourcesBuffer, 0, slengthOfLibrary);
sourcesOfLibrary := sourcesBuffer;
end;
&Array.copySimples(sources, 0, sourcesOfLibrary, slengthOfLibrary, slength);
slengthOfLibrary := nlength;
end;
for sindex := 0 to slength - 1 do begin
sources[sindex].parseInputStream();
end;
end;
if system.length(sourcesOfLibrary) <> slengthOfLibrary then begin
sourcesBuffer := Source_Array1d(&Array.newISimple1d(slengthOfLibrary));
&Array.copySimples(sourcesOfLibrary, 0, sourcesBuffer, 0, slengthOfLibrary);
sourcesOfLibrary := sourcesBuffer;
end;
sourcesBuffer := nil;
with CompilerParallelWorker.create(maxThreads) do try
objectsHolder := ObjectVector.create(false, ISimple_Array1d(sourcesOfLibrary), slengthOfLibrary);
try
targets := objectsHolder;
run(TableBuilderSourcesReader.create(self));
finally
objectsHolder.free();
end;
objectsHolder := ObjectVector.create(false, ISimple_Array1d(sourcesOfProject), slengthOfProject);
try
targets := objectsHolder;
run(TableBuilderSourcesLexer.create(languageLexer));
run(TableBuilderSourcesParser.create());
finally
objectsHolder.free();
objectsHolder := nil;
end;
finally
free();
end;
{ 3. Стадия поиска пакетов }
__libraries[0].createPackage(VIS_PUBLIC, '', nil, -1, -1);
for sindex := 0 to slengthOfLibrary - 1 do begin
binsource := BinarySource(Lang.cast(sourcesOfLibrary[sindex], BinarySource));
constants := binsource.readComponent(1) as ObjectVector;
chunks := binsource.chunks;
for cindex := 2 to chunks.getLength() - 2 do with chunks.readComponent(cindex) do if &type = CHUNK_PACK then begin
attributes := readUnsignedShort();
nindex := readInt();
binsource.writeComponent(cindex, binsource.parentLibrary.createPackage(attributes, (constants.readComponent(nindex) as CoUnicodeString).asAnsiString(), binsource, cindex, -1));
end;
end;
name := TableBuilderAnsiStringHolder.create();
for sindex := 0 to slengthOfProject - 1 do begin
txtsource := TextSource(Lang.cast(sourcesOfProject[sindex], TextSource));
if isPackageSourceFileName(txtsource.textSourcePath) then begin
position := 0;
visibility := VIS_PRIVATE;
{ документация }
documentationPosition := -1;
if txtsource.getLexemeKind(0) = L_DOC then begin
documentationPosition := 0;
position := 1;
end;
{ видимость }
case txtsource.getLexemeKind(position) of
VIS_PROTECTED: begin
visibility := VIS_PROTECTED;
inc(position);
end;
VIS_PRIVATE: begin
inc(position);
end;
VIS_PUBLIC,
VIS_PUBLISHED: begin
visibility := VIS_PUBLIC;
inc(position);
end;
end;
{ пакет }
if txtsource.getLexemeKind(position) <> VIS_PACKAGE then begin
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.package'));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
{ название }
inc(position);
declarationPosition := position;
position := parsePackageName(txtsource, position, name);
if txtsource.getLexemeKind(position) <> L_END then begin
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'extra.chars.source'));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
{ проверки }
specialCanonicalName := name.toString();
conflictItem := getPackage(specialCanonicalName, false);
if conflictItem <> nil then begin
texception := TextSourceException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'duplicate.package'), [
CoAnsiString.create(conflictItem.specialCanonicalName)
]));
texception.source := txtsource;
texception.position := declarationPosition;
raise texception;
end;
conflictItem := getPackage(specialCanonicalName, true);
if conflictItem <> nil then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'conflict.package-package'), [
CoAnsiString.create(conflictItem.specialCanonicalName)
]
));
texception.source := txtsource;
texception.position := declarationPosition;
raise texception;
end;
{ связывание пакета }
txtsource.owner := __project.createPackage(visibility, specialCanonicalName, txtsource, declarationPosition, documentationPosition);
name.clear();
end;
end;
for sindex := 0 to slengthOfProject - 1 do begin
txtsource := TextSource(Lang.cast(sourcesOfProject[sindex], TextSource));
if isTypeSourceFileName(txtsource.textSourcePath) then begin
{ секция пакета }
if txtsource.getLexemeKind(0) <> VIS_PACKAGE then begin
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.package'));
texception.source := txtsource;
texception.position := 0;
raise texception;
end;
position := parsePackageName(txtsource, 1, name);
if txtsource.getLexemeKind(position) <> SEMICOLON then begin
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.semicolon'));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
{ проверки }
specialCanonicalName := name.toString();
conflictItem := getPackage(specialCanonicalName, false);
if conflictItem <> nil then begin
if conflictItem.parentLibrary <> __project then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'duplicate.package.another-library'), [
CoAnsiString.create(conflictItem.specialCanonicalName)
]
));
texception.source := txtsource;
texception.position := 1;
raise texception;
end;
end else begin
conflictItem := getPackage(specialCanonicalName, true);
if conflictItem <> nil then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'conflict.package-package'), [
CoAnsiString.create(conflictItem.specialCanonicalName)
]
));
texception.source := txtsource;
texception.position := 1;
raise texception;
end;
conflictItem := __project.createPackage(VIS_PRIVATE, specialCanonicalName, nil, -1, -1);
end;
{ связывание пакета }
txtsource.owner := Package(conflictItem);
name.clear();
end;
end;
{ 4. Стадия поиска типов }
createPrimitiveTypes();
for sindex := 0 to slengthOfLibrary - 1 do begin
binsource := BinarySource(Lang.cast(sourcesOfLibrary[sindex], BinarySource));
constants := binsource.readComponent(1) as ObjectVector;
textSourcePath := '';
chunks := binsource.chunks;
for cindex := 2 to chunks.getLength() - 2 do with chunks.readComponent(cindex) do case &type of
CHUNK_SURC: begin
chars := &Array.newUChar1d(getLength());
readFully(chars);
textSourcePath := UnicodeString.create(chars);
end;
CHUNK_TYPE: begin
attributes := readUnsignedShort();
parentPackage := readInt();
nindex := readInt();
binsource.writeComponent(cindex, (constants.readComponent(parentPackage) as PackageElement).getItem().createClassType(
attributes, (constants.readComponent(nindex) as CoUnicodeString).asAnsiString(), binsource, cindex, -1, textSourcePath
));
end;
end;
end;
for sindex := 0 to slengthOfProject - 1 do begin
tbtsource := TableBuilderTextSource(Lang.cast(sourcesOfProject[sindex], TableBuilderTextSource));
txtsource := tbtsource;
if isTypeSourceFileName(txtsource.textSourcePath) then begin
owner := txtsource.owner;
tree := tbtsource.parsingTree;
for tindex := 1 to system.length(tree) - 1 do begin
attributes := 0;
position := tree[tindex][0];
{ документация }
documentationPosition := -1;
if txtsource.getLexemeKind(position) = L_DOC then begin
documentationPosition := position;
inc(position);
end;
{ видимость }
kind := txtsource.getLexemeKind(position);
visibilityPosition := position;
case kind of
VIS_PRIVATE,
VIS_PROTECTED: begin
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-visibility.type'));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
VIS_PACKAGE,
VIS_PUBLIC,
VIS_PUBLISHED: begin
attributes := attributes or kind;
inc(position);
end;
else
attributes := attributes or VIS_SOURCE;
end;
{ абстрактность }
bindingPosition := position;
case txtsource.getLexemeKind(position) of
DCL_ABSTRACT: begin
attributes := attributes or ATTR_ABSTRACT;
inc(position);
end;
DCL_FINAL: begin
attributes := attributes or ATTR_FINAL;
inc(position);
end;
end;
{ разновидность }
case txtsource.getLexemeKind(position) of
DCL_HELPER: begin
if (attributes and ATTR_ABSTRACT) <> 0 then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-modifiers.abstract.helper')
);
texception.source := txtsource;
texception.position := bindingPosition;
raise texception;
end;
attributes := attributes or (ATTR_SERVICE or ATTR_FINAL);
inc(position);
end;
DCL_STRUCT: begin
if (attributes and ATTR_ABSTRACT) <> 0 then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-modifiers.abstract.struct')
);
texception.source := txtsource;
texception.position := bindingPosition;
raise texception;
end;
attributes := attributes or ATTR_STRUCT;
inc(position);
end;
DCL_INTERFACE: begin
if (attributes and ATTR_FINAL) <> 0 then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-modifiers.final.interface')
);
texception.source := txtsource;
texception.position := bindingPosition;
raise texception;
end;
attributes := attributes or (ATTR_INTERFACE or ATTR_ABSTRACT);
inc(position);
end;
DCL_SERVICE: begin
if (attributes and ATTR_FINAL) <> 0 then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-modifiers.final.service')
);
texception.source := txtsource;
texception.position := bindingPosition;
raise texception;
end;
attributes := attributes or ATTR_SERVICE;
inc(position);
end;
DCL_CLASS: begin
inc(position);
end;
else
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.keyword.type'));
texception.source := txtsource;
texception.position := bindingPosition;
raise texception;
end;
{ название }
if txtsource.getLexemeKind(position) <> L_NAME then begin
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.name.type'));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
specialSimpleName := txtsource.getLexemeString(position).toUTF8();
specialCanonicalName := owner.specialCanonicalName;
{ проверки }
if
(attributes <> VIS_PUBLIC) and
(PACKNAME_LANG = specialCanonicalName) and
((TYPENAME_OBJECT = specialSimpleName) or (TYPENAME_STRUCT = specialSimpleName) or (TYPENAME_THROWABLE = specialSimpleName))
then begin
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-be.public-class'));
texception.source := txtsource;
texception.position := visibilityPosition;
raise texception;
end;
conflictItem := owner.getChildType(specialSimpleName, false);
if conflictItem <> nil then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'duplicate.name.type'), [
CoAnsiString.create(specialSimpleName)
]
));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
conflictItem := owner.getChildType(specialSimpleName, true);
if conflictItem <> nil then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'conflict.type-type'), [
CoAnsiString.create(conflictItem.specialSimpleName)
]
));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
conflictItem := getPackage(specialCanonicalName + '.' + specialSimpleName, false);
if conflictItem <> nil then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'conflict.type-package'), [
CoAnsiString.create(conflictItem.specialSimpleName)
]
));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
{ создание типа }
owner.createClassType(attributes, specialSimpleName, txtsource, position, documentationPosition, txtsource.textSourcePath);
end;
end;
end;
checkEssentialTypesPresence();
for sindex := 0 to slengthOfProject - 1 do begin
tbtsource := TableBuilderTextSource(Lang.cast(sourcesOfProject[sindex], TableBuilderTextSource));
txtsource := tbtsource;
if isTypeSourceFileName(txtsource.textSourcePath) then begin
position := tbtsource.parsingTree[0][0];
if position >= 0 then while txtsource.getLexemeKind(position) = DCL_IMPORT do begin
inc(position);
if txtsource.getLexemeKind(position) <> L_NAME then begin
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.name.package'));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
name.appendResultString(txtsource.getLexemeString(position).toUTF8());
inc(position);
if txtsource.getLexemeKind(position) <> PERIOD then begin
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.period'));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
isPackage := false;
repeat
inc(position);
case txtsource.getLexemeKind(position) of
O_SCAL_MUL: begin
inc(position);
if txtsource.getLexemeKind(position) <> SEMICOLON then begin
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.semicolon'));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
isPackage := true;
break;
end;
L_NAME: begin
name.appendResultString('.' + txtsource.getLexemeString(position).toUTF8());
end;
else
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.name-or-star'));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
inc(position);
case txtsource.getLexemeKind(position) of
PERIOD: ;
SEMICOLON: break;
else
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.period-or-semicolon'));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
until false;
specialCanonicalName := name.toString();
if isPackage then begin
pack := getPackage(specialCanonicalName);
item := pack;
if pack = nil then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-found.package'), [
CoAnsiString.create(specialCanonicalName)
]
));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
if txtsource.isImported(pack) then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'package.already.imported'), [
CoAnsiString.create(specialCanonicalName)
]
));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
if not item.isVisibleFrom(txtsource.declared.readComponent(0)) then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.package'), [
CoAnsiString.create(specialCanonicalName)
]
));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
end else begin
item := getClassType(specialCanonicalName);
if item = nil then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-found.type'), [
CoAnsiString.create(specialCanonicalName)
]
));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
specialSimpleName := item.specialSimpleName;
if txtsource.getImportedType(specialSimpleName) <> nil then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'type.already.imported'), [
CoAnsiString.create(specialSimpleName)
]
));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
if txtsource.getDeclaredType(specialSimpleName) <> nil then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'type.already.contained'), [
CoAnsiString.create(specialSimpleName)
]
));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
if not item.isVisibleFrom(txtsource.declared.readComponent(0)) then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.type'), [
CoAnsiString.create(specialCanonicalName)
]
));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
end;
txtsource.appendImported(item);
name.clear();
inc(position);
end;
end;
end;
typeObject := getClassType(PACKNAME_LANG + '.' + TYPENAME_OBJECT);
typeStruct := getClassType(PACKNAME_LANG + '.' + TYPENAME_STRUCT);
for sindex := 0 to slengthOfLibrary - 1 do begin
binsource := BinarySource(Lang.cast(sourcesOfLibrary[sindex], BinarySource));
constants := binsource.readComponent(1) as ObjectVector;
chunks := binsource.chunks;
for cindex := 2 to chunks.getLength() - 2 do with chunks.readComponent(cindex) do if &type = CHUNK_TYPE then begin
enclosing := binsource.readComponent(cindex) as ru.malik.elaborarer.avtoo.lang.ClassType;
nindex := readInt();
if enclosing.isHelper() then begin
enclosing.initHelperFor(getClassType((constants.readComponent(nindex) as CoUnicodeString).asAnsiString()), -1);
end else
if nindex > 0 then begin
enclosing.initSuperclass(getClassType((constants.readComponent(nindex) as CoUnicodeString).asAnsiString()), -1);
while available() > 0 do begin
nindex := readInt();
enclosing.appendSuperservice(getClassType((constants.readComponent(nindex) as CoUnicodeString).asAnsiString()), -1);
end;
end else
if enclosing.isStruct() then begin
enclosing.initSuperclass(typeStruct, -1);
end else
if enclosing <> typeObject then begin
enclosing.initSuperclass(typeObject, -1);
end;
end;
end;
supertypeHolder := TableBuilderClassTypeHolder.create();
for sindex := 0 to slengthOfProject - 1 do begin
txtsource := TextSource(Lang.cast(sourcesOfProject[sindex], TextSource));
declared := txtsource.declared;
for cindex := 0 to declared.getLength() - 1 do begin
enclosing := declared.readComponent(cindex);
position := enclosing.declarationPosition + 1;
case txtsource.getLexemeKind(position) of
COLON: begin
if enclosing.isHelper() then begin
supertypePosition := position + 1;
position := parseClassName(txtsource, supertypePosition, enclosing, supertypeHolder);
supertypeReference := supertypeHolder.resultClassType;
if supertypeReference.visibility < enclosing.visibility then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.lower-visibility.target-type'), [
CoAnsiString.create(enclosing.specialSimpleName)
]
));
texception.source := txtsource;
texception.position := supertypePosition;
raise texception;
end;
enclosing.initHelperFor(supertypeReference, supertypePosition);
end;
end;
PARENTH_OPENED: begin
if enclosing.isHelper() then begin
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.colon'));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
if enclosing = typeObject then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-have.supertypes'), [
CoAnsiString.create(PACKNAME_LANG + '.' + TYPENAME_OBJECT)
]
));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
hasSuperclass := false;
repeat
supertypePosition := position + 1;
position := parseClassName(txtsource, supertypePosition, enclosing, supertypeHolder);
supertypeReference := supertypeHolder.resultClassType;
if supertypeReference.visibility < enclosing.visibility then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.lower-visibility.supertype'), [
CoAnsiString.create(enclosing.specialSimpleName)
]
));
texception.source := txtsource;
texception.position := supertypePosition;
raise texception;
end;
if supertypeReference.isFinal() then begin
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.final.supertype'));
texception.source := txtsource;
texception.position := supertypePosition;
raise texception;
end;
if supertypeReference.isService() then begin
if enclosing.isStruct() then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-be.struct-superclass'), [
CoAnsiString.create(PACKNAME_LANG + '.' + TYPENAME_STRUCT)
]
));
texception.source := txtsource;
texception.position := supertypePosition;
raise texception;
end;
if enclosing.isSuperservice(supertypeReference) then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'duplicate.supertype'), [
CoAnsiString.create(supertypeReference.specialCanonicalName)
]
));
texception.source := txtsource;
texception.position := supertypePosition;
raise texception;
end;
if not hasSuperclass then begin
hasSuperclass := true;
enclosing.initSuperclass(typeObject, -1);
end;
enclosing.appendSuperservice(supertypeReference, supertypePosition);
end else
if supertypeReference.isStruct() then begin
if not enclosing.isStruct() then begin
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-be.class-supertype'));
texception.source := txtsource;
texception.position := supertypePosition;
raise texception;
end;
if hasSuperclass then begin
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-have.one-supertype'));
texception.source := txtsource;
texception.position := supertypePosition;
raise texception;
end;
hasSuperclass := true;
enclosing.initSuperclass(supertypeReference, supertypePosition);
end else
{ if supertypeReference.isClass() then } begin
if enclosing.isStruct() and (supertypeReference <> typeStruct) then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-be.struct-superclass'), [
CoAnsiString.create(PACKNAME_LANG + '.' + TYPENAME_STRUCT)
]
));
texception.source := txtsource;
texception.position := supertypePosition;
raise texception;
end;
if hasSuperclass then begin
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-have.one-superclass'));
texception.source := txtsource;
texception.position := supertypePosition;
raise texception;
end;
hasSuperclass := true;
enclosing.initSuperclass(supertypeReference, supertypePosition);
end;
case txtsource.getLexemeKind(position) of
COMMA: ;
PARENTH_CLOSED: begin
inc(position);
break;
end;
else
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.comma-or-closed-parenth'));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
until false;
end;
else
if enclosing.isHelper() then begin
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.colon'));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
if enclosing.isStruct() then begin
enclosing.initSuperclass(typeStruct, -1);
end else
if enclosing <> typeObject then begin
enclosing.initSuperclass(typeObject, -1);
end;
end;
if txtsource.getLexemeKind(position) <> CURLY_OPENED then begin
texception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-curly'));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
end;
end;
createArrayTypes();
__classes := classes.clone();
__arrays := ClassType_Array1d(arrays.clone());
__buffer := ClassType_Array1d(&Array.newTObject1d(system.length(__classes) + system.length(__arrays)));
checkSuperclasses(__classes, __buffer);
checkSuperclasses(__arrays, __buffer);
__buffer := nil;
initSubtypes();
appendImpliedSuperservices(__classes);
appendImpliedSuperservices(__arrays);
checkSuperservices(__classes);
checkSuperservices(__arrays);
if llength > 1 then begin
__classes := __project.classes.clone();
__arrays := nil;
end;
sortTypes();
{ 5. Стадия поиска членов }
typeInt := getPrimitiveType(TYP_INT);
typeVoid := getPrimitiveType(TYP_VOID);
typeBoolean := getPrimitiveType(TYP_BOOLEAN);
arguments := Local_Array1d(&Array.newTObject1d(LIMIT_ARGUMENTS_LENGTH));
factory := getConstantFactory();
for sindex := 0 to slengthOfLibrary - 1 do begin
binsource := BinarySource(Lang.cast(sourcesOfLibrary[sindex], BinarySource));
constants := binsource.readComponent(1) as ObjectVector;
chunks := binsource.chunks;
enclosing := nil;
for cindex := 2 to chunks.getLength() - 2 do with chunks.readComponent(cindex) do case &type of
CHUNK_CFLD: begin
attributes := readUnsignedShort();
__type := readInt();
nindex := readInt();
value := -1;
if available() > 0 then value := readInt();
__field := enclosing.createClassField(
attributes, (constants.readComponent(__type) as TypeElement).getItem(), (constants.readComponent(nindex) as CoUnicodeString).asAnsiString(), cindex, -1
);
binsource.writeComponent(cindex, __field);
if value < 0 then begin
__field.closeComputing();
continue;
end;
element := constants.readComponent(value);
if element is RecompilableElement then element := RecompilableElement(element).getItem();
__field.openComputing();
try
__field.setComputedValue(factory.createFrom(element));
finally
__field.closeComputing();
end;
end;
CHUNK_SFLD: begin
attributes := readUnsignedShort();
__type := readInt();
nindex := readInt();
capacity := readInt();
__offset := readInt();
binsource.writeComponent(cindex, enclosing.createStructField(
__offset, (constants.readComponent(__type) as TypeElement).getItem(), capacity, (constants.readComponent(nindex) as CoUnicodeString).asAnsiString(), cindex, -1
));
end;
CHUNK_METH: begin
attributes := readUnsignedShort();
__type := readInt();
nindex := readInt();
length := readUnsignedShort();
if length > LIMIT_ARGUMENTS_LENGTH then begin
bexception := BinarySourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'too-many.arguments'));
bexception.source := binsource;
bexception.offset := dataOffsetToSourceOffset(position);
raise bexception;
end;
__methodName := (constants.readComponent(nindex) as CoUnicodeString).asAnsiString();
&Array.fillObjects(arguments, 0, LIMIT_ARGUMENTS_LENGTH, nil);
try
if SPECNAME_CLASS_INIT <> __methodName then for index := 0 to length - 1 do begin
argumentType := readInt();
argumentName := readInt();
arguments[index] := createLocal(
false, (constants.readComponent(argumentType) as TypeElement).getItem(), (constants.readComponent(argumentName) as CoUnicodeString).asAnsiString(), nil, nil, -1
);
end;
if SPECNAME_CLASS_INIT = __methodName then begin
__method := enclosing.createStaticBlock(attributes, cindex, -1);
end else
if SPECNAME_INST_INIT = __methodName then begin
__method := enclosing.createConstructor(attributes, packArguments(arguments), cindex, -1);
end else begin
__method := enclosing.createMethod(attributes, (constants.readComponent(__type) as TypeElement).getItem(), __methodName, packArguments(arguments), cindex, -1);
end;
except
for index := LIMIT_ARGUMENTS_LENGTH - 1 downto 0 do arguments[index].free();
raise;
end;
binsource.writeComponent(cindex, __method);
while available() > 0 do begin
nindex := readInt();
throwable := getClassType((constants.readComponent(nindex) as CoUnicodeString).asAnsiString());
if
(throwable <> nil) and
(throwable.specialCanonicalName <> (PACKNAME_LANG + '.' + TYPENAME_THROWABLE)) and
not throwable.isSuperclass(PACKNAME_LANG + '.' + TYPENAME_THROWABLE)
then begin
bexception := BinarySourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'type.not-suitable.exception'), [
CoAnsiString.create(throwable.specialCanonicalName), CoAnsiString.create(PACKNAME_LANG + '.' + TYPENAME_THROWABLE)
]
));
bexception.source := binsource;
bexception.offset := dataOffsetToSourceOffset(position);
raise bexception;
end;
__method.appendThrowable(throwable, -1);
end;
end;
CHUNK_OPER: begin
attributes := readUnsignedShort();
__type := readInt();
nindex := readInt();
length := readUnsignedShort();
if length > LIMIT_ARGUMENTS_LENGTH then begin
bexception := BinarySourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'too-many.arguments'));
bexception.source := binsource;
bexception.offset := dataOffsetToSourceOffset(position);
raise bexception;
end;
&Array.fillObjects(arguments, 0, LIMIT_ARGUMENTS_LENGTH, nil);
try
for index := 0 to length - 1 do begin
argumentType := readInt();
argumentName := readInt();
arguments[index] := createLocal(
false, (constants.readComponent(argumentType) as TypeElement).getItem(), (constants.readComponent(argumentName) as CoUnicodeString).asAnsiString(), nil, nil, -1
);
end;
operatorKind := &Operator.specialSimpleNameToKind((constants.readComponent(nindex) as CoUnicodeString).asAnsiString());
__operator := enclosing.createOperator(attributes, (constants.readComponent(__type) as TypeElement).getItem(), operatorKind, packArguments(arguments), cindex, -1);
except
for index := LIMIT_ARGUMENTS_LENGTH - 1 downto 0 do arguments[index].free();
raise;
end;
binsource.writeComponent(cindex, __operator);
end;
CHUNK_PROP: begin
attributes := readUnsignedShort();
__type := readInt();
nindex := readInt();
binsource.writeComponent(cindex, enclosing.createProperty(
attributes, (constants.readComponent(__type) as TypeElement).getItem(), (constants.readComponent(nindex) as CoUnicodeString).asAnsiString(), cindex, -1
));
end;
CHUNK_TYPE: begin
enclosing := binsource.readComponent(cindex) as ru.malik.elaborarer.avtoo.lang.ClassType;
end;
end;
end;
for sindex := 0 to slengthOfLibrary - 1 do begin
binsource := BinarySource(Lang.cast(sourcesOfLibrary[sindex], BinarySource));
constants := binsource.readComponent(1) as ObjectVector;
chunks := binsource.chunks;
for cindex := 2 to chunks.getLength() - 2 do with chunks.readComponent(cindex) do if &type = CHUNK_PROP then begin
indexMember := readInt();
storedMember := readInt();
readMember := readInt();
writeMember := readInt();
__property := binsource.readComponent(cindex) as &Property;
if indexMember > 0 then __property.indexMember := (constants.readComponent(indexMember) as TypedMemberElement).getTypedMember();
if storedMember > 0 then __property.storedMember := (constants.readComponent(storedMember) as TypedMemberElement).getTypedMember();
if readMember > 0 then __property.readMember := (constants.readComponent(readMember) as TypedMemberElement).getTypedMember();
if writeMember > 0 then __property.writeMember := (constants.readComponent(writeMember) as TypedMemberElement).getTypedMember();
end;
end;
universalHolder := TableBuilderOperatorAndTypeHolder.create();
for sindex := 0 to slengthOfProject - 1 do begin
tbtsource := TableBuilderTextSource(Lang.cast(sourcesOfProject[sindex], TableBuilderTextSource));
txtsource := tbtsource;
if not isTypeSourceFileName(txtsource.textSourcePath) then continue;
declared := txtsource.declared;
cindex := 0;
tree := tbtsource.parsingTree;
for tindex := 1 to system.length(tree) - 1 do begin
begin
enclosing := declared.readComponent(cindex);
if enclosing.isStruct() then begin
parseAllocatableMembers(txtsource, tree[tindex][1], enclosing, enclosing);
goto continue_label0;
end;
positions := tree[tindex];
for pindex := 1 to system.length(positions) - 2 do begin
position := positions[pindex];
kind := txtsource.getLexemeKind(position);
{ документация }
documentationPosition := -1;
if kind = L_DOC then begin
documentationPosition := position;
inc(position);
kind := txtsource.getLexemeKind(position);
end;
{ атрибуты }
{ видимость }
begin
case kind of
VIS_PACKAGE: goto case_package;
VIS_PRIVATE: goto case_private;
VIS_PROTECTED,
VIS_PUBLISHED,
VIS_PUBLIC: goto case_public;
else
if enclosing.isInterface() or enclosing.isHelper() then begin
attributes := VIS_PUBLIC;
end else begin
attributes := VIS_SOURCE;
end;
goto break_label0;
end;
case_package: begin
if enclosing.isHelper() and (enclosing.getHelperForType().parentPackage <> enclosing.parentPackage) then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-visibility.helper-members')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
{ падение через }
end;
case_private: begin
if enclosing.isInterface() then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-visibility.interface-members')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
{ падение через }
end;
case_public: begin
attributes := kind;
inc(position);
kind := txtsource.getLexemeKind(position);
end;
end;
break_label0:
{ связывание: static final, static, final, abstract }
bindingPosition := position;
case kind of
DCL_STATIC: begin
attributes := attributes or ATTR_STATIC;
inc(position);
kind := txtsource.getLexemeKind(position);
if kind = DCL_FINAL then begin
attributes := attributes or ATTR_FINAL;
inc(position);
kind := txtsource.getLexemeKind(position);
end else
if enclosing.isInterface() then begin
attributes := attributes or ATTR_FINAL;
end;
end;
DCL_FINAL: begin
attributes := attributes or ATTR_FINAL;
if enclosing.isService() then begin
attributes := attributes or ATTR_STATIC;
end;
inc(position);
kind := txtsource.getLexemeKind(position);
end;
DCL_ABSTRACT: begin
if (attributes <= VIS_PACKAGE) and enclosing.isService() then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-modifiers.abstract.hidden-members')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
if (attributes <= VIS_PRIVATE) and enclosing.isClass() then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-modifiers.abstract.private-members')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
if enclosing.isHelper() then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-modifiers.abstract.helper-members')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
attributes := attributes or ATTR_ABSTRACT;
inc(position);
kind := txtsource.getLexemeKind(position);
end;
end;
{ детали реализации: native interrupt, native, interrupt native, interrupt, synchronized }
detailsPosition := position;
case kind of
DCL_NATIVE: begin
if enclosing.isInterface() then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-implementation-details.interface-members')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
if (attributes and ATTR_ABSTRACT) <> 0 then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-implementation-details.abstracts')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
attributes := attributes or ATTR_NATIVE;
inc(position);
kind := txtsource.getLexemeKind(position);
if kind = DCL_INTERRUPT then begin
if (attributes and ATTR_STATIC) = 0 then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.static.interrupt')
);
texception.source := txtsource;
texception.position := bindingPosition;
raise texception;
end;
attributes := attributes or ATTR_INTERRUPT;
inc(position);
kind := txtsource.getLexemeKind(position);
end;
end;
DCL_INTERRUPT: begin
if enclosing.isInterface() then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-implementation-details.interface-members')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
if (attributes and ATTR_ABSTRACT) <> 0 then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-implementation-details.abstracts')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
if (attributes and ATTR_STATIC) = 0 then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.static.interrupt')
);
texception.source := txtsource;
texception.position := bindingPosition;
raise texception;
end;
attributes := attributes or ATTR_INTERRUPT;
inc(position);
kind := txtsource.getLexemeKind(position);
if kind = DCL_NATIVE then begin
attributes := attributes or ATTR_NATIVE;
inc(position);
kind := txtsource.getLexemeKind(position);
end;
end;
DCL_SYNCHRONIZED: begin
if enclosing.isInterface() then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-implementation-details.interface-members')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
if (attributes and ATTR_ABSTRACT) <> 0 then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-implementation-details.abstracts')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
attributes := attributes or ATTR_SYNCHRONIZED;
inc(position);
kind := txtsource.getLexemeKind(position);
end;
end;
{ члены типов }
case kind of
CURLY_OPENED: begin
{ метод инициализации типа (статичный блок) }
if (attributes and ATTR_STATIC) = 0 then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.static.static-block')
);
texception.source := txtsource;
texception.position := bindingPosition;
raise texception;
end;
if (attributes and (ATTR_NATIVE or ATTR_INTERRUPT or ATTR_SYNCHRONIZED)) <> 0 then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-implementation-details.static-blocks')
);
texception.source := txtsource;
texception.position := detailsPosition;
raise texception;
end;
if enclosing.getStaticBlock() <> nil then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'duplicate.static-block'), [
CoAnsiString.create(enclosing.specialSimpleName)
]
));
texception.source := txtsource;
texception.position := position;
raise texception;
end;
enclosing.createStaticBlock(attributes, position, documentationPosition).implementationPosition := position;
continue;
end;
PARENTH_OPENED: begin
{ метод инициализации объекта (конструктор) }
if not enclosing.isClass() then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-be-used.constructors')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
if (attributes and (ATTR_STATIC or ATTR_FINAL or ATTR_ABSTRACT)) <> 0 then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-modifiers.binding.constructors')
);
texception.source := txtsource;
texception.position := bindingPosition;
raise texception;
end;
if (attributes and (ATTR_NATIVE or ATTR_INTERRUPT or ATTR_SYNCHRONIZED)) <> 0 then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-implementation-details.constructors')
);
texception.source := txtsource;
texception.position := detailsPosition;
raise texception;
end;
declarationPosition := position;
&Array.fillObjects(arguments, 0, LIMIT_ARGUMENTS_LENGTH, nil);
try
position := parseArgumentsClause(txtsource, position + 1, enclosing, arguments);
if enclosing.getChildCallable(SPECNAME_INST_INIT, toTypedItemArray(arguments)) <> nil then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'duplicate.constructor'), [
CoAnsiString.create(enclosing.specialSimpleName)
]
));
texception.source := txtsource;
texception.position := declarationPosition;
raise texception;
end;
__method := enclosing.createConstructor(attributes, packArguments(arguments), declarationPosition, documentationPosition);
except
for index := LIMIT_ARGUMENTS_LENGTH - 1 downto 0 do arguments[index].free();
raise;
end;
if txtsource.getLexemeKind(position) = DCL_THROWS then position := parseThrowsClause(txtsource, position + 1, enclosing, __method);
__method.implementationPosition := position;
continue;
end;
end;
returnTypePosition := position;
declarationPosition := parseTypeName(txtsource, position, enclosing, universalHolder);
returnTypeReference := universalHolder.resultType;
position := declarationPosition;
if ((attributes and ATTR_INTERRUPT) <> 0) and not returnTypeReference.isVoid() then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'type.required.interrupt')
);
texception.source := txtsource;
texception.position := returnTypePosition;
raise texception;
end;
case txtsource.getLexemeKind(position) of
L_NAME: ;
DCL_OPERATOR: begin
{ оператор }
if (attributes and ATTR_STATIC) <> 0 then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-modifiers.static.operators')
);
texception.source := txtsource;
texception.position := bindingPosition;
raise texception;
end;
if enclosing.isInterface() then begin
attributes := attributes or ATTR_ABSTRACT;
end;
argumentsPosition := parseOperator(txtsource, position + 1, universalHolder);
kind := universalHolder.resultKind;
position := argumentsPosition;
if txtsource.getLexemeKind(position) <> PARENTH_OPENED then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-parenth')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
&Array.fillObjects(arguments, 0, LIMIT_ARGUMENTS_LENGTH, nil);
try
position := parseArgumentsClause(txtsource, position + 1, enclosing, arguments);
length := &Array.indexOf(nil, arguments, 0, 0);
if length < 0 then length := LIMIT_ARGUMENTS_LENGTH;
if length <= 0 then case kind of
O_SCAL_ADD:
kind := O_SCAL_POS;
O_SCAL_SUB:
kind := O_SCAL_NEG;
O_VECT_ADD:
kind := O_VECT_POS;
O_VECT_SUB:
kind := O_VECT_NEG;
end;
case kind of
WRITE_COMPONENT: begin
if not returnTypeReference.isVoid() then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'operator.return-void'), [
CoAnsiString.create(&Operator.kindToSymbol(kind))
]
));
texception.source := txtsource;
texception.position := returnTypePosition;
raise texception;
end;
if length <> 2 then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'operator.arguments.2'), [
CoAnsiString.create(&Operator.kindToSymbol(kind))
]
));
texception.source := txtsource;
texception.position := argumentsPosition;
raise texception;
end;
end;
READ_COMPONENT,
O_BIT_AND,
O_BIT_OR,
O_BIT_XOR,
O_SCAL_MUL,
O_SCAL_DIV,
O_SCAL_DIVU,
O_SCAL_REM,
O_SCAL_REMU,
O_SCAL_ADD,
O_SCAL_SUB,
O_SCAL_SHR,
O_SCAL_SHRU,
O_SCAL_SHL,
O_VECT_MUL,
O_VECT_DIV,
O_VECT_ADD,
O_VECT_SUB,
O_VECT_SHR,
O_VECT_SHRU,
O_VECT_SHL,
O_VECT_GT,
O_VECT_GE,
O_VECT_LT,
O_VECT_LE,
O_VECT_EQ,
O_VECT_NE,
O_VECT_HMUL,
O_VECT_SADD,
O_VECT_SSUB,
O_VECT_HMULU,
O_VECT_SADDU,
O_VECT_SSUBU,
R_BIT_AND,
R_BIT_OR,
R_BIT_XOR,
R_SCAL_MUL,
R_SCAL_DIV,
R_SCAL_DIVU,
R_SCAL_REM,
R_SCAL_REMU,
R_SCAL_ADD,
R_SCAL_SUB,
R_SCAL_SHR,
R_SCAL_SHRU,
R_SCAL_SHL,
R_VECT_MUL,
R_VECT_DIV,
R_VECT_ADD,
R_VECT_SUB,
R_VECT_SHR,
R_VECT_SHRU,
R_VECT_SHL,
R_VECT_GT,
R_VECT_GE,
R_VECT_LT,
R_VECT_LE,
R_VECT_EQ,
R_VECT_NE,
R_VECT_HMUL,
R_VECT_SADD,
R_VECT_SSUB,
R_VECT_HMULU,
R_VECT_SADDU,
R_VECT_SSUBU: begin
if returnTypeReference.isVoid() then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'operator.return-type'), [
CoAnsiString.create(&Operator.kindToSymbol(kind))
]
));
texception.source := txtsource;
texception.position := returnTypePosition;
raise texception;
end;
if length <> 1 then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'operator.arguments.1'), [
CoAnsiString.create(&Operator.kindToSymbol(kind))
]
));
texception.source := txtsource;
texception.position := argumentsPosition;
raise texception;
end;
end;
O_SCAL_GT,
O_SCAL_GE,
O_SCAL_LT,
O_SCAL_LE,
R_SCAL_GT,
R_SCAL_GE,
R_SCAL_LT,
R_SCAL_LE: begin
if not returnTypeReference.isBoolean() then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'operator.return-boolean'), [
CoAnsiString.create(&Operator.kindToSymbol(kind))
]
));
texception.source := txtsource;
texception.position := returnTypePosition;
raise texception;
end;
if length <> 1 then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'operator.arguments.1'), [
CoAnsiString.create(&Operator.kindToSymbol(kind))
]
));
texception.source := txtsource;
texception.position := argumentsPosition;
raise texception;
end;
end;
O_BIT_NOT,
O_SCAL_POS,
O_SCAL_NEG,
O_VECT_POS,
O_VECT_NEG,
O_VECT_LUP,
O_VECT_UUP,
O_VECT_PCK: begin
if returnTypeReference.isVoid() then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'operator.return-type'), [
CoAnsiString.create(&Operator.kindToSymbol(kind))
]
));
texception.source := txtsource;
texception.position := returnTypePosition;
raise texception;
end;
if length > 0 then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'operator.arguments.0'), [
CoAnsiString.create(&Operator.kindToSymbol(kind))
]
));
texception.source := txtsource;
texception.position := argumentsPosition;
raise texception;
end;
end;
end;
if enclosing.getChildCallable(&Operator.kindToSpecialSimpleName(kind), toTypedItemArray(arguments)) <> nil then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'duplicate.operator'), [
CoAnsiString.create(enclosing.specialSimpleName), CoAnsiString.create(&Operator.kindToSymbol(kind))
]
));
texception.source := txtsource;
texception.position := declarationPosition;
raise texception;
end;
__operator := enclosing.createOperator(attributes, returnTypeReference, kind, packArguments(arguments), declarationPosition, documentationPosition);
except
for index := LIMIT_ARGUMENTS_LENGTH - 1 downto 0 do arguments[index].free();
raise;
end;
__operator.implementationPosition := position;
continue;
end;
else
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.name.member')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
specialSimpleName := txtsource.getLexemeString(position).toUTF8();
inc(position);
case txtsource.getLexemeKind(position) of
PARENTH_OPENED: begin
{ метод }
if enclosing.isInterface() then begin
if (attributes and (ATTR_STATIC or ATTR_FINAL)) <> 0 then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-modifiers.static-final.interface-methods')
);
texception.source := txtsource;
texception.position := bindingPosition;
raise texception;
end;
attributes := attributes or ATTR_ABSTRACT;
end;
found := enclosing.getChildMember(specialSimpleName);
if (found <> nil) and ((attributes and ATTR_INTERRUPT) <> 0) then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'duplicate.interrupt'), [
CoAnsiString.create(enclosing.specialSimpleName), CoAnsiString.create(specialSimpleName)
]
));
texception.source := txtsource;
texception.position := declarationPosition;
raise texception;
end;
if found is Fieldoid then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'duplicate.member.fieldoid'), [
CoAnsiString.create(enclosing.specialSimpleName), CoAnsiString.create(specialSimpleName)
]
));
texception.source := txtsource;
texception.position := declarationPosition;
raise texception;
end;
&Array.fillObjects(arguments, 0, LIMIT_ARGUMENTS_LENGTH, nil);
try
position := parseArgumentsClause(txtsource, position + 1, enclosing, arguments);
if enclosing.getChildCallable(specialSimpleName, toTypedItemArray(arguments)) <> nil then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'duplicate.method'), [
CoAnsiString.create(enclosing.specialSimpleName), CoAnsiString.create(specialSimpleName)
]
));
texception.source := txtsource;
texception.position := declarationPosition;
raise texception;
end;
__method := enclosing.createMethod(attributes, returnTypeReference, specialSimpleName, packArguments(arguments), declarationPosition, documentationPosition);
except
for index := LIMIT_ARGUMENTS_LENGTH - 1 downto 0 do arguments[index].free();
raise;
end;
if txtsource.getLexemeKind(position) = DCL_THROWS then begin
if (attributes and ATTR_INTERRUPT) <> 0 then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-throws.interrupt')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
position := parseThrowsClause(txtsource, position + 1, enclosing, __method);
end;
__method.implementationPosition := position;
end;
CURLY_OPENED: begin
{ свойство }
if (attributes and ATTR_STATIC) <> 0 then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-modifiers.static.properties')
);
texception.source := txtsource;
texception.position := bindingPosition;
raise texception;
end;
if (attributes and (ATTR_NATIVE or ATTR_INTERRUPT or ATTR_SYNCHRONIZED)) <> 0 then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-implementation-details.properties')
);
texception.source := txtsource;
texception.position := detailsPosition;
raise texception;
end;
if returnTypeReference.isVoid() then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'type.not-suitable.property'), [
CoObject.create(returnTypeReference)
]
));
texception.source := txtsource;
texception.position := returnTypePosition;
raise texception;
end;
if enclosing.getChildMember(specialSimpleName) <> nil then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'duplicate.member'), [
CoAnsiString.create(enclosing.specialSimpleName), CoAnsiString.create(specialSimpleName)
]
));
texception.source := txtsource;
texception.position := declarationPosition;
raise texception;
end;
if enclosing.isInterface() then begin
attributes := attributes or ATTR_ABSTRACT;
end;
enclosing.createProperty(attributes, returnTypeReference, specialSimpleName, declarationPosition, documentationPosition).implementationPosition := position;
implementationPosition := position;
isAbstract := (attributes and ATTR_ABSTRACT) <> 0;
hasWrite := false;
hasRead := false;
attributes := attributes or ATTR_SYNTHETIC;
inc(position);
kind := txtsource.getLexemeKind(position);
begin
{ index }
if (kind = L_NAME) and (MEMBER_SUFFIX_INDEX = txtsource.getLexemeString(position).toUTF8()) then begin
if isAbstract then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-specifiers.index')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
inc(position);
if txtsource.getLexemeKind(position) <> EQUAL then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.equals')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
inc(position);
enclosing.createMethod(attributes, typeInt, specialSimpleName + ('.' + MEMBER_SUFFIX_INDEX), nil, -1, -1).implementationPosition := position;
position := skipPropertySpecifier(txtsource, position);
kind := txtsource.getLexemeKind(position);
if kind <> COMMA then goto break_label1;
inc(position);
kind := txtsource.getLexemeKind(position);
end;
{ read }
if (kind = L_NAME) and (MEMBER_SUFFIX_READ = txtsource.getLexemeString(position).toUTF8()) then begin
hasRead := true;
if isAbstract then begin
enclosing.createMethod(attributes, returnTypeReference, specialSimpleName + ('.' + MEMBER_SUFFIX_READ), nil, -1, -1);
inc(position);
end else begin
inc(position);
if txtsource.getLexemeKind(position) <> EQUAL then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.equals')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
inc(position);
enclosing.createMethod(attributes, returnTypeReference, specialSimpleName + ('.' + MEMBER_SUFFIX_READ), nil, -1, -1).implementationPosition := position;
position := skipPropertySpecifier(txtsource, position);
end;
kind := txtsource.getLexemeKind(position);
if kind <> COMMA then goto break_label1;
inc(position);
kind := txtsource.getLexemeKind(position);
end;
{ write }
if (kind = L_NAME) and (MEMBER_SUFFIX_WRITE = txtsource.getLexemeString(position).toUTF8()) then begin
hasWrite := true;
if isAbstract then begin
enclosing.createMethod(attributes, typeVoid, specialSimpleName + ('.' + MEMBER_SUFFIX_WRITE), [
createLocal(true, returnTypeReference, SPECNAME_VALUE, nil, txtsource, declarationPosition)
], -1, -1);
inc(position);
end else begin
inc(position);
if txtsource.getLexemeKind(position) <> EQUAL then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.equals')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
inc(position);
enclosing.createMethod(attributes, typeVoid, specialSimpleName + ('.' + MEMBER_SUFFIX_WRITE), [
createLocal(true, returnTypeReference, SPECNAME_VALUE, nil, txtsource, declarationPosition)
], -1, -1).implementationPosition := position;
position := skipPropertySpecifier(txtsource, position);
end;
kind := txtsource.getLexemeKind(position);
if kind <> COMMA then goto break_label1;
inc(position);
kind := txtsource.getLexemeKind(position);
end;
{ stored }
if (kind = L_NAME) and (MEMBER_SUFFIX_STORED = txtsource.getLexemeString(position).toUTF8()) then begin
if isAbstract then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-specifiers.stored')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
inc(position);
if txtsource.getLexemeKind(position) <> EQUAL then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.equals')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
inc(position);
enclosing.createMethod(attributes, typeBoolean, specialSimpleName + ('.' + MEMBER_SUFFIX_STORED), nil, -1, -1).implementationPosition := position;
position := skipPropertySpecifier(txtsource, position);
kind := txtsource.getLexemeKind(position);
end;
end;
break_label1:
if kind <> CURLY_CLOSED then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-curly')
);
texception.source := txtsource;
texception.position := position;
raise texception;
end;
if not hasRead and not hasWrite then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.property-specifier.read-or-write')
);
texception.source := txtsource;
texception.position := implementationPosition;
raise texception;
end;
end;
else
{ поле }
if (attributes and ATTR_ABSTRACT) <> 0 then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-modifiers.abstract.fields')
);
texception.source := txtsource;
texception.position := bindingPosition;
raise texception;
end;
if (attributes and (ATTR_NATIVE or ATTR_INTERRUPT or ATTR_SYNCHRONIZED)) <> 0 then begin
texception := TextSourceException.create(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unsupported-implementation-details.fields')
);
texception.source := txtsource;
texception.position := detailsPosition;
raise texception;
end;
if returnTypeReference.isVoid() then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'type.not-suitable.field'), [
CoObject.create(returnTypeReference)
]
));
texception.source := txtsource;
texception.position := returnTypePosition;
raise texception;
end;
if enclosing.getChildMember(specialSimpleName) <> nil then begin
texception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'duplicate.member'), [
CoAnsiString.create(enclosing.specialSimpleName), CoAnsiString.create(specialSimpleName)
]
));
texception.source := txtsource;
texception.position := declarationPosition;
raise texception;
end;
if enclosing.isService() then begin
if enclosing.isInterface() then begin
attributes := attributes or (ATTR_STATIC or ATTR_FINAL);
end else begin
attributes := attributes or ATTR_STATIC;
end;
end;
enclosing.createClassField(attributes, returnTypeReference, specialSimpleName, declarationPosition, documentationPosition).implementationPosition := position;
end;
end;
end;
continue_label0:
inc(cindex);
end;
end;
createMembersForArrayTypes();
appendImpliedMembers(__classes);
appendImpliedMembers(__arrays);
checkMembers(__classes);
checkMembers(__arrays);
finally
name.free();
supertypeHolder.free();
universalHolder.free();
end;
end;
procedure TableBuilder.clear();
begin
fldProject := nil;
inherited clear();
end;
function TableBuilder.createLibrary(fileSystem: FileSystem; const directoryPath: UnicodeString; application: boolean): &Library;
var
__library: &Library;
begin
__library := inherited createLibrary(fileSystem, directoryPath, application);
fldProject := __library;
result := __library;
end;
{%endregion}
{%region ImmediateBuilder }
class procedure ImmediateBuilder.requiresValue(value: Node);
var
__type: &Type;
__callable: Callable;
begin
__type := value.&type;
if (__type = nil) or __type.isVoid() then case value.instruction of
STORE_LOCAL,
STORE_STATIC: begin
__type := (value.operand1 as TypedItem).&type;
value.&type := __type;
value.parentCode.createAndAppendNode(value).setData(-1, nil, DUP1, __type);
end;
WRITE_FIELD,
WRITE_SPECIAL,
WRITE_PROPERTY: begin
__type := (value.operand1 as TypedItem).&type;
value.&type := __type;
value.parentCode.createAndAppendNode(value).setData(-1, nil, DUP1X1, __type);
end;
WRITE_COMPONENT: begin
__type := value.operand1 as &Type;
value.&type := __type;
value.parentCode.createAndAppendNode(value).setData(-1, nil, DUP1X2, __type);
end;
INVOKE_SERVICE,
INVOKE_SPECIAL,
INVOKE_VIRTUAL: begin
__callable := value.operand1 as Callable;
if (__callable is &Operator) and (&Operator(__callable).kind = WRITE_COMPONENT) then begin
__type := __callable.arguments.readComponent(1).&type;
value.&type := __type;
value.parentCode.createAndAppendNode(value).setData(-1, nil, DUP1X2, __type);
end;
end;
end;
end;
class procedure ImmediateBuilder.defineAttainability(const attainability: byte_Array1d; __code: Code; length: int);
var
added: boolean;
order: int;
cindex: int;
jindex: int;
instruction: int;
__node: Node;
target: Node;
begin
added := false;
cindex := 0;
repeat
__node := __code.readComponent(cindex);
instruction := __node.instruction;
if
__node.persistent and (instruction <> FCT_BEGIN) or
(instruction = METHOD_ENTER) or (instruction >= EXCEPT_ENTER) and (instruction <= EXCEPT_LEAVE) or
(attainability[cindex] <> 0)
then begin
attainability[cindex] := -1;
for jindex := __node.getJumpCasesLength() - 1 downto -1 do begin
if jindex < 0 then begin
target := __node.jumpDefault;
end else begin
target := __node.getJumpCaseNodeAt(jindex);
end;
if target <> nil then begin
order := target.order;
if (order >= 0) and (attainability[order] = 0) then begin
attainability[order] := -1;
added := true;
end;
end;
end;
end;
inc(cindex);
if cindex >= length then begin
if not added then break;
added := false;
cindex := 0;
end;
until false;
end;
class procedure ImmediateBuilder.appendPropertyIndexCode(position: int; parent: Node; __constant: Constant; __member: TypedMember);
var
index: Node;
__code: Code;
__method: Method;
enclosingCallable: Callable;
enclosingClassType: ru.malik.elaborarer.avtoo.lang.ClassType;
begin
if __constant <> nil then begin
parent.parentCode.createAndAppendNode(parent).setData(position, __constant.&type, LOAD_CONST, __constant);
exit;
end;
if Lang.isInstance(__member, Field) then begin
__code := parent.parentCode;
enclosingCallable := __code.parentCallable;
enclosingClassType := enclosingCallable.parentType;
index := __code.createAndAppendNode(parent).setData(position, __member.&type, READ_FIELD, Field(Lang.cast(__member, Field)));
__code.createAndAppendNode(index).setData(position, enclosingClassType.getRealType(), LOAD_LOCAL, enclosingCallable.arguments.thisArgument);
exit;
end;
if Lang.isInstance(__member, Method) then begin
__method := Method(Lang.cast(__member, Method));
__code := parent.parentCode;
enclosingCallable := __code.parentCallable;
enclosingClassType := enclosingCallable.parentType;
index := __code.createAndAppendNode(parent).setData(position, __member.&type, invokeInstructionFor(__method, enclosingClassType), __method);
__code.createAndAppendNode(index).setData(position, enclosingClassType.getRealType(), LOAD_LOCAL, enclosingCallable.arguments.thisArgument);
end;
end;
class function ImmediateBuilder.isLogicalConditionNode(__node: Node): boolean;
var
subnode: Node;
begin
subnode := __node.readComponent(1);
case subnode.instruction of
BOOL_OR,
BOOL_AND,
BOOL_NOT: begin
result := true;
exit;
end;
BOOL_COND: begin
if isLogicalConditionNode(subnode) then begin
result := true;
exit;
end;
end;
end;
subnode := __node.readComponent(-1);
case subnode.instruction of
BOOL_OR,
BOOL_AND,
BOOL_NOT: begin
result := true;
exit;
end;
BOOL_COND: begin
result := isLogicalConditionNode(subnode);
exit;
end;
end;
result := false;
end;
class function ImmediateBuilder.isHandledException(__type: ClassType; parent: Node; __callable: Callable): boolean;
var
index: int;
__node: Node;
handler: Node;
begin
handler := parent;
while handler <> nil do begin
if handler.instruction = FCT_BEGIN then begin
handler := handler.parentNode;
for index := handler.getLength() - 1 downto 1 do begin
__node := handler.readComponent(index);
if (__node.instruction = FCT_CATCH) and (__node.reference1 as ru.malik.elaborarer.avtoo.lang.ClassType).isAssignableFrom(__type) then begin
result := true;
exit;
end;
end;
end;
handler := handler.parentNode;
end;
result := __callable.canThrown(__type);
end;
class function ImmediateBuilder.invokeInstructionFor(foundCallable: Member; foundPlace: ClassType): int;
begin
if (foundCallable.visibility <= VIS_PRIVATE) or foundCallable.isFinal() or foundPlace.isFinal() or foundCallable.parentType.isHelper() then begin
result := INVOKE_SPECIAL;
exit;
end;
if foundPlace.isService() then begin
result := INVOKE_SERVICE;
exit;
end;
result := INVOKE_VIRTUAL;
end;
class function ImmediateBuilder.getUnhandledException(__method: Method; parent: Node; __callable: Callable): ClassType;
var
index: int;
__type: ru.malik.elaborarer.avtoo.lang.ClassType;
begin
for index := __method.getThrowablesLength() - 1 downto 0 do begin
__type := __method.getThrowableTypeAt(index);
if not __type.isFreeThrowableType() and not isHandledException(__type, parent, __callable) then begin
result := __type;
exit;
end;
end;
result := nil;
end;
class function ImmediateBuilder.cast(value: Node; newType: &Type): Node;
var
__cast: Node;
__code: Code;
oldType: &Type;
begin
oldType := value.&type;
if newType <> oldType then begin
if oldType.isNull() then begin
if not newType.isPrimitive() then begin
value.&type := newType;
end;
end else
if oldType.isPrimitive() then begin
if newType.isPrimitive() then begin
if value.instruction = LOAD_CONST then begin
value.&type := newType;
value.operandC := value.operandC.castTo(newType);
end else
if newType.isInt() and not oldType.isStackable() then begin
value.&type := newType;
end else begin
newType.makeCompilable();
__code := value.parentCode;
__cast := __code.createAndInsertNode(value.parentNode, value.index).setData(-1, newType, CAST_TO, newType, oldType);
__code.moveNode(value, __cast, 0);
result := __cast;
exit;
end;
end;
end else begin
if not newType.isPrimitive() then begin
if newType.isAssignableFrom(oldType) then begin
value.&type := newType;
end else begin
newType.makeCompilable();
__code := value.parentCode;
__cast := __code.createAndInsertNode(value.parentNode, value.index).setData(-1, newType, CAST_TO, newType, oldType);
__code.moveNode(value, __cast, 0);
result := __cast;
exit;
end;
end;
end;
end;
result := value;
end;
procedure ImmediateBuilder.buildPropertySpecifiers(__property: &Property);
label
break_label0,
break_label1,
break_label2,
break_label3;
var
hasIndex: boolean;
root: Node;
value: Node;
write: Node;
__code: Code;
control: Node;
__type: &Type;
__value: Local;
__member: Member;
__method: Method;
readConstant: Constant;
readMember: TypedMember;
indexConstant: Constant;
indexMember: TypedMember;
writeMember: TypedMember;
storedConstant: Constant;
storedMember: TypedMember;
factEnclosing: ru.malik.elaborarer.avtoo.lang.ClassType;
realEnclosing: ru.malik.elaborarer.avtoo.lang.ClassType;
begin
factEnclosing := __property.parentType;
realEnclosing := factEnclosing.getRealType();
indexMember := __property.indexMember;
indexConstant := __property.indexConstant;
hasIndex := (indexConstant <> nil) or (indexMember <> nil);
__method := __property.indexSynthetic;
if __method <> nil then begin
__type := __method.&type;
__code := __method.code;
root := __code.root.setData(-1, METHOD_ENTER, nil);
control := __code.createAndAppendNode(root).setData(-1, FCT_RETURN);
__code.createAndAppendNode(root).setData(-1, METHOD_LEAVE);
if indexConstant <> nil then begin
__code.createAndAppendNode(control).setData(-1, __type, LOAD_CONST, indexConstant.castTo(__type));
goto break_label0;
end;
if Lang.isInstance(indexMember, Field) then begin
__member := Member(Lang.cast(indexMember, Member));
value := __code.createAndAppendNode(control).setData(-1, indexMember.&type, READ_FIELD, __member);
__code.createAndPrependNode(value).setData(-1, realEnclosing, LOAD_LOCAL, __method.arguments.thisArgument);
cast(value, __type);
goto break_label0;
end;
if Lang.isInstance(indexMember, Method) then begin
__member := Member(Lang.cast(indexMember, Member));
value := __code.createAndAppendNode(control).setData(-1, indexMember.&type, invokeInstructionFor(__member, factEnclosing), __member);
__code.createAndPrependNode(value).setData(-1, realEnclosing, LOAD_LOCAL, __method.arguments.thisArgument);
cast(value, __type);
end;
end;
break_label0:
__method := __property.readSynthetic;
if __method <> nil then begin
__type := __method.&type;
__code := __method.code;
readMember := __property.readMember;
readConstant := __property.readConstant;
root := __code.root.setData(-1, METHOD_ENTER, nil);
control := __code.createAndAppendNode(root).setData(-1, FCT_RETURN);
__code.createAndAppendNode(root).setData(-1, METHOD_LEAVE);
if readConstant <> nil then begin
__code.createAndAppendNode(control).setData(-1, __type, LOAD_CONST, readConstant.castTo(__type));
goto break_label1;
end;
if Lang.isInstance(readMember, Field) then begin
__member := Member(Lang.cast(readMember, Member));
value := __code.createAndAppendNode(control).setData(-1, readMember.&type, READ_FIELD, __member);
__code.createAndPrependNode(value).setData(-1, realEnclosing, LOAD_LOCAL, __method.arguments.thisArgument);
cast(value, __type);
goto break_label1;
end;
if Lang.isInstance(readMember, Method) then begin
__member := Member(Lang.cast(readMember, Member));
value := __code.createAndAppendNode(control).setData(-1, readMember.&type, invokeInstructionFor(__member, factEnclosing), __member);
if hasIndex then appendPropertyIndexCode(-1, value, indexConstant, indexMember);
__code.createAndPrependNode(value).setData(-1, realEnclosing, LOAD_LOCAL, __method.arguments.thisArgument);
cast(value, __type);
end;
end;
break_label1:
__method := __property.writeSynthetic;
if __method <> nil then begin
__code := __method.code;
__value := __method.getArgument(SPECNAME_VALUE);
writeMember := __property.writeMember;
root := __code.root.setData(-1, METHOD_ENTER, nil);
__code.createAndAppendNode(root).setData(-1, METHOD_LEAVE);
if Lang.isInstance(writeMember, Field) then begin
__member := Member(Lang.cast(writeMember, Member));
write := __code.createAndPrependNode(root).setData(-1, nil, WRITE_FIELD, __member);
__code.createAndAppendNode(write).setData(-1, __value.&type, LOAD_LOCAL, __value);
__code.createAndPrependNode(write).setData(-1, realEnclosing, LOAD_LOCAL, __method.arguments.thisArgument);
goto break_label2;
end;
if Lang.isInstance(writeMember, Method) then begin
__member := Member(Lang.cast(writeMember, Member));
write := __code.createAndPrependNode(root).setData(-1, nil, invokeInstructionFor(__member, factEnclosing), __member);
if hasIndex then appendPropertyIndexCode(-1, write, indexConstant, indexMember);
__code.createAndAppendNode(write).setData(-1, __value.&type, LOAD_LOCAL, __value);
__code.createAndPrependNode(write).setData(-1, realEnclosing, LOAD_LOCAL, __method.arguments.thisArgument);
end;
end;
break_label2:
__method := __property.storedSynthetic;
if __method <> nil then begin
__type := __method.&type;
__code := __method.code;
storedMember := __property.storedMember;
storedConstant := __property.storedConstant;
root := __code.root.setData(-1, METHOD_ENTER, nil);
control := __code.createAndAppendNode(root).setData(-1, FCT_RETURN);
__code.createAndAppendNode(root).setData(-1, METHOD_LEAVE);
if storedConstant <> nil then begin
__code.createAndAppendNode(control).setData(-1, __type, LOAD_CONST, storedConstant.castTo(__type));
goto break_label3;
end;
if Lang.isInstance(storedMember, Field) then begin
__member := Member(Lang.cast(storedMember, Member));
value := __code.createAndAppendNode(control).setData(-1, storedMember.&type, READ_FIELD, __member);
__code.createAndPrependNode(value).setData(-1, realEnclosing, LOAD_LOCAL, __method.arguments.thisArgument);
cast(value, __type);
goto break_label3;
end;
if Lang.isInstance(storedMember, Method) then begin
__member := Member(Lang.cast(storedMember, Member));
value := __code.createAndAppendNode(control).setData(-1, storedMember.&type, invokeInstructionFor(__member, factEnclosing), __member);
if hasIndex then appendPropertyIndexCode(-1, value, indexConstant, indexMember);
__code.createAndPrependNode(value).setData(-1, realEnclosing, LOAD_LOCAL, __method.arguments.thisArgument);
cast(value, __type);
end;
end;
break_label3:
end;
procedure ImmediateBuilder.parsePropertySpecifiers(__property: &Property);
label
break_label0,
break_label1,
break_label2,
break_label3;
var
hasIndex: boolean;
kind: int;
index: int;
position: int;
foundLength: int;
indexPosition: int;
name: AnsiString;
message: AnsiString;
arguments: Type_Array1d;
foundMethods: Method_Array1d;
foundFieldoids: Fieldoid_Array1d;
root: Node;
value: Node;
write: Node;
__exit: Node;
__code: Code;
__index: Node;
control: Node;
typeInt: &Type;
__value: Local;
__member: Member;
__method: Method;
valueType: &Type;
foundType: &Type;
foundField: Field;
sourceType: &Type;
targetType: &Type;
source: TextSource;
foundMethod: Method;
foundValue: Constant;
indexConstant: Constant;
indexMember: TypedMember;
foundProperty: &Property;
foundFieldoid: TypedMember;
foundArguments: ArgumentArray;
factEnclosing: ru.malik.elaborarer.avtoo.lang.ClassType;
realEnclosing: ru.malik.elaborarer.avtoo.lang.ClassType;
foundThrowable: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
source := TextSource(Lang.cast(__property.source, TextSource));
factEnclosing := __property.parentType;
realEnclosing := factEnclosing.getRealType();
__method := __property.indexSynthetic;
indexMember := __method;
indexConstant := nil;
typeInt := fldTypeInt;
indexPosition := 0;
hasIndex := __method <> nil;
{ index }
if hasIndex then begin
position := __method.implementationPosition;
targetType := __method.&type;
__code := __method.code;
root := __code.root.setData(-1, METHOD_ENTER, nil);
control := __code.createAndAppendNode(root).setData(-1, FCT_RETURN);
__code.createAndAppendNode(root).setData(-1, METHOD_LEAVE);
indexPosition := position - 2;
if (source.getLexemeKind(position) = L_NAME) and (source.getLexemeKind(position + 1) = COMMA) then begin
name := source.getLexemeString(position).toUTF8();
__member := factEnclosing.resolveName(name, factEnclosing, true);
if __member is Fieldoid then begin
foundFieldoids := factEnclosing.findFieldoids(name, factEnclosing);
foundLength := system.length(foundFieldoids);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.fieldoid'), [
CoAnsiString.create(factEnclosing.specialSimpleName), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundFieldoid := foundFieldoids[0];
if not foundFieldoid.isVisibleFrom(factEnclosing, factEnclosing) then begin
if Lang.isInstance(foundFieldoid, &Property) then begin
message := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.property');
end else begin
message := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.field');
end;
exception := TextSourceException.create(AnsiString.format(message, [
CoAnsiString.create(factEnclosing.specialSimpleName), CoSimple.create(foundFieldoid)
]));
exception.source := source;
exception.position := position;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.fieldoid'), [
CoAnsiString.create(factEnclosing.specialCanonicalName + '.' + name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if Lang.isInstance(foundFieldoid, Field) then begin
foundField := Field(Lang.cast(foundFieldoid, Field));
foundType := foundField.&type;
if not targetType.isConvertableFrom(foundType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.index.field-type'), [
CoObject.create(foundField), CoObject.create(foundType), CoObject.create(targetType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
value := __code.createAndAppendNode(control);
if not foundField.isStatic() then begin
if targetType.isAssignableFrom(foundType) then begin
__property.indexMember := foundField;
indexMember := foundField;
end;
value.setData(position, foundType, READ_FIELD, foundField);
__code.createAndPrependNode(value).setData(position, realEnclosing, LOAD_LOCAL, __method.arguments.thisArgument);
end else begin
case foundField.state of
Field.COMPUTING: begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'field.self-dependent-value'), [
CoObject.create(foundField)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
Field.NOT_COMPUTED: begin
parseStaticFieldValue(foundField, foundField.parentType.getStaticBlock());
end;
end;
foundValue := foundField.value;
if foundField.isFinal() and (foundValue <> nil) then begin
foundValue := foundValue.castTo(targetType);
__property.indexConstant := foundValue;
indexConstant := foundValue;
value.setData(position, foundValue.&type, LOAD_CONST, foundValue);
end else begin
value.setData(position, foundType, LOAD_STATIC, foundField);
end;
end;
cast(value, targetType);
goto break_label0;
end;
if Lang.isInstance(foundFieldoid, &Property) then begin
foundProperty := &Property(Lang.cast(foundFieldoid, &Property));
if not foundProperty.hasRead() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.index.property-write-only'), [
CoObject.create(foundProperty)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundType := foundProperty.&type;
if not targetType.isConvertableFrom(foundType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.index.property-type'), [
CoObject.create(foundProperty), CoObject.create(foundType), CoObject.create(targetType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
value := __code.createAndAppendNode(control).setData(position, foundType, READ_PROPERTY, foundProperty);
__code.createAndPrependNode(value).setData(position, realEnclosing, LOAD_LOCAL, __method.arguments.thisArgument);
cast(value, targetType);
goto break_label0;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.fieldoid'), [
CoAnsiString.create(factEnclosing.specialSimpleName), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if __member is Method then begin
foundMethods := factEnclosing.findMethods(name, nil, factEnclosing);
foundLength := system.length(foundMethods);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.method'), [
CoAnsiString.create(factEnclosing.specialSimpleName), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundMethod := foundMethods[0];
if foundMethod.isInterrupt() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.index.method-interrupt'), [
CoObject.create(foundMethod)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if not foundMethod.isConvertableArguments(nil) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.index.method-arguments'), [
CoObject.create(foundMethod), CoAnsiString.create(ArgumentArray.toString(nil))
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if not foundMethod.isVisibleFrom(factEnclosing, factEnclosing) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.method'), [
CoAnsiString.create(factEnclosing.specialSimpleName), CoObject.create(foundMethod)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.method'), [
CoAnsiString.create(factEnclosing.specialCanonicalName + '.' + name + ArgumentArray.toString(nil))
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundType := foundMethod.&type;
if not targetType.isConvertableFrom(foundType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.index.method-return-type'), [
CoObject.create(foundMethod), CoObject.create(foundType), CoObject.create(targetType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundThrowable := foundMethod.firstNonFreeThrowableType();
if foundThrowable <> nil then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.index.method-throws'), [
CoObject.create(foundMethod), CoObject.create(foundThrowable)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
value := __code.createAndAppendNode(control);
if foundMethod.isStatic() then begin
value.setData(position, foundType, INVOKE_STATIC, foundMethod);
end else begin
if targetType.isAssignableFrom(foundType) then begin
__property.indexMember := foundMethod;
indexMember := foundMethod;
end;
value.setData(position, foundType, invokeInstructionFor(foundMethod, factEnclosing), foundMethod);
__code.createAndPrependNode(value).setData(position, realEnclosing, LOAD_LOCAL, __method.arguments.thisArgument);
end;
cast(value, targetType);
goto break_label0;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.member'), [
CoAnsiString.create(factEnclosing.specialSimpleName), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
position := parseExpression(control, source, position, false);
if source.getLexemeKind(position) <> COMMA then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.comma'));
exception.source := source;
exception.position := position;
raise exception;
end;
value := control.readComponent(-1);
requiresValue(value);
valueType := value.&type;
if not targetType.isConvertableFrom(valueType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.index.expression-type'), [
CoObject.create(valueType), CoObject.create(targetType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
cast(value, targetType);
if value.instruction = LOAD_CONST then begin
indexConstant := value.operandC;
__property.indexConstant := indexConstant;
end;
end;
break_label0:
{ read }
__method := __property.readSynthetic;
if __method <> nil then begin
position := __method.implementationPosition;
targetType := __method.&type;
__code := __method.code;
root := __code.root.setData(-1, METHOD_ENTER, nil);
control := __code.createAndAppendNode(root).setData(-1, FCT_RETURN);
__code.createAndAppendNode(root).setData(-1, METHOD_LEAVE);
if source.getLexemeKind(position) = L_NAME then begin
kind := source.getLexemeKind(position + 1);
if (kind = COMMA) or (kind = CURLY_CLOSED) then begin
name := source.getLexemeString(position).toUTF8();
__member := factEnclosing.resolveName(name, factEnclosing, true);
if __member is Fieldoid then begin
foundFieldoids := factEnclosing.findFieldoids(name, factEnclosing);
foundLength := system.length(foundFieldoids);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.fieldoid'), [
CoAnsiString.create(factEnclosing.specialSimpleName), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundFieldoid := foundFieldoids[0];
if not foundFieldoid.isVisibleFrom(factEnclosing, factEnclosing) then begin
if Lang.isInstance(foundFieldoid, &Property) then begin
message := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.property');
end else begin
message := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.field');
end;
exception := TextSourceException.create(AnsiString.format(message, [
CoAnsiString.create(factEnclosing.specialSimpleName), CoSimple.create(foundFieldoid)
]));
exception.source := source;
exception.position := position;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.fieldoid'), [
CoAnsiString.create(factEnclosing.specialCanonicalName + '.' + name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if Lang.isInstance(foundFieldoid, Field) then begin
foundField := Field(Lang.cast(foundFieldoid, Field));
foundType := foundField.&type;
if not targetType.isConvertableFrom(foundType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.read.field-type'), [
CoObject.create(foundField), CoObject.create(foundType), CoObject.create(targetType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
value := __code.createAndAppendNode(control);
if not foundField.isStatic() then begin
if targetType.isAssignableFrom(foundType) then __property.readMember := foundField;
value.setData(position, foundType, READ_FIELD, foundField);
__code.createAndPrependNode(value).setData(position, realEnclosing, LOAD_LOCAL, __method.arguments.thisArgument);
end else begin
case foundField.state of
Field.COMPUTING: begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'field.self-dependent-value'), [
CoObject.create(foundField)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
Field.NOT_COMPUTED: begin
parseStaticFieldValue(foundField, foundField.parentType.getStaticBlock());
end;
end;
foundValue := foundField.value;
if foundField.isFinal() and (foundValue <> nil) then begin
foundValue := foundValue.castTo(targetType);
__property.readConstant := foundValue;
value.setData(position, foundValue.&type, LOAD_CONST, foundValue);
end else begin
value.setData(position, foundType, LOAD_STATIC, foundField);
end;
end;
cast(value, targetType);
goto break_label1;
end;
if Lang.isInstance(foundFieldoid, &Property) then begin
foundProperty := &Property(Lang.cast(foundFieldoid, &Property));
if not foundProperty.hasRead() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.read.property-write-only'), [
CoObject.create(foundProperty)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundType := foundProperty.&type;
if not targetType.isConvertableFrom(foundType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.read.property-type'), [
CoObject.create(foundProperty), CoObject.create(foundType), CoObject.create(targetType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
value := __code.createAndAppendNode(control).setData(position, foundType, READ_PROPERTY, foundProperty);
__code.createAndPrependNode(value).setData(position, realEnclosing, LOAD_LOCAL, __method.arguments.thisArgument);
cast(value, targetType);
goto break_label1;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.fieldoid'), [
CoAnsiString.create(factEnclosing.specialSimpleName), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if __member is Method then begin
if not hasIndex then begin
arguments := nil;
end else begin
arguments := [ typeInt ];
end;
foundMethods := factEnclosing.findMethods(name, arguments, factEnclosing);
foundLength := system.length(foundMethods);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.method'), [
CoAnsiString.create(factEnclosing.specialSimpleName), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundMethod := foundMethods[0];
if foundMethod.isInterrupt() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.read.method-interrupt'), [
CoObject.create(foundMethod)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if not foundMethod.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.read.method-arguments'), [
CoObject.create(foundMethod), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if not foundMethod.isVisibleFrom(factEnclosing, factEnclosing) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.method'), [
CoAnsiString.create(factEnclosing.specialSimpleName), CoObject.create(foundMethod)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.method'), [
CoAnsiString.create(factEnclosing.specialCanonicalName + '.' + name + ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundType := foundMethod.&type;
if not targetType.isConvertableFrom(foundType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.read.method-return-type'), [
CoObject.create(foundMethod), CoObject.create(foundType), CoObject.create(targetType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundThrowable := foundMethod.firstNonFreeThrowableType();
if foundThrowable <> nil then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.read.method-throws'), [
CoObject.create(foundMethod), CoObject.create(foundThrowable)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
value := __code.createAndAppendNode(control);
if foundMethod.isStatic() then begin
value.setData(position, foundType, INVOKE_STATIC, foundMethod);
if hasIndex then appendPropertyIndexCode(position, value, indexConstant, indexMember);
foundArguments := foundMethod.arguments;
for index := foundArguments.getLength() - 1 downto 0 do cast(value.readComponent(index), foundArguments.readComponent(index).&type);
end else begin
if targetType.isAssignableFrom(foundType) and foundMethod.isAssignableArguments(arguments) then __property.readMember := foundMethod;
value.setData(position, foundType, invokeInstructionFor(foundMethod, factEnclosing), foundMethod);
if hasIndex then appendPropertyIndexCode(position, value, indexConstant, indexMember);
foundArguments := foundMethod.arguments;
for index := foundArguments.getLength() - 1 downto 0 do cast(value.readComponent(index), foundArguments.readComponent(index).&type);
__code.createAndPrependNode(value).setData(position, realEnclosing, LOAD_LOCAL, __method.arguments.thisArgument);
end;
cast(value, targetType);
goto break_label1;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.member'), [
CoAnsiString.create(factEnclosing.specialSimpleName), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
end;
if hasIndex then begin
__index := __code.createAndPrependNode(root).setData(-1, nil, DECLARE_LOCAL, __code.createLocal(true, typeInt, SPECNAME_INDEX, nil, indexPosition));
appendPropertyIndexCode(-1, __index, indexConstant, indexMember);
end;
position := parseExpression(control, source, position, false);
kind := source.getLexemeKind(position);
if (kind <> COMMA) and (kind <> CURLY_CLOSED) then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
value := control.readComponent(-1);
requiresValue(value);
valueType := value.&type;
if not targetType.isConvertableFrom(valueType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.read.expression-type'), [
CoObject.create(valueType), CoObject.create(targetType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
cast(value, targetType);
if value.instruction = LOAD_CONST then __property.readConstant := value.operandC;
end;
break_label1:
{ write }
__method := __property.writeSynthetic;
if __method <> nil then begin
position := __method.implementationPosition;
sourceType := __property.&type;
__code := __method.code;
root := __code.root.setData(-1, METHOD_ENTER, nil);
__exit := __code.createAndAppendNode(root).setData(-1, METHOD_LEAVE);
if source.getLexemeKind(position) = L_NAME then begin
kind := source.getLexemeKind(position + 1);
if (kind = COMMA) or (kind = CURLY_CLOSED) then begin
__value := __method.getArgument(SPECNAME_VALUE);
name := source.getLexemeString(position).toUTF8();
__member := factEnclosing.resolveName(name, factEnclosing, true);
if __member is Fieldoid then begin
foundFieldoids := factEnclosing.findFieldoids(name, factEnclosing);
foundLength := system.length(foundFieldoids);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.fieldoid'), [
CoAnsiString.create(factEnclosing.specialSimpleName), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundFieldoid := foundFieldoids[0];
if not foundFieldoid.isVisibleFrom(factEnclosing, factEnclosing) then begin
if Lang.isInstance(foundFieldoid, &Property) then begin
message := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.property');
end else begin
message := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.field');
end;
exception := TextSourceException.create(AnsiString.format(message, [
CoAnsiString.create(factEnclosing.specialSimpleName), CoSimple.create(foundFieldoid)
]));
exception.source := source;
exception.position := position;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.fieldoid'), [
CoAnsiString.create(factEnclosing.specialCanonicalName + '.' + name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if Lang.isInstance(foundFieldoid, Field) then begin
foundField := Field(Lang.cast(foundFieldoid, Field));
if foundField.isFinal() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.write.field-final'), [
CoObject.create(foundField)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundType := foundField.&type;
if not foundType.isConvertableFrom(sourceType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.write.field-type'), [
CoObject.create(foundField), CoObject.create(foundType), CoObject.create(sourceType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
write := __code.createAndPrependNode(root);
if foundField.isStatic() then begin
write.setData(position, nil, STORE_STATIC, foundField);
end else begin
if foundType.isAssignableFrom(sourceType) then __property.writeMember := foundField;
write.setData(position, nil, WRITE_FIELD, foundField);
__code.createAndPrependNode(write).setData(position, realEnclosing, LOAD_LOCAL, __method.arguments.thisArgument);
end;
cast(__code.createAndAppendNode(write).setData(position, __value.&type, LOAD_LOCAL, __value), foundType);
goto break_label2;
end;
if Lang.isInstance(foundFieldoid, &Property) then begin
foundProperty := &Property(Lang.cast(foundFieldoid, &Property));
if not foundProperty.hasWrite() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.write.property-read-only'), [
CoObject.create(foundProperty)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundType := foundProperty.&type;
if not foundType.isConvertableFrom(sourceType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.write.property-type'), [
CoObject.create(foundProperty), CoObject.create(foundType), CoObject.create(sourceType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
write := __code.createAndPrependNode(root).setData(position, nil, WRITE_PROPERTY, foundProperty);
__code.createAndPrependNode(write).setData(position, realEnclosing, LOAD_LOCAL, __method.arguments.thisArgument);
cast(__code.createAndAppendNode(write).setData(position, __value.&type, LOAD_LOCAL, __value), foundType);
goto break_label2;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.fieldoid'), [
CoAnsiString.create(factEnclosing.specialSimpleName), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if __member is Method then begin
if not hasIndex then begin
arguments := [ sourceType ];
end else begin
arguments := [ typeInt, sourceType ];
end;
foundMethods := factEnclosing.findMethods(name, arguments, factEnclosing);
foundLength := system.length(foundMethods);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.method'), [
CoAnsiString.create(factEnclosing.specialSimpleName), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundMethod := foundMethods[0];
if foundMethod.isInterrupt() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.write.method-interrupt'), [
CoObject.create(foundMethod)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if not foundMethod.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.write.method-arguments'), [
CoObject.create(foundMethod), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if not foundMethod.isVisibleFrom(factEnclosing, factEnclosing) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.method'), [
CoAnsiString.create(factEnclosing.specialSimpleName), CoObject.create(foundMethod)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.method'), [
CoAnsiString.create(factEnclosing.specialCanonicalName + '.' + name + ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundType := foundMethod.&type;
if not foundType.isVoid() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.write.method-return-type'), [
CoObject.create(foundMethod), CoObject.create(foundType), CoObject.create(fldTypeVoid)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundThrowable := foundMethod.firstNonFreeThrowableType();
if foundThrowable <> nil then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.write.method-throws'), [
CoObject.create(foundMethod), CoObject.create(foundThrowable)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if foundMethod.isStatic() then begin
write := __code.createAndPrependNode(root).setData(position, nil, INVOKE_STATIC, foundMethod);
if hasIndex then appendPropertyIndexCode(position, write, indexConstant, indexMember);
__code.createAndAppendNode(write).setData(position, __value.&type, LOAD_LOCAL, __value);
foundArguments := foundMethod.arguments;
for index := foundArguments.getLength() - 1 downto 0 do cast(write.readComponent(index), foundArguments.readComponent(index).&type);
goto break_label2;
end;
if foundMethod.isAssignableArguments(arguments) then __property.writeMember := foundMethod;
write := __code.createAndPrependNode(root).setData(position, nil, invokeInstructionFor(foundMethod, factEnclosing), foundMethod);
if hasIndex then appendPropertyIndexCode(position, write, indexConstant, indexMember);
__code.createAndAppendNode(write).setData(position, __value.&type, LOAD_LOCAL, __value);
foundArguments := foundMethod.arguments;
for index := foundArguments.getLength() - 1 downto 0 do cast(write.readComponent(index), foundArguments.readComponent(index).&type);
__code.createAndPrependNode(write).setData(position, realEnclosing, LOAD_LOCAL, __method.arguments.thisArgument);
goto break_label2;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.member'), [
CoAnsiString.create(factEnclosing.specialSimpleName), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
end;
if hasIndex then begin
__index := __code.createAndPrependNode(root).setData(-1, nil, DECLARE_LOCAL, __code.createLocal(true, typeInt, SPECNAME_INDEX, nil, indexPosition));
appendPropertyIndexCode(-1, __index, indexConstant, indexMember);
end;
position := parseDeclareLocal(root, source, position, false);
kind := source.getLexemeKind(position);
if (kind <> COMMA) and (kind <> CURLY_CLOSED) then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
__code.moveNode(__exit, root.getLength());
end;
break_label2:
{ stored }
__method := __property.storedSynthetic;
if __method <> nil then begin
position := __method.implementationPosition;
targetType := __method.&type;
__code := __method.code;
root := __code.root.setData(-1, METHOD_ENTER, nil);
control := __code.createAndAppendNode(root).setData(-1, FCT_RETURN);
__code.createAndAppendNode(root).setData(-1, METHOD_LEAVE);
if (source.getLexemeKind(position) = L_NAME) and (source.getLexemeKind(position + 1) = CURLY_CLOSED) then begin
name := source.getLexemeString(position).toUTF8();
__member := factEnclosing.resolveName(name, factEnclosing, true);
if __member is Fieldoid then begin
foundFieldoids := factEnclosing.findFieldoids(name, factEnclosing);
foundLength := system.length(foundFieldoids);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.fieldoid'), [
CoAnsiString.create(factEnclosing.specialSimpleName), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundFieldoid := foundFieldoids[0];
if not foundFieldoid.isVisibleFrom(factEnclosing, factEnclosing) then begin
if Lang.isInstance(foundFieldoid, &Property) then begin
message := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.property');
end else begin
message := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.field');
end;
exception := TextSourceException.create(AnsiString.format(message, [
CoAnsiString.create(factEnclosing.specialSimpleName), CoSimple.create(foundFieldoid)
]));
exception.source := source;
exception.position := position;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.fieldoid'), [
CoAnsiString.create(factEnclosing.specialCanonicalName + '.' + name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if Lang.isInstance(foundFieldoid, Field) then begin
foundField := Field(Lang.cast(foundFieldoid, Field));
foundType := foundField.&type;
if not targetType.isConvertableFrom(foundType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.stored.field-type'), [
CoObject.create(foundField), CoObject.create(foundType), CoObject.create(targetType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
value := __code.createAndAppendNode(control);
if not foundField.isStatic() then begin
if targetType.isAssignableFrom(foundType) then __property.storedMember := foundField;
value.setData(position, foundType, READ_FIELD, foundField);
__code.createAndPrependNode(value).setData(position, realEnclosing, LOAD_LOCAL, __method.arguments.thisArgument);
end else begin
case foundField.state of
Field.COMPUTING: begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'field.self-dependent-value'), [
CoObject.create(foundField)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
Field.NOT_COMPUTED: begin
parseStaticFieldValue(foundField, foundField.parentType.getStaticBlock());
end;
end;
foundValue := foundField.value;
if foundField.isFinal() and (foundValue <> nil) then begin
foundValue := foundValue.castTo(targetType);
__property.storedConstant := foundValue;
value.setData(position, foundValue.&type, LOAD_CONST, foundValue);
end else begin
value.setData(position, foundType, LOAD_STATIC, foundField);
end;
end;
cast(value, targetType);
goto break_label3;
end;
if Lang.isInstance(foundFieldoid, &Property) then begin
foundProperty := &Property(Lang.cast(foundFieldoid, &Property));
if not foundProperty.hasRead() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.stored.property-write-only'), [
CoObject.create(foundProperty)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundType := foundProperty.&type;
if not targetType.isConvertableFrom(foundType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.stored.property-type'), [
CoObject.create(foundProperty), CoObject.create(foundType), CoObject.create(targetType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
value := __code.createAndAppendNode(control).setData(position, foundType, READ_PROPERTY, foundProperty);
__code.createAndPrependNode(value).setData(position, realEnclosing, LOAD_LOCAL, __method.arguments.thisArgument);
cast(value, targetType);
goto break_label3;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.fieldoid'), [
CoAnsiString.create(factEnclosing.specialSimpleName), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if __member is Method then begin
if not hasIndex then begin
arguments := nil;
end else begin
arguments := [ typeInt ];
end;
foundMethods := factEnclosing.findMethods(name, arguments, factEnclosing);
foundLength := system.length(foundMethods);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.method'), [
CoAnsiString.create(factEnclosing.specialSimpleName), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundMethod := foundMethods[0];
if foundMethod.isInterrupt() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.stored.method-interrupt'), [
CoObject.create(foundMethod)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if not foundMethod.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.stored.method-arguments'), [
CoObject.create(foundMethod), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if not foundMethod.isVisibleFrom(factEnclosing, factEnclosing) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.method'), [
CoAnsiString.create(factEnclosing.specialSimpleName), CoObject.create(foundMethod)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.method'), [
CoAnsiString.create(factEnclosing.specialCanonicalName + '.' + name + ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundType := foundMethod.&type;
if not targetType.isConvertableFrom(foundType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.stored.method-return-type'), [
CoObject.create(foundMethod), CoObject.create(foundType), CoObject.create(targetType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundThrowable := foundMethod.firstNonFreeThrowableType();
if foundThrowable <> nil then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.stored.method-throws'), [
CoObject.create(foundMethod), CoObject.create(foundThrowable)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
value := __code.createAndAppendNode(control);
if foundMethod.isStatic() then begin
value.setData(position, foundType, INVOKE_STATIC, foundMethod);
if hasIndex then appendPropertyIndexCode(position, value, indexConstant, indexMember);
foundArguments := foundMethod.arguments;
for index := foundArguments.getLength() - 1 downto 0 do cast(value.readComponent(index), foundArguments.readComponent(index).&type);
end else begin
if targetType.isAssignableFrom(foundType) and foundMethod.isAssignableArguments(arguments) then __property.storedMember := foundMethod;
value.setData(position, foundType, invokeInstructionFor(foundMethod, factEnclosing), foundMethod);
if hasIndex then appendPropertyIndexCode(position, value, indexConstant, indexMember);
foundArguments := foundMethod.arguments;
for index := foundArguments.getLength() - 1 downto 0 do cast(value.readComponent(index), foundArguments.readComponent(index).&type);
__code.createAndPrependNode(value).setData(position, realEnclosing, LOAD_LOCAL, __method.arguments.thisArgument);
end;
cast(value, targetType);
goto break_label3;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.member'), [
CoAnsiString.create(factEnclosing.specialSimpleName), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if hasIndex then begin
__index := __code.createAndPrependNode(root).setData(-1, nil, DECLARE_LOCAL, __code.createLocal(true, typeInt, SPECNAME_INDEX, nil, indexPosition));
appendPropertyIndexCode(-1, __index, indexConstant, indexMember);
end;
position := parseExpression(control, source, position, false);
if source.getLexemeKind(position) <> CURLY_CLOSED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
value := control.readComponent(-1);
requiresValue(value);
valueType := value.&type;
if not targetType.isConvertableFrom(valueType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'property.stored.expression-type'), [
CoObject.create(valueType), CoObject.create(targetType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
cast(value, targetType);
if value.instruction = LOAD_CONST then __property.storedConstant := value.operandC;
end;
break_label3:
end;
procedure ImmediateBuilder.parseStaticFieldValue(__field: Field; staticBlock: ClassInit);
var
before: int;
position: int;
store: Node;
value: Node;
__code: Code;
fieldType: &Type;
valueType: &Type;
source: TextSource;
exception: TextSourceException;
begin
if __field.state = Field.NOT_COMPUTED then begin
source := TextSource(Lang.cast(__field.source, TextSource));
position := __field.implementationPosition;
case source.getLexemeKind(position) of
SEMICOLON: begin
__field.closeComputing();
exit;
end;
EQUAL: begin
if __field.isStatic() then begin
__code := staticBlock.code;
__field.openComputing();
try
before := position;
store := __code.createAndAppendNode(nil);
position := parseExpression(store, source, position + 1, false);
if source.getLexemeKind(position) <> SEMICOLON then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.semicolon'));
exception.source := source;
exception.position := position;
raise exception;
end;
value := store.readComponent(-1);
requiresValue(value);
fieldType := __field.&type;
valueType := value.&type;
if not fieldType.isConvertableFrom(valueType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.type'), [
CoObject.create(valueType), CoObject.create(fieldType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
value := cast(value, fieldType);
if (value.instruction <> LOAD_CONST) or not fieldType.isPrimitive() and not __field.isFinal() then begin
store.setData(before, nil, STORE_STATIC, __field);
end else begin
__field.setComputedValue(value.operandC);
__code.removeNode(store);
end;
finally
__field.closeComputing();
end;
exit;
end;
end;
end;
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.semicolon'));
exception.source := source;
exception.position := position;
raise exception;
end;
end;
function ImmediateBuilder.parsePostfix(parent: Node; source: TextSource; position: int; isStaticOnly, isImplicitPeriod: boolean): int;
label
continue_label0;
var
isPeriod: boolean;
isUseSuper: boolean;
kind: int;
index: int;
length: int;
before: int;
context: int;
operation: int;
instruction: int;
foundLength: int;
name: AnsiString;
resource: AnsiString;
arguments: Type_Array1d;
foundFieldoids: Fieldoid_Array1d;
foundOperators: Operator_Array1d;
foundCallables: Callable_Array1d;
foundInterrupts: Callable_Array1d;
load: Node;
read: Node;
delta: Node;
child1: Node;
child2: Node;
__code: Code;
resultNode: Node;
foundField: Field;
foundLocal: Local;
foundValue: Constant;
foundItem: TableItem;
argument1Type: &Type;
argument2Type: &Type;
componentType: &Type;
typeInt: PrimitiveType;
resolvedMember: Member;
foundCallable: Callable;
foundInterrupt: Callable;
foundOperator: &Operator;
foundProperty: &Property;
foundFieldoid: TypedMember;
foundReadOperator: &Operator;
foundWriteOperator: &Operator;
vectorMainType: PrimitiveType;
vectorBaseType: PrimitiveType;
foundArguments: ArgumentArray;
operatorHolder: ImmediateBuilderItemHolder;
enclosingCallable: ru.malik.elaborarer.avtoo.lang.Callable;
enclosingClassType: ru.malik.elaborarer.avtoo.lang.ClassType;
dereferenceClassType: ru.malik.elaborarer.avtoo.lang.ClassType;
impliedParentClassType: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
__code := parent.parentCode;
enclosingCallable := __code.parentCallable;
enclosingClassType := enclosingCallable.parentType;
child1 := parent.readComponent(-1);
isUseSuper := child1.useSuper;
repeat
operation := source.getLexemeKind(position);
if isUseSuper and (operation <> PERIOD) and (operation <> PARENTH_OPENED) and (operation <> BRACKET_OPENED) then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'error.expression.super'));
exception.source := source;
exception.position := position;
raise exception;
end;
isPeriod := false;
if isImplicitPeriod then begin
isPeriod := true;
end else
if operation = PERIOD then begin
isPeriod := true;
inc(position);
end;
before := position;
argument1Type := child1.&type;
if isPeriod then begin
if (argument1Type <> nil) and not(argument1Type is ru.malik.elaborarer.avtoo.lang.ClassType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.dereference.type'), [
CoObject.create(argument1Type)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if child1.instruction = DCL_CLASS then begin
context := -1; { это точно статичный контекст }
dereferenceClassType := child1.operand1 as ru.malik.elaborarer.avtoo.lang.ClassType;
end else begin
if isImplicitPeriod then begin
context := 0; { неопределённый контекст }
end else begin
context := 1; { это точно инстанционный контекст }
end;
dereferenceClassType := ru.malik.elaborarer.avtoo.lang.ClassType(argument1Type);
end;
if isUseSuper then begin
impliedParentClassType := enclosingClassType;
end else begin
impliedParentClassType := dereferenceClassType;
end;
kind := 0;
name := '';
case source.getLexemeKind(position) of
DCL_OPERATOR: begin
operatorHolder := getItemHolder();
position := parseOperator(source, position + 1, operatorHolder) - 1;
kind := operatorHolder.resultKind;
name := &Operator.kindToSpecialSimpleName(kind);
end;
L_NAME: begin
name := source.getLexemeString(position).toUTF8();
end;
else
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.name.member'));
exception.source := source;
exception.position := position;
raise exception;
end;
resolvedMember := dereferenceClassType.resolveName(name, enclosingClassType, false);
if resolvedMember is Fieldoid then begin
foundFieldoids := dereferenceClassType.findFieldoids(name, enclosingClassType);
foundLength := system.length(foundFieldoids);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.fieldoid'), [
CoObject.create(dereferenceClassType), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundFieldoid := foundFieldoids[0];
if not foundFieldoid.isVisibleFrom(enclosingClassType, impliedParentClassType) then begin
if Lang.isInstance(foundFieldoid, &Property) then begin
resource := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.property');
end else begin
resource := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.field');
end;
exception := TextSourceException.create(AnsiString.format(resource, [ CoAnsiString.create(enclosingClassType.specialSimpleName), CoSimple.create(foundFieldoid) ]));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.fieldoid'), [
CoAnsiString.create(dereferenceClassType.specialCanonicalName + '.' + name)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if Lang.isInstance(foundFieldoid, Field) then begin
foundField := Field(Lang.cast(foundFieldoid, Field));
if context > 0 then begin
if foundField.isStatic() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-be.access.static-field'), [
CoObject.create(foundField)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
resultNode := __code.createAndAppendNode(parent).setData(before, foundField.&type, READ_FIELD, foundField);
__code.moveNode(child1, resultNode, 0);
child1 := resultNode;
goto continue_label0;
end;
if not foundField.isStatic() then begin
if context < 0 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-be.access.instance-field'), [
CoObject.create(foundField)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
resultNode := __code.createAndAppendNode(parent).setData(before, foundField.&type, READ_FIELD, foundField);
__code.moveNode(child1, resultNode, 0);
child1 := resultNode;
goto continue_label0;
end;
case foundField.state of
Field.COMPUTING: begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'field.self-dependent-value'), [
CoObject.create(foundField)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
Field.NOT_COMPUTED: begin
parseStaticFieldValue(foundField, foundField.parentType.getStaticBlock());
end;
end;
foundValue := foundField.value;
if foundField.isFinal() and (foundValue <> nil) then begin
child1.setData(before, foundValue.&type, LOAD_CONST, foundValue);
goto continue_label0;
end;
child1.setData(before, foundField.&type, LOAD_STATIC, foundField);
goto continue_label0;
end;
if Lang.isInstance(foundFieldoid, &Property) then begin
foundProperty := &Property(Lang.cast(foundFieldoid, &Property));
if context < 0 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-be.access.property'), [
CoObject.create(foundProperty)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
resultNode := __code.createAndAppendNode(parent);
if foundProperty.hasRead() then begin
if isUseSuper then begin
if foundProperty.isAbstract() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.direct-access-abstract.property.read'), [
CoObject.create(foundProperty)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
resultNode.setData(before, foundProperty.&type, READ_SPECIAL, foundProperty);
end else begin
resultNode.setData(before, foundProperty.&type, READ_PROPERTY, foundProperty);
end;
end else begin
if source.getLexemeKind(position + 1) <> EQUAL then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.access.property-write-only.read'), [
CoObject.create(foundProperty)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if isUseSuper then begin
if foundProperty.isAbstract() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.direct-access-abstract.property.write'), [
CoObject.create(foundProperty)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
resultNode.setData(before, foundProperty.&type, WRITE_SPECIAL, foundProperty);
end else begin
resultNode.setData(before, foundProperty.&type, WRITE_PROPERTY, foundProperty);
end;
end;
__code.moveNode(child1, resultNode, 0);
child1 := resultNode;
goto continue_label0;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.fieldoid'), [
CoObject.create(dereferenceClassType), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if (kind <> 0) or (resolvedMember is Callable) then begin
if source.getLexemeKind(position + 1) <> PARENTH_OPENED then begin
if kind <> 0 then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-parenth'));
exception.source := source;
exception.position := position + 1;
raise exception;
end;
foundInterrupts := dereferenceClassType.findInterrupts(name, enclosingClassType);
foundLength := system.length(foundInterrupts);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.interrupt'), [
CoObject.create(dereferenceClassType), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundInterrupt := foundInterrupts[0];
if not foundInterrupt.isVisibleFrom(enclosingClassType, impliedParentClassType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.interrupt'), [
CoAnsiString.create(enclosingClassType.specialSimpleName), CoObject.create(foundInterrupt)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.interrupt'), [
CoAnsiString.create(dereferenceClassType.specialCanonicalName + '.' + name)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if context > 0 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-be.access.static-method'), [
CoObject.create(foundInterrupt)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
child1.setData(before, fldTypeLong, LOAD_INTERRUPT, foundInterrupt);
goto continue_label0;
end;
resultNode := __code.createAndAppendNode(parent);
inc(position, 2);
if source.getLexemeKind(position) <> PARENTH_CLOSED then repeat
position := parseExpression(resultNode, source, position, isStaticOnly);
requiresValue(resultNode.readComponent(-1));
case source.getLexemeKind(position) of
PARENTH_CLOSED:
break;
COMMA:
inc(position);
else
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
until false;
length := resultNode.getLength();
if length <= 0 then case kind of
O_SCAL_ADD:
kind := O_SCAL_POS;
O_SCAL_SUB:
kind := O_SCAL_NEG;
O_VECT_ADD:
kind := O_VECT_POS;
O_VECT_SUB:
kind := O_VECT_NEG;
end;
arguments := Type_Array1d(&Array.newTObject1d(length));
for index := 0 to length - 1 do arguments[index] := resultNode.readComponent(index).&type;
if kind <> 0 then begin
foundCallables := Callable_Array1d(dereferenceClassType.findOperators(kind, arguments, enclosingClassType));
end else begin
foundCallables := Callable_Array1d(dereferenceClassType.findMethods(name, arguments, enclosingClassType));
end;
foundLength := system.length(foundCallables);
if foundLength < 1 then begin
if kind <> 0 then begin
resource := AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereferenceClassType), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(kind))
]
);
end else begin
resource := AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.method'), [
CoObject.create(dereferenceClassType), CoAnsiString.create(name)
]
);
end;
exception := TextSourceException.create(resource);
exception.source := source;
exception.position := before;
raise exception;
end;
foundCallable := foundCallables[0];
if foundCallable.isInterrupt() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.invoke-interrupt'), [
CoObject.create(foundCallable)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundCallable.isConvertableArguments(arguments) then begin
if kind <> 0 then begin
resource := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator');
end else begin
resource := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.method');
end;
exception := TextSourceException.create(AnsiString.format(resource, [ CoObject.create(foundCallable), CoAnsiString.create(ArgumentArray.toString(arguments)) ]));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundCallable.isVisibleFrom(enclosingClassType, impliedParentClassType) then begin
if kind <> 0 then begin
resource := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator');
end else begin
resource := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.method');
end;
exception := TextSourceException.create(AnsiString.format(resource, [ CoAnsiString.create(enclosingClassType.specialSimpleName), CoObject.create(foundCallable) ]));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
if kind <> 0 then begin
resource := AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereferenceClassType.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(kind) + foundCallable.arguments.toString())
]
);
end else begin
resource := AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.method'), [
CoAnsiString.create(dereferenceClassType.toString() + '.' + name + foundCallable.arguments.toString())
]
);
end;
exception := TextSourceException.create(resource);
exception.source := source;
exception.position := before;
raise exception;
end;
if isUseSuper and foundCallable.isAbstract() then begin
if kind <> 0 then begin
resource := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.direct-access-abstract.operator');
end else begin
resource := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.direct-access-abstract.method');
end;
exception := TextSourceException.create(AnsiString.format(resource, [ CoObject.create(foundCallable) ]));
exception.source := source;
exception.position := before;
raise exception;
end;
foundArguments := foundCallable.arguments;
for index := 0 to length - 1 do cast(resultNode.readComponent(index), foundArguments.readComponent(index).&type);
if context < 0 then begin
if not foundCallable.isStatic() then begin
if kind <> 0 then begin
resource := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-be.access.operator');
end else begin
resource := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-be.access.instance-method');
end;
exception := TextSourceException.create(AnsiString.format(resource, [ CoObject.create(foundCallable) ]));
exception.source := source;
exception.position := before;
raise exception;
end;
resultNode.setData(before, foundCallable.&type, INVOKE_STATIC, foundCallable);
__code.removeNode(child1);
child1 := resultNode;
goto continue_label0;
end;
if foundCallable.isStatic() then begin
if context > 0 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-be.access.static-method'), [
CoObject.create(foundCallable)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
resultNode.setData(before, foundCallable.&type, INVOKE_STATIC, foundCallable);
__code.removeNode(child1);
child1 := resultNode;
goto continue_label0;
end;
if isUseSuper then begin
instruction := INVOKE_SPECIAL;
end else begin
instruction := invokeInstructionFor(foundCallable, dereferenceClassType);
end;
resultNode.setData(before, foundCallable.&type, instruction, foundCallable);
__code.moveNode(child1, resultNode, 0);
child1 := resultNode;
goto continue_label0;
end;
if kind <> 0 then begin
resource := AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereferenceClassType), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(kind))
]
);
end else begin
resource := AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.member'), [
CoObject.create(dereferenceClassType), CoAnsiString.create(name)
]
);
end;
exception := TextSourceException.create(resource);
exception.source := source;
exception.position := before;
raise exception;
end;
case operation of
PARENTH_OPENED: begin
if argument1Type is ru.malik.elaborarer.avtoo.lang.ClassType then begin
resultNode := __code.createAndAppendNode(parent);
dereferenceClassType := ru.malik.elaborarer.avtoo.lang.ClassType(argument1Type);
if isUseSuper then begin
impliedParentClassType := enclosingClassType;
end else begin
impliedParentClassType := dereferenceClassType;
end;
inc(position);
if source.getLexemeKind(position) <> PARENTH_CLOSED then repeat
position := parseExpression(resultNode, source, position, isStaticOnly);
requiresValue(resultNode.readComponent(-1));
case source.getLexemeKind(position) of
PARENTH_CLOSED:
break;
COMMA:
inc(position);
else
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
until false;
length := resultNode.getLength();
arguments := Type_Array1d(&Array.newTObject1d(length));
for index := 0 to length - 1 do arguments[index] := resultNode.readComponent(index).&type;
foundOperators := dereferenceClassType.findOperators(INVOKE_VIRTUAL, arguments, enclosingClassType);
foundLength := system.length(foundOperators);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereferenceClassType), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(INVOKE_VIRTUAL))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundOperator := foundOperators[0];
if not foundOperator.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator'), [
CoObject.create(foundOperator), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundOperator.isVisibleFrom(enclosingClassType, impliedParentClassType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosingClassType.specialSimpleName), CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereferenceClassType.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(INVOKE_VIRTUAL) + foundOperator.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if isUseSuper and foundOperator.isAbstract() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.direct-access-abstract.operator'), [
CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundArguments := foundOperator.arguments;
for index := 0 to length - 1 do cast(resultNode.readComponent(index), foundArguments.readComponent(index).&type);
if isUseSuper then begin
instruction := INVOKE_SPECIAL;
end else begin
instruction := invokeInstructionFor(foundOperator, dereferenceClassType);
end;
resultNode.setData(before, foundOperator.&type, instruction, foundOperator);
__code.moveNode(child1, resultNode, 0);
child1 := resultNode;
goto continue_label0;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'operator.not-applicable-to-type'), [
CoObject.create(argument1Type), CoAnsiString.create(&Operator.kindToSymbol(INVOKE_VIRTUAL))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
BRACKET_OPENED: begin
if (argument1Type is PrimitiveType) and argument1Type.isVector() then begin
typeInt := fldTypeInt;
vectorMainType := PrimitiveType(argument1Type);
vectorBaseType := vectorMainType.vectorBaseType;
position := parseExpression(parent, source, position + 1, isStaticOnly);
if source.getLexemeKind(position) <> BRACKET_CLOSED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-bracket'));
exception.source := source;
exception.position := position;
raise exception;
end;
child2 := parent.readComponent(-1);
requiresValue(child2);
argument2Type := child2.&type;
if not typeInt.isConvertableFrom(argument2Type) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.type'), [
CoObject.create(argument2Type), CoObject.create(typeInt)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
child2 := cast(child2, typeInt);
if child2.instruction = LOAD_CONST then begin
index := child2.operandC.asInt();
if (index < 0) or (index >= vectorMainType.vectorLength) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'out-of-range.vector-index'), [
CoAnsiString.create(CoInt.toString(index))
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if child1.instruction = LOAD_CONST then begin
case vectorBaseType.kind shr 2 of
TYP_DOUBLE shr 2:
child1.setData(child1.position, vectorBaseType, LOAD_CONST, fldConstantFactory.createDouble(child1.operandC.asDouble8()[index]));
TYP_FLOAT shr 2:
child1.setData(child1.position, vectorBaseType, LOAD_CONST, fldConstantFactory.createFloat(child1.operandC.asFloat8()[index]));
TYP_BYTE shr 2:
child1.setData(child1.position, vectorBaseType, LOAD_CONST, fldConstantFactory.createByte(child1.operandC.asByte8()[index]));
TYP_SHORT shr 2:
child1.setData(child1.position, vectorBaseType, LOAD_CONST, fldConstantFactory.createShort(child1.operandC.asShort8()[index]));
TYP_INT shr 2:
child1.setData(child1.position, vectorBaseType, LOAD_CONST, fldConstantFactory.createInt(child1.operandC.asInt8()[index]));
TYP_LONG shr 2:
child1.setData(child1.position, vectorBaseType, LOAD_CONST, fldConstantFactory.createLong(child1.operandC.asLong8()[index]));
end;
__code.removeNode(child2);
goto continue_label0;
end;
end;
resultNode := __code.createAndAppendNode(parent).setData(-1, vectorBaseType, READ_ELEMENT, vectorMainType);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
goto continue_label0;
end;
if argument1Type is ArrayType then begin
typeInt := fldTypeInt;
componentType := ArrayType(argument1Type).componentType;
position := parseExpression(parent, source, position + 1, isStaticOnly);
if source.getLexemeKind(position) <> BRACKET_CLOSED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-bracket'));
exception.source := source;
exception.position := position;
raise exception;
end;
child2 := parent.readComponent(-1);
requiresValue(child2);
argument2Type := child2.&type;
if not typeInt.isConvertableFrom(argument2Type) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.type'), [
CoObject.create(argument2Type), CoObject.create(typeInt)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
child2 := cast(child2, typeInt);
resultNode := __code.createAndAppendNode(parent).setData(-1, componentType, READ_COMPONENT, componentType);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
goto continue_label0;
end;
if argument1Type is ru.malik.elaborarer.avtoo.lang.ClassType then begin
dereferenceClassType := ru.malik.elaborarer.avtoo.lang.ClassType(argument1Type);
if isUseSuper then begin
impliedParentClassType := enclosingClassType;
end else begin
impliedParentClassType := dereferenceClassType;
end;
position := parseExpression(parent, source, position + 1, isStaticOnly);
if source.getLexemeKind(position) <> BRACKET_CLOSED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-bracket'));
exception.source := source;
exception.position := position;
raise exception;
end;
child2 := parent.readComponent(-1);
requiresValue(child2);
resultNode := __code.createAndAppendNode(parent);
if source.getLexemeKind(position + 1) = EQUAL then begin
resultNode.setData(-1, nil, INVOKE_VIRTUAL, TableItem(nil));
end else begin
arguments := [ child2.&type ];
foundOperators := dereferenceClassType.findOperators(READ_COMPONENT, arguments, enclosingClassType);
foundLength := system.length(foundOperators);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereferenceClassType), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(READ_COMPONENT))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundOperator := foundOperators[0];
if not foundOperator.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator'), [
CoObject.create(foundOperator), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundOperator.isVisibleFrom(enclosingClassType, impliedParentClassType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosingClassType.specialSimpleName), CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereferenceClassType.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(READ_COMPONENT) + foundOperator.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if isUseSuper and foundOperator.isAbstract() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.direct-access-abstract.operator'), [
CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
child2 := cast(child2, foundOperator.arguments.readComponent(0).&type);
if isUseSuper then begin
instruction := INVOKE_SPECIAL;
end else begin
instruction := invokeInstructionFor(foundOperator, dereferenceClassType);
end;
resultNode.setData(-1, foundOperator.&type, instruction, foundOperator);
end;
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
goto continue_label0;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'operator.not-applicable-to-type'), [
CoObject.create(argument1Type), CoAnsiString.create(&Operator.kindToSymbol(READ_COMPONENT))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
INC_LOCAL,
DEC_LOCAL: begin
instruction := child1.instruction;
case instruction of
LOAD_LOCAL: begin
foundLocal := child1.operand1 as Local;
if foundLocal.isFinal() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.access.local-final.write'), [
CoObject.create(foundLocal)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
argument1Type := foundLocal.&type;
if not(argument1Type is PrimitiveType) or not argument1Type.isNumeric() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.1'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if operation = INC_LOCAL then begin
instruction := INC_POST_LOAD_LOCAL;
end else begin
instruction := DEC_POST_LOAD_LOCAL;
end;
child1.setData(child1.position, argument1Type, instruction, foundLocal);
goto continue_label0;
end;
LOAD_STATIC: begin
foundField := child1.operand1 as Field;
if foundField.isFinal() and (not(enclosingCallable is ClassInit) or (foundField.parentType <> enclosingClassType) or (foundField.value <> nil)) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.access.field-final.write'), [
CoObject.create(foundField)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
argument1Type := foundField.&type;
if not(argument1Type is PrimitiveType) or not argument1Type.isNumeric() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.1'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
__code.createAndAppendNode(child1).setData(child1.position, argument1Type, LOAD_STATIC, foundField);
delta := appendIncrementCode(child1, PrimitiveType(argument1Type), operation = INC_LOCAL);
__code.createAndPrependNode(delta).setData(-1, nil, DUP1, argument1Type);
child1.setData(-1, argument1Type, STORE_STATIC, foundField);
goto continue_label0;
end;
READ_FIELD,
READ_SPECIAL,
READ_PROPERTY: begin
foundFieldoid := child1.operand1 as TypedMember;
if Lang.isInstance(foundFieldoid, &Property) then begin
if not &Property(Lang.cast(foundFieldoid, &Property)).hasWrite() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.access.property-read-only.write'), [
CoSimple.create(foundFieldoid)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
end else begin
load := child1.readComponent(0);
if
foundFieldoid.isFinal() and (
not(enclosingCallable is InstInit) or (foundFieldoid.parentType <> enclosingClassType) or
(load.instruction <> LOAD_LOCAL) or (load.operand1 <> enclosingCallable.arguments.thisArgument)
)
then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.access.field-final.write'), [
CoSimple.create(foundFieldoid)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
end;
argument1Type := foundFieldoid.&type;
if not(argument1Type is PrimitiveType) or not argument1Type.isNumeric() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.1'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundItem := TableItem(Lang.cast(foundFieldoid, TableItem));
read := __code.createAndAppendNode(child1).setData(child1.position, argument1Type, instruction, foundItem);
__code.createAndAppendNode(read).setData(-1, nil, DUP1, fldTypeObject);
delta := appendIncrementCode(child1, PrimitiveType(argument1Type), operation = INC_LOCAL);
__code.createAndPrependNode(delta).setData(-1, nil, DUP1X1, argument1Type);
child1.setData(-1, argument1Type, instruction + A_DELTA, foundItem);
goto continue_label0;
end;
READ_COMPONENT: begin
argument1Type := child1.operand1 as &Type;
if not(argument1Type is PrimitiveType) or not argument1Type.isNumeric() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.1'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
read := __code.createAndAppendNode(child1).setData(child1.position, argument1Type, READ_COMPONENT, argument1Type);
__code.createAndAppendNode(read).setData(-1, nil, DUP2, fldTypeInt);
delta := appendIncrementCode(child1, PrimitiveType(argument1Type), operation = INC_LOCAL);
__code.createAndPrependNode(delta).setData(-1, nil, DUP1X2, argument1Type);
child1.setData(-1, argument1Type, WRITE_COMPONENT, argument1Type);
goto continue_label0;
end;
INVOKE_SERVICE,
INVOKE_SPECIAL,
INVOKE_VIRTUAL: begin
foundItem := child1.operand1;
if foundItem is &Operator then begin
foundReadOperator := &Operator(foundItem);
if foundReadOperator.kind = READ_COMPONENT then begin
argument1Type := foundReadOperator.&type;
if not(argument1Type is PrimitiveType) or not argument1Type.isNumeric() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.1'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
load := child1.readComponent(0);
dereferenceClassType := load.&type as ru.malik.elaborarer.avtoo.lang.ClassType;
isUseSuper := load.useSuper;
if isUseSuper then begin
impliedParentClassType := enclosingClassType;
end else begin
impliedParentClassType := dereferenceClassType;
end;
arguments := [ foundReadOperator.arguments.readComponent(0).&type, argument1Type ];
foundOperators := dereferenceClassType.findOperators(WRITE_COMPONENT, arguments, enclosingClassType);
if system.length(foundOperators) <> 1 then begin
foundWriteOperator := nil;
end else begin
foundWriteOperator := foundOperators[0];
end;
if (foundWriteOperator = nil) or not foundWriteOperator.isIdentityArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-found.operator'), [
CoObject.create(dereferenceClassType), CoAnsiString.create(&Operator.kindToSymbol(WRITE_COMPONENT) + ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundWriteOperator.isVisibleFrom(enclosingClassType, impliedParentClassType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosingClassType.specialSimpleName), CoObject.create(foundWriteOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if isUseSuper and foundWriteOperator.isAbstract() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.direct-access-abstract.operator'), [
CoObject.create(foundWriteOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
read := __code.createAndAppendNode(child1).setData(child1.position, argument1Type, instruction, foundReadOperator);
__code.createAndAppendNode(read).setData(-1, nil, DUP2, arguments[0]);
delta := appendIncrementCode(child1, PrimitiveType(argument1Type), operation = INC_LOCAL);
__code.createAndPrependNode(delta).setData(-1, nil, DUP1X2, argument1Type);
if isUseSuper then begin
instruction := INVOKE_SPECIAL;
end else begin
instruction := invokeInstructionFor(foundWriteOperator, dereferenceClassType);
end;
child1.setData(-1, argument1Type, instruction, foundWriteOperator);
goto continue_label0;
end;
end;
end;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'applicable.operator.assignment'), [
CoUnicodeString.create(source.getLexemeString(before))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
else
break;
end;
continue_label0:
isImplicitPeriod := false;
isUseSuper := false;
inc(position);
until false;
result := position;
end;
function ImmediateBuilder.parsePrimary(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
label
break_label0;
var
condition: boolean;
isConstant: boolean;
isImplicitPeriod: boolean;
kind: int;
index: int;
length: int;
before: int;
operation: int;
instruction: int;
foundLength: int;
dimCountTotal: int;
dimCountCreate: int;
vectorResultLength: int;
name: AnsiString;
resource: AnsiString;
arguments: Type_Array1d;
foundFieldoids: Fieldoid_Array1d;
foundConstructors: InstInit_Array1d;
write: Node;
value: Node;
__code: Code;
__array: Node;
__method: Node;
typeInt: &Type;
resultNode: Node;
fieldType: &Type;
valueType: &Type;
foundType: &Type;
foundWith: Local;
foundLocal: Local;
resultType: &Type;
typeInt01d: &Type;
__constructor: Node;
componentType: &Type;
foundValue: Constant;
foundItem: TableItem;
foundMethod: Callable;
foundPackage: Package;
factory: ConstantFactory;
foundProperty: &Property;
foundConstructor: InstInit;
foundFieldoid: TypedMember;
foundArguments: ArgumentArray;
vectorBaseType: PrimitiveType;
vectorResultType: PrimitiveType;
operatorHolder: ImmediateBuilderItemHolder;
tableItemHolder: ImmediateBuilderItemHolder;
resultTypeHolder: ImmediateBuilderItemHolder;
foundClassType: ru.malik.elaborarer.avtoo.lang.ClassType;
objectResultType: ru.malik.elaborarer.avtoo.lang.ClassType;
enclosingCallable: ru.malik.elaborarer.avtoo.lang.Callable;
enclosingClassType: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
isImplicitPeriod := false;
operation := source.getLexemeKind(position);
__code := parent.parentCode;
enclosingCallable := __code.parentCallable;
enclosingClassType := enclosingCallable.parentType;
case operation of
PARENTH_OPENED: begin
position := parseExpression(parent, source, position + 1, isStaticOnly);
if source.getLexemeKind(position) <> PARENTH_CLOSED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
requiresValue(parent.readComponent(-1));
end;
EXP_SUPER: begin
if isStaticOnly then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-reference.this'));
exception.source := source;
exception.position := position;
raise exception;
end;
if enclosingCallable.isStatic() then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-use.static.this'));
exception.source := source;
exception.position := position;
raise exception;
end;
if enclosingClassType.isHelper() then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-use.helper.super'));
exception.source := source;
exception.position := position;
raise exception;
end;
foundClassType := enclosingClassType.getSuperclassType();
if foundClassType = nil then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-use.super'), [
CoAnsiString.create(enclosingClassType.specialSimpleName)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
__code.createAndAppendNode(parent).setData(position, foundClassType, LOAD_LOCAL, enclosingCallable.arguments.thisArgument).useSuper := true;
end;
EXP_THIS: begin
if isStaticOnly then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-reference.this'));
exception.source := source;
exception.position := position;
raise exception;
end;
if enclosingCallable.isStatic() then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-use.static.this'));
exception.source := source;
exception.position := position;
raise exception;
end;
__code.createAndAppendNode(parent).setData(position, enclosingClassType.getRealType(), LOAD_LOCAL, enclosingCallable.arguments.thisArgument);
end;
EXP_NEW: begin
before := position;
inc(position);
resultTypeHolder := getItemHolder();
position := parseTypeName(source, position, enclosingClassType, resultTypeHolder);
resultType := resultTypeHolder.resultType;
if resultType is ArrayType then begin
if source.getLexemeKind(position) <> CURLY_OPENED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
resultType.makeCompilable();
resultNode := __code.createAndAppendNode(parent);
factory := fldConstantFactory;
inc(position);
if source.getLexemeKind(position) <> CURLY_CLOSED then begin
componentType := ArrayType(resultType).componentType;
typeInt := fldTypeInt;
index := 0;
repeat
write := __code.createAndAppendNode(resultNode).setData(-1, nil, WRITE_COMPONENT, componentType);
__code.createAndAppendNode(write).setData(position, resultType, DUP1, resultType);
__code.createAndAppendNode(write).setData(-1, typeInt, LOAD_CONST, factory.createInt(index));
position := parseExpression(write, source, position, isStaticOnly);
value := write.readComponent(-1);
requiresValue(value);
valueType := value.&type;
if not componentType.isConvertableFrom(valueType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.type'), [
CoObject.create(valueType), CoObject.create(componentType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
cast(value, componentType);
case source.getLexemeKind(position) of
CURLY_CLOSED:
break;
COMMA:
inc(position);
else
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
inc(index);
until false;
end;
index := resultNode.getLength();
resultNode.setData(before, resultType, NEW_ARRAY, resultType, factory.createInt(index));
while index > 0 do begin
dec(index);
write := resultNode.readComponent(index);
value := write.readComponent(-1);
if (value.instruction = LOAD_CONST) and value.operandC.isDefaultValue() then __code.removeNode(write);
end;
goto break_label0;
end;
if source.getLexemeKind(position) = BRACKET_OPENED then begin
if resultType.isVoid() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'type.not-suitable.array-components'), [
CoObject.create(resultType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
dimCountCreate := 0;
typeInt := fldTypeInt;
resultNode := __code.createAndAppendNode(parent);
repeat
inc(dimCountCreate);
position := parseExpression(resultNode, source, position + 1, isStaticOnly);
if source.getLexemeKind(position) <> BRACKET_CLOSED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-bracket'));
exception.source := source;
exception.position := position;
raise exception;
end;
value := resultNode.readComponent(-1);
requiresValue(value);
valueType := value.&type;
if not typeInt.isConvertableFrom(valueType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.type'), [
CoObject.create(valueType), CoObject.create(typeInt)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
cast(value, typeInt);
if (dimCountCreate >= LIMIT_DIMENSIONS_COUNT) or (source.getLexemeKind(position + 1) <> BRACKET_OPENED) or (source.getLexemeKind(position + 2) = BRACKET_CLOSED) then break;
inc(position);
until false;
dimCountTotal := dimCountCreate;
while (dimCountTotal < LIMIT_DIMENSIONS_COUNT) and (source.getLexemeKind(position + 1) = BRACKET_OPENED) and (source.getLexemeKind(position + 2) = BRACKET_CLOSED) do begin
inc(position, 2);
inc(dimCountTotal);
end;
resultType := acquireArrayType(resultType, dimCountTotal);
resultType.makeCompilable();
if dimCountCreate <= 1 then begin
resultNode.setData(before, resultType, NEW_ARRAY_MONO, resultType);
goto break_label0;
end;
resultNode.setData(before, resultType, NEW_ARRAY_MULTI, resultType);
typeInt01d := getArrayType(typeInt);
typeInt01d.makeCompilable();
factory := fldConstantFactory;
__array := __code.createAndAppendNode(resultNode).setData(before, typeInt01d, NEW_ARRAY, typeInt01d, factory.createInt(dimCountCreate));
for index := dimCountCreate - 1 downto 0 do begin
value := resultNode.readComponent(index);
write := __code.createAndPrependNode(__array).setData(-1, nil, WRITE_COMPONENT, typeInt);
__code.createAndAppendNode(write).setData(-1, typeInt01d, DUP1, typeInt01d);
__code.createAndAppendNode(write).setData(-1, typeInt, LOAD_CONST, factory.createInt(index));
__code.moveNode(value, write, 2);
end;
goto break_label0;
end;
if (resultType is PrimitiveType) and resultType.isVector() then begin
if source.getLexemeKind(position) <> CURLY_OPENED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
isConstant := true;
resultNode := __code.createAndAppendNode(parent);
vectorResultType := PrimitiveType(resultType);
vectorBaseType := vectorResultType.vectorBaseType;
vectorResultLength := vectorResultType.vectorLength;
index := 0;
repeat
position := parseExpression(resultNode, source, position + 1, isStaticOnly);
value := resultNode.readComponent(-1);
requiresValue(value);
valueType := value.&type;
if not vectorBaseType.isConvertableFrom(valueType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.type'), [
CoObject.create(valueType), CoObject.create(vectorBaseType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if cast(value, vectorBaseType).instruction <> LOAD_CONST then isConstant := false;
inc(index);
if index >= vectorResultLength then break;
if source.getLexemeKind(position) <> COMMA then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.comma'));
exception.source := source;
exception.position := position;
raise exception;
end;
until false;
if source.getLexemeKind(position) <> CURLY_CLOSED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
if not isConstant then begin
resultNode.setData(before, resultType, NEW_VECTOR, resultType);
goto break_label0;
end;
case vectorResultType.kind of
TYP_DOUBLE2:
resultNode.setData(before, resultType, LOAD_CONST, fldConstantFactory.createDouble2(Vector.newDouble2(
resultNode.readComponent(0).operandC.asDouble(), resultNode.readComponent(1).operandC.asDouble()
)));
TYP_DOUBLE4:
resultNode.setData(before, resultType, LOAD_CONST, fldConstantFactory.createDouble4(Vector.newDouble4(
resultNode.readComponent(0).operandC.asDouble(), resultNode.readComponent(1).operandC.asDouble(),
resultNode.readComponent(2).operandC.asDouble(), resultNode.readComponent(3).operandC.asDouble()
)));
TYP_DOUBLE8:
resultNode.setData(before, resultType, LOAD_CONST, fldConstantFactory.createDouble8(Vector.newDouble8(
resultNode.readComponent(0).operandC.asDouble(), resultNode.readComponent(1).operandC.asDouble(),
resultNode.readComponent(2).operandC.asDouble(), resultNode.readComponent(3).operandC.asDouble(),
resultNode.readComponent(4).operandC.asDouble(), resultNode.readComponent(5).operandC.asDouble(),
resultNode.readComponent(6).operandC.asDouble(), resultNode.readComponent(7).operandC.asDouble()
)));
TYP_FLOAT2:
resultNode.setData(before, resultType, LOAD_CONST, fldConstantFactory.createFloat2(Vector.newFloat2(
resultNode.readComponent(0).operandC.asFloat(), resultNode.readComponent(1).operandC.asFloat()
)));
TYP_FLOAT4:
resultNode.setData(before, resultType, LOAD_CONST, fldConstantFactory.createFloat4(Vector.newFloat4(
resultNode.readComponent(0).operandC.asFloat(), resultNode.readComponent(1).operandC.asFloat(),
resultNode.readComponent(2).operandC.asFloat(), resultNode.readComponent(3).operandC.asFloat()
)));
TYP_FLOAT8:
resultNode.setData(before, resultType, LOAD_CONST, fldConstantFactory.createFloat8(Vector.newFloat8(
resultNode.readComponent(0).operandC.asFloat(), resultNode.readComponent(1).operandC.asFloat(),
resultNode.readComponent(2).operandC.asFloat(), resultNode.readComponent(3).operandC.asFloat(),
resultNode.readComponent(4).operandC.asFloat(), resultNode.readComponent(5).operandC.asFloat(),
resultNode.readComponent(6).operandC.asFloat(), resultNode.readComponent(7).operandC.asFloat()
)));
TYP_BYTE2:
resultNode.setData(before, resultType, LOAD_CONST, fldConstantFactory.createByte2(Vector.newByte2(
resultNode.readComponent(0).operandC.asByte(), resultNode.readComponent(1).operandC.asByte()
)));
TYP_BYTE4:
resultNode.setData(before, resultType, LOAD_CONST, fldConstantFactory.createByte4(Vector.newByte4(
resultNode.readComponent(0).operandC.asByte(), resultNode.readComponent(1).operandC.asByte(),
resultNode.readComponent(2).operandC.asByte(), resultNode.readComponent(3).operandC.asByte()
)));
TYP_BYTE8:
resultNode.setData(before, resultType, LOAD_CONST, fldConstantFactory.createByte8(Vector.newByte8(
resultNode.readComponent(0).operandC.asByte(), resultNode.readComponent(1).operandC.asByte(),
resultNode.readComponent(2).operandC.asByte(), resultNode.readComponent(3).operandC.asByte(),
resultNode.readComponent(4).operandC.asByte(), resultNode.readComponent(5).operandC.asByte(),
resultNode.readComponent(6).operandC.asByte(), resultNode.readComponent(7).operandC.asByte()
)));
TYP_SHORT2:
resultNode.setData(before, resultType, LOAD_CONST, fldConstantFactory.createShort2(Vector.newShort2(
resultNode.readComponent(0).operandC.asShort(), resultNode.readComponent(1).operandC.asShort()
)));
TYP_SHORT4:
resultNode.setData(before, resultType, LOAD_CONST, fldConstantFactory.createShort4(Vector.newShort4(
resultNode.readComponent(0).operandC.asShort(), resultNode.readComponent(1).operandC.asShort(),
resultNode.readComponent(2).operandC.asShort(), resultNode.readComponent(3).operandC.asShort()
)));
TYP_SHORT8:
resultNode.setData(before, resultType, LOAD_CONST, fldConstantFactory.createShort8(Vector.newShort8(
resultNode.readComponent(0).operandC.asShort(), resultNode.readComponent(1).operandC.asShort(),
resultNode.readComponent(2).operandC.asShort(), resultNode.readComponent(3).operandC.asShort(),
resultNode.readComponent(4).operandC.asShort(), resultNode.readComponent(5).operandC.asShort(),
resultNode.readComponent(6).operandC.asShort(), resultNode.readComponent(7).operandC.asShort()
)));
TYP_INT2:
resultNode.setData(before, resultType, LOAD_CONST, fldConstantFactory.createInt2(Vector.newInt2(
resultNode.readComponent(0).operandC.asInt(), resultNode.readComponent(1).operandC.asInt()
)));
TYP_INT4:
resultNode.setData(before, resultType, LOAD_CONST, fldConstantFactory.createInt4(Vector.newInt4(
resultNode.readComponent(0).operandC.asInt(), resultNode.readComponent(1).operandC.asInt(),
resultNode.readComponent(2).operandC.asInt(), resultNode.readComponent(3).operandC.asInt()
)));
TYP_INT8:
resultNode.setData(before, resultType, LOAD_CONST, fldConstantFactory.createInt8(Vector.newInt8(
resultNode.readComponent(0).operandC.asInt(), resultNode.readComponent(1).operandC.asInt(),
resultNode.readComponent(2).operandC.asInt(), resultNode.readComponent(3).operandC.asInt(),
resultNode.readComponent(4).operandC.asInt(), resultNode.readComponent(5).operandC.asInt(),
resultNode.readComponent(6).operandC.asInt(), resultNode.readComponent(7).operandC.asInt()
)));
TYP_LONG2:
resultNode.setData(before, resultType, LOAD_CONST, fldConstantFactory.createLong2(Vector.newLong2(
resultNode.readComponent(0).operandC.asLong(), resultNode.readComponent(1).operandC.asLong()
)));
TYP_LONG4:
resultNode.setData(before, resultType, LOAD_CONST, fldConstantFactory.createLong4(Vector.newLong4(
resultNode.readComponent(0).operandC.asLong(), resultNode.readComponent(1).operandC.asLong(),
resultNode.readComponent(2).operandC.asLong(), resultNode.readComponent(3).operandC.asLong()
)));
TYP_LONG8:
resultNode.setData(before, resultType, LOAD_CONST, fldConstantFactory.createLong8(Vector.newLong8(
resultNode.readComponent(0).operandC.asLong(), resultNode.readComponent(1).operandC.asLong(),
resultNode.readComponent(2).operandC.asLong(), resultNode.readComponent(3).operandC.asLong(),
resultNode.readComponent(4).operandC.asLong(), resultNode.readComponent(5).operandC.asLong(),
resultNode.readComponent(6).operandC.asLong(), resultNode.readComponent(7).operandC.asLong()
)));
end;
__code.removeChilds(resultNode);
goto break_label0;
end;
if resultType.isAbstract() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.instantiate.abstract-type'), [
CoObject.create(resultType)
]
));
exception.source := source;
exception.position := before + 1;
raise exception;
end;
if resultType is ru.malik.elaborarer.avtoo.lang.ClassType then begin
if source.getLexemeKind(position) <> PARENTH_OPENED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
resultType.makeCompilable();
resultNode := __code.createAndAppendNode(parent).setData(before, resultType, NEW_INSTANCE, resultType);
__constructor := __code.createAndAppendNode(resultNode);
objectResultType := ru.malik.elaborarer.avtoo.lang.ClassType(resultType);
inc(position);
if source.getLexemeKind(position) <> PARENTH_CLOSED then repeat
position := parseExpression(__constructor, source, position, isStaticOnly);
requiresValue(__constructor.readComponent(-1));
case source.getLexemeKind(position) of
PARENTH_CLOSED:
break;
COMMA:
inc(position);
else
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
until false;
length := __constructor.getLength();
arguments := Type_Array1d(&Array.newTObject1d(length));
for index := 0 to length - 1 do arguments[index] := __constructor.readComponent(index).&type;
foundConstructors := objectResultType.findConstructors(arguments, enclosingClassType);
foundLength := system.length(foundConstructors);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-found.constructor'), [
CoObject.create(objectResultType), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before + 1;
raise exception;
end;
foundConstructor := foundConstructors[0];
if not foundConstructor.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.constructor'), [
CoObject.create(foundConstructor), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before + 1;
raise exception;
end;
if not foundConstructor.isVisibleFrom(enclosingClassType, objectResultType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.constructor'), [
CoAnsiString.create(enclosingClassType.specialSimpleName), CoObject.create(foundConstructor)
]
));
exception.source := source;
exception.position := before + 1;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.constructor'), [
CoAnsiString.create(objectResultType.specialCanonicalName + ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before + 1;
raise exception;
end;
foundArguments := foundConstructor.arguments;
for index := 0 to length - 1 do cast(__constructor.readComponent(index), foundArguments.readComponent(index).&type);
__code.createAndPrependNode(__constructor).setData(-1, resultType, DUP1, resultType);
__constructor.setData(before + 1, foundConstructor.&type, INVOKE_SPECIAL, foundConstructor);
foundMethod := fldTypeObject.getChildCallable('afterConstruction', Type_Array1d(nil));
if (foundMethod <> nil) and not foundMethod.isStatic() and foundMethod.&type.isVoid() and not foundMethod.canThrown() then begin
if foundMethod.visibility <= VIS_PRIVATE then begin
instruction := INVOKE_SPECIAL;
end else begin
instruction := INVOKE_VIRTUAL;
end;
__method := __code.createAndAppendNode(resultNode).setData(-1, fldTypeVoid, instruction, foundMethod);
__code.createAndPrependNode(__method).setData(-1, resultType, DUP1, resultType);
end;
if source.getLexemeKind(position + 1) = CURLY_OPENED then begin
inc(position, 2);
if source.getLexemeKind(position) <> CURLY_CLOSED then repeat
if source.getLexemeKind(position) <> L_NAME then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.name.fieldoid'), [
CoObject.create(objectResultType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
name := source.getLexemeString(position).toUTF8();
foundFieldoids := objectResultType.findFieldoids(name, enclosingClassType);
foundLength := system.length(foundFieldoids);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.fieldoid'), [
CoObject.create(objectResultType), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundFieldoid := foundFieldoids[0];
if not foundFieldoid.isVisibleFrom(enclosingClassType, objectResultType) then begin
if Lang.isInstance(foundFieldoid, &Property) then begin
resource := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.property');
end else begin
resource := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.field');
end;
exception := TextSourceException.create(AnsiString.format(resource, [ CoAnsiString.create(enclosingClassType.specialSimpleName), CoSimple.create(foundFieldoid) ]));
exception.source := source;
exception.position := position;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.fieldoid'), [
CoAnsiString.create(objectResultType.specialCanonicalName + '.' + name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
write := __code.createAndAppendNode(resultNode);
if Lang.isInstance(foundFieldoid, Field) then begin
if foundFieldoid.isStatic() or foundFieldoid.isFinal() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-be.instance-writeable-field'), [
CoSimple.create(foundFieldoid)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
write.setData(position + 1, nil, WRITE_FIELD, Field(Lang.cast(foundFieldoid, Field)));
end else
if Lang.isInstance(foundFieldoid, &Property) then begin
foundProperty := &Property(Lang.cast(foundFieldoid, &Property));
if foundFieldoid.isStatic() or not foundProperty.hasWrite() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-be.writeable-property'), [
CoSimple.create(foundFieldoid)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
write.setData(position + 1, nil, WRITE_PROPERTY, foundProperty);
end else begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.fieldoid'), [
CoObject.create(objectResultType), CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
inc(position);
if source.getLexemeKind(position) <> EQUAL then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.equals'));
exception.source := source;
exception.position := position;
raise exception;
end;
__code.createAndPrependNode(write).setData(position - 1, resultType, DUP1, resultType);
position := parseExpression(write, source, position + 1, isStaticOnly);
value := write.readComponent(-1);
requiresValue(value);
fieldType := foundFieldoid.&type;
valueType := value.&type;
if not fieldType.isConvertableFrom(valueType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.type'), [
CoObject.create(valueType), CoObject.create(fieldType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
cast(value, fieldType);
case source.getLexemeKind(position) of
CURLY_CLOSED:
break;
COMMA:
inc(position);
else
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
until false;
end;
goto break_label0;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.instantiate.type'), [
CoObject.create(resultType)
]
));
exception.source := source;
exception.position := before + 1;
raise exception;
end;
TYP_VOID,
TYP_BOOLEAN,
TYP_CHAR,
TYP_REAL,
TYP_DOUBLE,
TYP_DOUBLE2,
TYP_DOUBLE4,
TYP_DOUBLE8,
TYP_FLOAT,
TYP_FLOAT2,
TYP_FLOAT4,
TYP_FLOAT8,
TYP_BYTE,
TYP_BYTE2,
TYP_BYTE4,
TYP_BYTE8,
TYP_SHORT,
TYP_SHORT2,
TYP_SHORT4,
TYP_SHORT8,
TYP_INT,
TYP_INT2,
TYP_INT4,
TYP_INT8,
TYP_LONG,
TYP_LONG2,
TYP_LONG4,
TYP_LONG8,
L_NAME: begin
before := position;
name := source.getLexemeString(position).toUTF8();
tableItemHolder := getItemHolder();
tableItemHolder.helpersAllowed := true;
try
if operation <> L_NAME then begin
position := parseTypeName(source, before, enclosingClassType, tableItemHolder) - 1;
foundItem := tableItemHolder.resultItem;
end else begin
position := tryParseName(parent, source, before, name, tableItemHolder) - 1;
foundItem := tableItemHolder.resultItem;
if foundItem = nil then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.some-variable'), [
CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
end;
finally
tableItemHolder.helpersAllowed := false;
end;
if foundItem is Local then begin
foundLocal := Local(foundItem);
if foundLocal.isConstant() then begin
foundValue := foundLocal.value;
__code.createAndAppendNode(parent).setData(before, foundValue.&type, LOAD_CONST, foundValue);
goto break_label0;
end;
__code.createAndAppendNode(parent).setData(before, foundLocal.&type, LOAD_LOCAL, foundLocal);
goto break_label0;
end;
if foundItem is Member then begin
foundWith := tableItemHolder.resultWith;
if (foundWith = nil) or isStaticOnly then begin
__code.createAndAppendNode(parent).setData(before, nil, DCL_CLASS, enclosingClassType);
end else
if not foundWith.isConstant() then begin
__code.createAndAppendNode(parent).setData(before, foundWith.&type, LOAD_LOCAL, foundWith);
end else begin
foundValue := foundWith.value;
__code.createAndAppendNode(parent).setData(before, foundValue.&type, LOAD_CONST, foundValue);
end;
isImplicitPeriod := true;
position := before;
goto break_label0;
end;
if foundItem is ru.malik.elaborarer.avtoo.lang.ClassType then begin
foundClassType := ru.malik.elaborarer.avtoo.lang.ClassType(foundItem);
if not foundClassType.isVisibleFrom(enclosingClassType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.type'), [
CoAnsiString.create(foundClassType.specialCanonicalName)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
inc(position);
if source.getLexemeKind(position) <> PERIOD then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.period'));
exception.source := source;
exception.position := position;
raise exception;
end;
inc(position);
case source.getLexemeKind(position) of
EXP_SUPER: begin
if isStaticOnly then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-reference.this'));
exception.source := source;
exception.position := position;
raise exception;
end;
if enclosingCallable.isStatic() then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-use.static.this'));
exception.source := source;
exception.position := position;
raise exception;
end;
if enclosingClassType.isHelper() then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-use.helper.super'));
exception.source := source;
exception.position := position;
raise exception;
end;
if foundClassType.isHelper() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.some-variable'), [
CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
condition := foundClassType.isClass();
if condition and (enclosingClassType.getSuperclassType() <> foundClassType) or not condition and not enclosingClassType.isSuperservice(foundClassType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'type.not-direct-supertype'), [
CoAnsiString.create(enclosingClassType.specialSimpleName), CoObject.create(foundClassType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
__code.createAndAppendNode(parent).setData(before, foundClassType, LOAD_LOCAL, enclosingCallable.arguments.thisArgument).useSuper := true;
end;
DCL_CLASS: begin
foundClassType.makeCompilable();
__code.createAndAppendNode(parent).setData(before, fldTypeClass, LOAD_CONST, fldConstantFactory.createClass(foundClassType));
end;
L_NAME: begin
if foundClassType.isHelper() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.some-variable'), [
CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
__code.createAndAppendNode(parent).setData(before, nil, DCL_CLASS, foundClassType);
isImplicitPeriod := true;
end;
else
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.name.static-member'));
exception.source := source;
exception.position := position;
raise exception;
end;
goto break_label0;
end;
if foundItem is PrimitiveType then begin
inc(position);
if source.getLexemeKind(position) <> PERIOD then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.period'));
exception.source := source;
exception.position := position;
raise exception;
end;
inc(position);
if source.getLexemeKind(position) <> DCL_CLASS then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.class'));
exception.source := source;
exception.position := position;
raise exception;
end;
foundType := &Type(foundItem);
foundType.makeCompilable();
__code.createAndAppendNode(parent).setData(before, fldTypeClass, LOAD_CONST, fldConstantFactory.createClass(foundType));
goto break_label0;
end;
if foundItem is Package then begin
foundPackage := Package(foundItem);
if not foundPackage.isVisibleFrom(enclosingClassType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.package'), [
CoAnsiString.create(foundPackage.specialCanonicalName)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
inc(position);
if source.getLexemeKind(position) <> PERIOD then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.period'));
exception.source := source;
exception.position := position;
raise exception;
end;
inc(position);
if source.getLexemeKind(position) <> VIS_PACKAGE then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.package'));
exception.source := source;
exception.position := position;
raise exception;
end;
__code.createAndAppendNode(parent).setData(before, fldTypePackage, LOAD_CONST, fldConstantFactory.createPackage(foundPackage));
goto break_label0;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.some-variable'), [
CoAnsiString.create(name)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
DCL_OPERATOR: begin
operatorHolder := getItemHolder();
parseOperator(source, position + 1, operatorHolder);
kind := operatorHolder.resultKind;
tryParseName(parent, source, position, &Operator.kindToSpecialSimpleName(kind), operatorHolder);
foundItem := operatorHolder.resultItem;
if foundItem = nil then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.some-operator'), [
CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(kind))
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
foundWith := operatorHolder.resultWith;
if (foundWith = nil) or isStaticOnly then begin
__code.createAndAppendNode(parent).setData(position, nil, DCL_CLASS, enclosingClassType);
end else
if not foundWith.isConstant() then begin
__code.createAndAppendNode(parent).setData(position, foundWith.&type, LOAD_LOCAL, foundWith);
end else begin
foundValue := foundWith.value;
__code.createAndAppendNode(parent).setData(position, foundValue.&type, LOAD_CONST, foundValue);
end;
isImplicitPeriod := true;
end;
EXP_NULL: begin
__code.createAndAppendNode(parent).setData(position, fldTypeNull, LOAD_CONST, fldConstantFactory.createNull());
end;
DCL_CLASS: begin
__code.createAndAppendNode(parent).setData(position, fldTypeClass, LOAD_CONST, fldConstantFactory.createClass(enclosingClassType));
end;
VIS_PACKAGE: begin
__code.createAndAppendNode(parent).setData(position, fldTypePackage, LOAD_CONST, fldConstantFactory.createPackage(enclosingClassType.parentPackage));
end;
L_STRING: begin
__code.createAndAppendNode(parent).setData(position, fldTypeString, LOAD_CONST, fldConstantFactory.createString(source.getLexemeString(position)));
end;
L_BOOLEAN: begin
__code.createAndAppendNode(parent).setData(position, fldTypeBoolean, LOAD_CONST, fldConstantFactory.createBoolean(source.getLexemeBoolean(position)));
end;
L_CHAR: begin
__code.createAndAppendNode(parent).setData(position, getPrimitiveType(TYP_CHAR), LOAD_CONST, fldConstantFactory.createChar(source.getLexemeChar(position)));
end;
L_REAL: begin
__code.createAndAppendNode(parent).setData(position, getPrimitiveType(TYP_REAL), LOAD_CONST, fldConstantFactory.createReal(source.getLexemeReal(position)));
end;
L_DOUBLE: begin
__code.createAndAppendNode(parent).setData(position, getPrimitiveType(TYP_DOUBLE), LOAD_CONST, fldConstantFactory.createDouble(source.getLexemeDouble(position)));
end;
L_FLOAT: begin
__code.createAndAppendNode(parent).setData(position, getPrimitiveType(TYP_FLOAT), LOAD_CONST, fldConstantFactory.createFloat(source.getLexemeFloat(position)));
end;
L_BYTE: begin
__code.createAndAppendNode(parent).setData(position, getPrimitiveType(TYP_BYTE), LOAD_CONST, fldConstantFactory.createByte(byte(source.getLexemeInt(position))));
end;
L_SHORT: begin
__code.createAndAppendNode(parent).setData(position, getPrimitiveType(TYP_SHORT), LOAD_CONST, fldConstantFactory.createShort(short(source.getLexemeInt(position))));
end;
L_INT: begin
__code.createAndAppendNode(parent).setData(position, getPrimitiveType(TYP_INT), LOAD_CONST, fldConstantFactory.createInt(source.getLexemeInt(position)));
end;
L_LONG: begin
__code.createAndAppendNode(parent).setData(position, getPrimitiveType(TYP_LONG), LOAD_CONST, fldConstantFactory.createLong(source.getLexemeLong(position)));
end;
else
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'error.expression'));
exception.source := source;
exception.position := position;
raise exception;
end;
break_label0:
if not isImplicitPeriod then inc(position);
result := parsePostfix(parent, source, position, isStaticOnly, isImplicitPeriod);
end;
function ImmediateBuilder.parsePrefix(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
label
break_label0,
break_label1,
break_label2;
var
isUseSuper: boolean;
kind: int;
index: int;
before: int;
operation: int;
instruction: int;
foundLength: int;
arguments: Type_Array1d;
foundOperators: Operator_Array1d;
load: Node;
read: Node;
delta: Node;
child1: Node;
__code: Code;
newType: &Type;
resultNode: Node;
resultType: &Type;
foundLocal: Local;
foundField: Field;
operand1: Constant;
stack: ObjectVector;
argument1Type: &Type;
foundItem: TableItem;
resultValue: Constant;
typeInt: PrimitiveType;
factory: ConstantFactory;
foundOperator: &Operator;
foundFieldoid: TypedMember;
foundReadOperator: &Operator;
foundWriteOperator: &Operator;
item: ImmediateBuilderUnaryOperation;
newTypeHolder: ImmediateBuilderItemHolder;
enclosingCallable: ru.malik.elaborarer.avtoo.lang.Callable;
enclosingClassType: ru.malik.elaborarer.avtoo.lang.ClassType;
dereferenceClassType: ru.malik.elaborarer.avtoo.lang.ClassType;
impliedParentClassType: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
__code := parent.parentCode;
enclosingCallable := __code.parentCallable;
enclosingClassType := enclosingCallable.parentType;
stack := nil;
try
repeat
operation := source.getLexemeKind(position);
case operation of
INC_LOCAL,
DEC_LOCAL,
BOOL_NOT,
O_BIT_NOT,
O_VECT_LUP,
O_VECT_UUP,
O_VECT_PCK: begin
if stack = nil then stack := ObjectVector.create(true);
stack.append(ImmediateBuilderUnaryOperation.create(position, operation));
end;
O_SCAL_ADD: begin
if stack = nil then stack := ObjectVector.create(true);
stack.append(ImmediateBuilderUnaryOperation.create(position, O_SCAL_POS));
end;
O_SCAL_SUB: begin
if stack = nil then stack := ObjectVector.create(true);
stack.append(ImmediateBuilderUnaryOperation.create(position, O_SCAL_NEG));
end;
O_VECT_ADD: begin
if stack = nil then stack := ObjectVector.create(true);
stack.append(ImmediateBuilderUnaryOperation.create(position, O_VECT_POS));
end;
O_VECT_SUB: begin
if stack = nil then stack := ObjectVector.create(true);
stack.append(ImmediateBuilderUnaryOperation.create(position, O_VECT_NEG));
end;
PARENTH_OPENED: begin
before := position;
inc(position);
newTypeHolder := getItemHolder();
if source.getLexemeKind(position) <> L_NAME then begin
position := tryParseTypeName(source, position, enclosingClassType, newTypeHolder);
end else begin
position := tryParseName(parent, source, position, source.getLexemeString(position).toUTF8(), newTypeHolder);
end;
newType := newTypeHolder.resultType;
if (source.getLexemeKind(position) <> PARENTH_CLOSED) or (newType = nil) or not newType.isVisibleFrom(enclosingClassType) then begin
position := before;
break;
end;
if stack = nil then stack := ObjectVector.create(true);
stack.append(ImmediateBuilderUnaryOperation.create(before, CAST_TO, newType));
end;
else
break;
end;
inc(position);
until false;
position := parsePrimary(parent, source, position, isStaticOnly);
if stack = nil then begin
result := position;
exit;
end;
typeInt := fldTypeInt;
factory := fldConstantFactory;
child1 := parent.readComponent(-1);
for index := stack.getLength() - 1 downto 0 do begin
item := stack.readComponent(index) as ImmediateBuilderUnaryOperation;
argument1Type := child1.&type;
operation := item.operation;
before := item.position;
begin
if argument1Type is NullType then begin
if operation = CAST_TO then begin
newType := item.newType;
if newType is ru.malik.elaborarer.avtoo.lang.ClassType then begin
resultNode := __code.createAndAppendNode(parent).setData(before, newType, NOP);
__code.moveNode(child1, resultNode, 0);
child1 := resultNode;
continue;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.type-cast'), [
CoObject.create(argument1Type), CoObject.create(newType)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
goto break_label0;
end;
if argument1Type is ru.malik.elaborarer.avtoo.lang.ClassType then begin
dereferenceClassType := ru.malik.elaborarer.avtoo.lang.ClassType(argument1Type);
case operation of
O_BIT_NOT,
O_SCAL_POS,
O_SCAL_NEG,
O_VECT_LUP,
O_VECT_UUP,
O_VECT_PCK,
O_VECT_POS,
O_VECT_NEG: begin
foundOperators := dereferenceClassType.findOperators(operation, nil, enclosingClassType);
foundLength := system.length(foundOperators);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereferenceClassType), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(operation))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundOperator := foundOperators[0];
if not foundOperator.isConvertableArguments(nil) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator'), [
CoObject.create(foundOperator), CoAnsiString.create(ArgumentArray.toString(nil))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundOperator.isVisibleFrom(enclosingClassType, dereferenceClassType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosingClassType.specialSimpleName), CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereferenceClassType.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(operation) + foundOperator.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
resultNode := __code.createAndAppendNode(parent).setData(before, foundOperator.&type, invokeInstructionFor(foundOperator, dereferenceClassType), foundOperator);
__code.moveNode(child1, resultNode, 0);
child1 := resultNode;
continue;
end;
CAST_TO: begin
newType := item.newType;
if newType is ru.malik.elaborarer.avtoo.lang.ClassType then begin
if (newType = argument1Type) or newType.isAssignableFrom(argument1Type) then begin
resultNode := __code.createAndAppendNode(parent).setData(before, newType, NOP);
__code.moveNode(child1, resultNode, 0);
child1 := resultNode;
continue;
end;
if newType.isCompatibleWith(argument1Type) then begin
newType.makeCompilable();
resultNode := __code.createAndAppendNode(parent).setData(before, newType, CAST_TO, newType, argument1Type);
__code.moveNode(child1, resultNode, 0);
child1 := resultNode;
continue;
end;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.type-cast'), [
CoObject.create(argument1Type), CoObject.create(newType)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
end;
goto break_label0;
end;
if argument1Type is PrimitiveType then begin
kind := argument1Type.kind;
instruction := child1.instruction;
if kind = TYP_CHAR then begin
kind := TYP_INT;
argument1Type := typeInt;
end;
if instruction = LOAD_CONST then begin
operand1 := child1.operandC;
case operation of
BOOL_NOT: begin
if kind = TYP_BOOLEAN then begin
resultValue := factory.createBoolean(not operand1.asBoolean());
end else begin
goto break_label0;
end;
end;
O_BIT_NOT: begin
case kind of
TYP_BYTE:
resultValue := factory.createByte(not operand1.asByte());
TYP_BYTE2:
resultValue := factory.createByte2(not operand1.asByte2());
TYP_BYTE4:
resultValue := factory.createByte4(not operand1.asByte4());
TYP_BYTE8:
resultValue := factory.createByte8(not operand1.asByte8());
TYP_SHORT:
resultValue := factory.createShort(not operand1.asShort());
TYP_SHORT2:
resultValue := factory.createShort2(not operand1.asShort2());
TYP_SHORT4:
resultValue := factory.createShort4(not operand1.asShort4());
TYP_SHORT8:
resultValue := factory.createShort8(not operand1.asShort8());
TYP_INT:
resultValue := factory.createInt(not operand1.asInt());
TYP_INT2:
resultValue := factory.createInt2(not operand1.asInt2());
TYP_INT4:
resultValue := factory.createInt4(not operand1.asInt4());
TYP_INT8:
resultValue := factory.createInt8(not operand1.asInt8());
TYP_LONG:
resultValue := factory.createLong(not operand1.asLong());
TYP_LONG2:
resultValue := factory.createLong2(not operand1.asLong2());
TYP_LONG4:
resultValue := factory.createLong4(not operand1.asLong4());
TYP_LONG8:
resultValue := factory.createLong8(not operand1.asLong8());
else
goto break_label0;
end;
end;
O_SCAL_POS: begin
case kind of
TYP_REAL,
TYP_DOUBLE,
TYP_DOUBLE2,
TYP_DOUBLE4,
TYP_DOUBLE8,
TYP_FLOAT,
TYP_FLOAT2,
TYP_FLOAT4,
TYP_FLOAT8,
TYP_BYTE,
TYP_SHORT,
TYP_INT,
TYP_INT2,
TYP_INT4,
TYP_INT8,
TYP_LONG,
TYP_LONG2,
TYP_LONG4,
TYP_LONG8:
resultValue := operand1;
TYP_BYTE2:
resultValue := factory.createInt2(operand1.asByte2());
TYP_BYTE4:
resultValue := factory.createInt4(operand1.asByte4());
TYP_BYTE8:
resultValue := factory.createInt8(operand1.asByte8());
TYP_SHORT2:
resultValue := factory.createInt2(operand1.asShort2());
TYP_SHORT4:
resultValue := factory.createInt4(operand1.asShort4());
TYP_SHORT8:
resultValue := factory.createInt8(operand1.asShort8());
else
goto break_label0;
end;
end;
O_SCAL_NEG: begin
case kind of
TYP_REAL:
resultValue := factory.createReal(-operand1.asReal());
TYP_DOUBLE:
resultValue := factory.createDouble(-operand1.asDouble());
TYP_DOUBLE2:
resultValue := factory.createDouble2(-operand1.asDouble2());
TYP_DOUBLE4:
resultValue := factory.createDouble4(-operand1.asDouble4());
TYP_DOUBLE8:
resultValue := factory.createDouble8(-operand1.asDouble8());
TYP_FLOAT:
resultValue := factory.createFloat(-operand1.asFloat());
TYP_FLOAT2:
resultValue := factory.createFloat2(-operand1.asFloat2());
TYP_FLOAT4:
resultValue := factory.createFloat4(-operand1.asFloat4());
TYP_FLOAT8:
resultValue := factory.createFloat8(-operand1.asFloat8());
TYP_BYTE:
resultValue := factory.createIntegral(-operand1.asByte());
TYP_BYTE2:
resultValue := factory.createInt2(-operand1.asByte2());
TYP_BYTE4:
resultValue := factory.createInt4(-operand1.asByte4());
TYP_BYTE8:
resultValue := factory.createInt8(-operand1.asByte8());
TYP_SHORT:
resultValue := factory.createIntegral(-operand1.asShort());
TYP_SHORT2:
resultValue := factory.createInt2(-operand1.asShort2());
TYP_SHORT4:
resultValue := factory.createInt4(-operand1.asShort4());
TYP_SHORT8:
resultValue := factory.createInt8(-operand1.asShort8());
TYP_INT:
resultValue := factory.createIntegral(-operand1.asInt());
TYP_INT2:
resultValue := factory.createInt2(-operand1.asInt2());
TYP_INT4:
resultValue := factory.createInt4(-operand1.asInt4());
TYP_INT8:
resultValue := factory.createInt8(-operand1.asInt8());
TYP_LONG:
resultValue := factory.createLong(-operand1.asLong());
TYP_LONG2:
resultValue := factory.createLong2(-operand1.asLong2());
TYP_LONG4:
resultValue := factory.createLong4(-operand1.asLong4());
TYP_LONG8:
resultValue := factory.createLong8(-operand1.asLong8());
else
goto break_label0;
end;
end;
O_VECT_POS: begin
case kind of
TYP_DOUBLE,
TYP_DOUBLE2,
TYP_DOUBLE4,
TYP_DOUBLE8,
TYP_FLOAT,
TYP_FLOAT2,
TYP_FLOAT4,
TYP_FLOAT8,
TYP_BYTE,
TYP_BYTE2,
TYP_BYTE4,
TYP_BYTE8,
TYP_SHORT,
TYP_SHORT2,
TYP_SHORT4,
TYP_SHORT8,
TYP_INT,
TYP_INT2,
TYP_INT4,
TYP_INT8,
TYP_LONG,
TYP_LONG2,
TYP_LONG4,
TYP_LONG8:
resultValue := operand1;
else
goto break_label0;
end;
end;
O_VECT_NEG: begin
case kind of
TYP_DOUBLE:
resultValue := factory.createDouble(-operand1.asDouble());
TYP_DOUBLE2:
resultValue := factory.createDouble2(Vector.neg(operand1.asDouble2()));
TYP_DOUBLE4:
resultValue := factory.createDouble4(Vector.neg(operand1.asDouble4()));
TYP_DOUBLE8:
resultValue := factory.createDouble8(Vector.neg(operand1.asDouble8()));
TYP_FLOAT:
resultValue := factory.createFloat(-operand1.asFloat());
TYP_FLOAT2:
resultValue := factory.createFloat2(Vector.neg(operand1.asFloat2()));
TYP_FLOAT4:
resultValue := factory.createFloat4(Vector.neg(operand1.asFloat4()));
TYP_FLOAT8:
resultValue := factory.createFloat8(Vector.neg(operand1.asFloat8()));
TYP_BYTE:
resultValue := factory.createByte(byte(-operand1.asByte()));
TYP_BYTE2:
resultValue := factory.createByte2(Vector.neg(operand1.asByte2()));
TYP_BYTE4:
resultValue := factory.createByte4(Vector.neg(operand1.asByte4()));
TYP_BYTE8:
resultValue := factory.createByte8(Vector.neg(operand1.asByte8()));
TYP_SHORT:
resultValue := factory.createShort(short(-operand1.asShort()));
TYP_SHORT2:
resultValue := factory.createShort2(Vector.neg(operand1.asShort2()));
TYP_SHORT4:
resultValue := factory.createShort4(Vector.neg(operand1.asShort4()));
TYP_SHORT8:
resultValue := factory.createShort8(Vector.neg(operand1.asShort8()));
TYP_INT:
resultValue := factory.createInt(-operand1.asInt());
TYP_INT2:
resultValue := factory.createInt2(Vector.neg(operand1.asInt2()));
TYP_INT4:
resultValue := factory.createInt4(Vector.neg(operand1.asInt4()));
TYP_INT8:
resultValue := factory.createInt8(Vector.neg(operand1.asInt8()));
TYP_LONG:
resultValue := factory.createLong(-operand1.asLong());
TYP_LONG2:
resultValue := factory.createLong2(Vector.neg(operand1.asLong2()));
TYP_LONG4:
resultValue := factory.createLong4(Vector.neg(operand1.asLong4()));
TYP_LONG8:
resultValue := factory.createLong8(Vector.neg(operand1.asLong8()));
else
goto break_label0;
end;
end;
O_VECT_PCK: begin
if (kind >= TYP_BYTE) and (kind <= TYP_BYTE8) then begin
inc(kind, TYP_SHORT - TYP_BYTE);
operand1 := operand1.castTo(getPrimitiveType(kind));
end;
case kind of
TYP_SHORT:
resultValue := factory.createByte(Vector.pck(operand1.asShort()));
TYP_SHORT2:
resultValue := factory.createByte2(Vector.pck(operand1.asShort2()));
TYP_SHORT4:
resultValue := factory.createByte4(Vector.pck(operand1.asShort4()));
TYP_SHORT8:
resultValue := factory.createByte8(Vector.pck(operand1.asShort8()));
TYP_INT:
resultValue := factory.createShort(Vector.pck(operand1.asInt()));
TYP_INT2:
resultValue := factory.createShort2(Vector.pck(operand1.asInt2()));
TYP_INT4:
resultValue := factory.createShort4(Vector.pck(operand1.asInt4()));
TYP_INT8:
resultValue := factory.createShort8(Vector.pck(operand1.asInt8()));
TYP_LONG:
resultValue := factory.createInt(Vector.pck(operand1.asLong()));
TYP_LONG2:
resultValue := factory.createInt2(Vector.pck(operand1.asLong2()));
TYP_LONG4:
resultValue := factory.createInt4(Vector.pck(operand1.asLong4()));
TYP_LONG8:
resultValue := factory.createInt8(Vector.pck(operand1.asLong8()));
else
goto break_label0;
end;
end;
O_VECT_LUP: begin
case kind of
TYP_BYTE:
resultValue := factory.createShort(Vector.lup(operand1.asByte()));
TYP_BYTE2:
resultValue := factory.createShort2(Vector.lup(operand1.asByte2()));
TYP_BYTE4:
resultValue := factory.createShort4(Vector.lup(operand1.asByte4()));
TYP_BYTE8:
resultValue := factory.createShort8(Vector.lup(operand1.asByte8()));
TYP_SHORT:
resultValue := factory.createInt(Vector.lup(operand1.asShort()));
TYP_SHORT2:
resultValue := factory.createInt2(Vector.lup(operand1.asShort2()));
TYP_SHORT4:
resultValue := factory.createInt4(Vector.lup(operand1.asShort4()));
TYP_SHORT8:
resultValue := factory.createInt8(Vector.lup(operand1.asShort8()));
TYP_INT:
resultValue := factory.createLong(Vector.lup(operand1.asInt()));
TYP_INT2:
resultValue := factory.createLong2(Vector.lup(operand1.asInt2()));
TYP_INT4:
resultValue := factory.createLong4(Vector.lup(operand1.asInt4()));
TYP_INT8:
resultValue := factory.createLong8(Vector.lup(operand1.asInt8()));
else
goto break_label0;
end;
end;
O_VECT_UUP: begin
case kind of
TYP_BYTE:
resultValue := factory.createShort(Vector.uup(operand1.asByte()));
TYP_BYTE2:
resultValue := factory.createShort2(Vector.uup(operand1.asByte2()));
TYP_BYTE4:
resultValue := factory.createShort4(Vector.uup(operand1.asByte4()));
TYP_BYTE8:
resultValue := factory.createShort8(Vector.uup(operand1.asByte8()));
TYP_SHORT:
resultValue := factory.createInt(Vector.uup(operand1.asShort()));
TYP_SHORT2:
resultValue := factory.createInt2(Vector.uup(operand1.asShort2()));
TYP_SHORT4:
resultValue := factory.createInt4(Vector.uup(operand1.asShort4()));
TYP_SHORT8:
resultValue := factory.createInt8(Vector.uup(operand1.asShort8()));
TYP_INT:
resultValue := factory.createLong(Vector.uup(operand1.asInt()));
TYP_INT2:
resultValue := factory.createLong2(Vector.uup(operand1.asInt2()));
TYP_INT4:
resultValue := factory.createLong4(Vector.uup(operand1.asInt4()));
TYP_INT8:
resultValue := factory.createLong8(Vector.uup(operand1.asInt8()));
else
goto break_label0;
end;
end;
CAST_TO: begin
newType := item.newType;
if newType.isBoolean() and argument1Type.isBoolean() then begin
resultValue := operand1;
goto break_label1;
end;
if newType.isNumeric() and argument1Type.isNumeric() then begin
resultValue := operand1.castTo(newType);
goto break_label1;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.type-cast'), [
CoObject.create(argument1Type), CoObject.create(newType)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
INC_LOCAL,
DEC_LOCAL: begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'applicable.operator.assignment'), [
CoUnicodeString.create(source.getLexemeString(before))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
end;
break_label1:
child1.setData(before, resultValue.&type, LOAD_CONST, resultValue);
continue;
end;
case operation of
BOOL_NOT: begin
if kind = TYP_BOOLEAN then begin
resultType := argument1Type;
goto break_label2;
end;
goto break_label0;
end;
O_BIT_NOT: begin
if (kind >= TYP_BYTE) and (kind <= TYP_LONG8) then begin
resultType := argument1Type;
goto break_label2;
end;
goto break_label0;
end;
O_SCAL_POS: begin
if (kind >= TYP_BYTE) and (kind <= TYP_SHORT8) then begin
resultType := getPrimitiveType(TYP_INT + (kind and 3));
if (kind <> TYP_BYTE) and (kind <> TYP_SHORT) then begin
resultNode := __code.createAndAppendNode(parent).setData(before, resultType, CAST_TO, resultType, argument1Type);
end else begin
resultNode := __code.createAndAppendNode(parent).setData(before, resultType, NOP);
end;
__code.moveNode(child1, resultNode, 0);
child1 := resultNode;
continue;
end;
if argument1Type.isNumeric() then begin
resultNode := __code.createAndAppendNode(parent).setData(before, argument1Type, NOP);
__code.moveNode(child1, resultNode, 0);
child1 := resultNode;
continue;
end;
goto break_label0;
end;
O_SCAL_NEG: begin
if (kind >= TYP_BYTE) and (kind <= TYP_SHORT8) then begin
resultType := getPrimitiveType(TYP_INT + (kind and 3));
if (kind <> TYP_BYTE) and (kind <> TYP_SHORT) then begin
resultNode := __code.createAndAppendNode(parent).setData(before, resultType, CAST_TO, resultType, argument1Type);
__code.moveNode(child1, resultNode, 0);
child1 := resultNode;
end;
argument1Type := resultType;
goto break_label2;
end;
if argument1Type.isNumeric() then begin
resultType := argument1Type;
goto break_label2;
end;
goto break_label0;
end;
O_VECT_POS: begin
if (kind >= TYP_DOUBLE) and (kind <= TYP_LONG8) then begin
resultNode := __code.createAndAppendNode(parent).setData(before, argument1Type, NOP);
__code.moveNode(child1, resultNode, 0);
child1 := resultNode;
continue;
end;
goto break_label0;
end;
O_VECT_NEG: begin
if (kind >= TYP_DOUBLE) and (kind <= TYP_LONG8) then begin
resultType := argument1Type;
goto break_label2;
end;
goto break_label0;
end;
O_VECT_PCK: begin
if (kind >= TYP_BYTE) and (kind <= TYP_BYTE8) then begin
inc(kind, TYP_SHORT - TYP_BYTE);
resultType := getPrimitiveType(kind);
resultNode := __code.createAndAppendNode(parent).setData(before, resultType, CAST_TO, resultType, argument1Type);
__code.moveNode(child1, resultNode, 0);
child1 := resultNode;
argument1Type := resultType;
end;
if (kind >= TYP_SHORT) and (kind <= TYP_LONG8) then begin
resultType := getPrimitiveType(kind + (TYP_BYTE - TYP_SHORT));
goto break_label2;
end;
goto break_label0;
end;
O_VECT_LUP,
O_VECT_UUP: begin
if (kind >= TYP_BYTE) and (kind <= TYP_INT8) then begin
resultType := getPrimitiveType(kind + (TYP_SHORT - TYP_BYTE));
goto break_label2;
end;
goto break_label0;
end;
CAST_TO: begin
newType := item.newType;
if newType.isBoolean() and argument1Type.isBoolean() then begin
resultNode := __code.createAndAppendNode(parent).setData(before, newType, NOP);
__code.moveNode(child1, resultNode, 0);
child1 := resultNode;
continue;
end;
if newType.isNumeric() and argument1Type.isNumeric() then begin
if newType <> argument1Type then begin
resultNode := __code.createAndAppendNode(parent).setData(before, newType, CAST_TO, newType, argument1Type);
end else begin
resultNode := __code.createAndAppendNode(parent).setData(before, newType, NOP);
end;
__code.moveNode(child1, resultNode, 0);
child1 := resultNode;
continue;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.type-cast'), [
CoObject.create(argument1Type), CoObject.create(newType)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
INC_LOCAL,
DEC_LOCAL: begin
case instruction of
LOAD_LOCAL: begin
foundLocal := child1.operand1 as Local;
if foundLocal.isFinal() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.access.local-final.write'), [
CoObject.create(foundLocal)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
argument1Type := foundLocal.&type;
if not(argument1Type is PrimitiveType) or not argument1Type.isNumeric() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.1'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if operation = INC_LOCAL then begin
instruction := INC_PRED_LOAD_LOCAL;
end else begin
instruction := DEC_PRED_LOAD_LOCAL;
end;
child1.setData(child1.position, argument1Type, instruction, foundLocal);
continue;
end;
LOAD_STATIC: begin
foundField := child1.operand1 as Field;
if foundField.isFinal() and (not(enclosingCallable is ClassInit) or (foundField.parentType <> enclosingClassType) or (foundField.value <> nil)) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.access.field-final.write'), [
CoObject.create(foundField)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
argument1Type := foundField.&type;
if not(argument1Type is PrimitiveType) or not argument1Type.isNumeric() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.1'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
delta := appendIncrementCode(child1, PrimitiveType(argument1Type), operation = INC_LOCAL);
__code.createAndPrependNode(delta).setData(child1.position, argument1Type, LOAD_STATIC, foundField);
__code.createAndAppendNode(child1).setData(-1, nil, DUP1, argument1Type);
child1.setData(-1, argument1Type, STORE_STATIC, foundField);
continue;
end;
READ_FIELD,
READ_SPECIAL,
READ_PROPERTY: begin
foundFieldoid := child1.operand1 as TypedMember;
if Lang.isInstance(foundFieldoid, &Property) then begin
if not &Property(Lang.cast(foundFieldoid, &Property)).hasWrite() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.access.property-read-only.write'), [
CoSimple.create(foundFieldoid)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
end else begin
load := child1.readComponent(0);
if
foundFieldoid.isFinal() and (
not(enclosingCallable is InstInit) or (foundFieldoid.parentType <> enclosingClassType) or
(load.instruction <> LOAD_LOCAL) or (load.operand1 <> enclosingCallable.arguments.thisArgument)
)
then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.access.field-final.write'), [
CoSimple.create(foundFieldoid)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
end;
argument1Type := foundFieldoid.&type;
if not(argument1Type is PrimitiveType) or not argument1Type.isNumeric() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.1'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundItem := TableItem(Lang.cast(foundFieldoid, TableItem));
delta := appendIncrementCode(child1, PrimitiveType(argument1Type), operation = INC_LOCAL);
read := __code.createAndPrependNode(delta).setData(child1.position, argument1Type, instruction, foundItem);
__code.createAndAppendNode(read).setData(-1, nil, DUP1, fldTypeObject);
__code.createAndAppendNode(child1).setData(-1, nil, DUP1X1, argument1Type);
child1.setData(-1, argument1Type, instruction + A_DELTA, foundItem);
continue;
end;
READ_COMPONENT: begin
argument1Type := child1.operand1 as &Type;
if not(argument1Type is PrimitiveType) or not argument1Type.isNumeric() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.1'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
delta := appendIncrementCode(child1, PrimitiveType(argument1Type), operation = INC_LOCAL);
read := __code.createAndPrependNode(delta).setData(child1.position, argument1Type, READ_COMPONENT, argument1Type);
__code.createAndAppendNode(read).setData(-1, nil, DUP2, fldTypeInt);
__code.createAndAppendNode(child1).setData(-1, nil, DUP1X2, argument1Type);
child1.setData(-1, argument1Type, WRITE_COMPONENT, argument1Type);
continue;
end;
INVOKE_SERVICE,
INVOKE_SPECIAL,
INVOKE_VIRTUAL: begin
foundItem := child1.operand1;
if foundItem is &Operator then begin
foundReadOperator := &Operator(foundItem);
if foundReadOperator.kind = READ_COMPONENT then begin
argument1Type := foundReadOperator.&type;
if not(argument1Type is PrimitiveType) or not argument1Type.isNumeric() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.1'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
load := child1.readComponent(0);
dereferenceClassType := load.&type as ru.malik.elaborarer.avtoo.lang.ClassType;
isUseSuper := load.useSuper;
if isUseSuper then begin
impliedParentClassType := enclosingClassType;
end else begin
impliedParentClassType := dereferenceClassType;
end;
arguments := [ foundReadOperator.arguments.readComponent(0).&type, argument1Type ];
foundOperators := dereferenceClassType.findOperators(WRITE_COMPONENT, arguments, enclosingClassType);
if system.length(foundOperators) <> 1 then begin
foundWriteOperator := nil;
end else begin
foundWriteOperator := foundOperators[0];
end;
if (foundWriteOperator = nil) or not foundWriteOperator.isIdentityArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-found.operator'), [
CoObject.create(dereferenceClassType), CoAnsiString.create(&Operator.kindToSymbol(WRITE_COMPONENT) + ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundWriteOperator.isVisibleFrom(enclosingClassType, impliedParentClassType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosingClassType.specialSimpleName), CoObject.create(foundWriteOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if isUseSuper and foundWriteOperator.isAbstract() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.direct-access-abstract.operator'), [
CoObject.create(foundWriteOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
delta := appendIncrementCode(child1, PrimitiveType(argument1Type), operation = INC_LOCAL);
read := __code.createAndPrependNode(delta).setData(child1.position, argument1Type, instruction, foundReadOperator);
__code.createAndAppendNode(read).setData(-1, nil, DUP2, arguments[0]);
__code.createAndAppendNode(child1).setData(-1, nil, DUP1X2, argument1Type);
if isUseSuper then begin
instruction := INVOKE_SPECIAL;
end else begin
instruction := invokeInstructionFor(foundWriteOperator, dereferenceClassType);
end;
child1.setData(-1, argument1Type, instruction, foundWriteOperator);
continue;
end;
end;
end;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'applicable.operator.assignment'), [
CoUnicodeString.create(source.getLexemeString(before))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
end;
break_label2:
if operation = BOOL_NOT then argument1Type := nil;
resultNode := __code.createAndAppendNode(parent).setData(before, resultType, operation, argument1Type);
__code.moveNode(child1, resultNode, 0);
child1 := resultNode;
continue;
end;
end;
break_label0:
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.1'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
finally
stack.free();
end;
result := position;
end;
function ImmediateBuilder.parseMultiplicative(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
label
break_label0,
break_label1,
break_label2,
continue_label0;
var
kind: int;
before: int;
operation: int;
foundLength: int;
arguments: Type_Array1d;
foundOperators: Operator_Array1d;
child1: Node;
child2: Node;
__code: Code;
resultNode: Node;
resultType: &Type;
commonType: &Type;
operand1: Constant;
operand2: Constant;
argument1Type: &Type;
argument2Type: &Type;
resultValue: Constant;
factory: ConstantFactory;
foundOperator: &Operator;
enclosing: ru.malik.elaborarer.avtoo.lang.ClassType;
dereference: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
position := parsePrefix(parent, source, position, isStaticOnly);
operation := source.getLexemeKind(position);
if
(operation = O_SCAL_MUL) or (operation = O_SCAL_DIV) or (operation = O_SCAL_DIVU) or (operation = O_SCAL_REM) or (operation = O_SCAL_REMU) or
(operation = O_VECT_MUL) or (operation = O_VECT_DIV) or (operation = O_VECT_HMUL) or (operation = O_VECT_HMULU)
then begin
__code := parent.parentCode;
enclosing := __code.parentCallable.parentType;
factory := fldConstantFactory;
child1 := parent.readComponent(-1);
repeat
before := position;
position := parsePrefix(parent, source, position + 1, isStaticOnly);
child2 := parent.readComponent(-1);
argument1Type := child1.&type;
argument2Type := child2.&type;
begin
begin
if argument1Type is ru.malik.elaborarer.avtoo.lang.ClassType then begin
dereference := ru.malik.elaborarer.avtoo.lang.ClassType(argument1Type);
arguments := [ argument2Type ];
foundOperators := dereference.findOperators(operation, arguments, enclosing);
foundLength := system.length(foundOperators);
if foundLength < 1 then begin
if argument2Type is ru.malik.elaborarer.avtoo.lang.ClassType then goto break_label1;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereference), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(operation))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundOperator := foundOperators[0];
if not foundOperator.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator'), [
CoObject.create(foundOperator), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundOperator.isVisibleFrom(enclosing, dereference) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosing.specialSimpleName), CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereference.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(operation) + foundOperator.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
child2 := cast(child2, foundOperator.arguments.readComponent(0).&type);
resultNode := __code.createAndAppendNode(parent).setData(before, foundOperator.&type, invokeInstructionFor(foundOperator, dereference), foundOperator);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
goto continue_label0;
end;
if argument2Type is ru.malik.elaborarer.avtoo.lang.ClassType then goto break_label1;
if not(argument1Type is PrimitiveType) then goto break_label0;
if operation >= O_VECT_OPERATOR then begin
commonType := argument1Type.getVectorCommonType(argument2Type);
end else begin
commonType := argument1Type.getScalarCommonType(argument2Type);
end;
if commonType = nil then goto break_label0;
kind := commonType.kind;
if (child1.instruction = LOAD_CONST) and (child2.instruction = LOAD_CONST) then begin
operand1 := child1.operandC;
operand2 := child2.operandC;
case operation of
O_SCAL_MUL: begin
case kind of
TYP_REAL:
resultValue := factory.createReal(operand1.asReal() * operand2.asReal());
TYP_DOUBLE:
resultValue := factory.createDouble(operand1.asDouble() * operand2.asDouble());
TYP_DOUBLE2:
resultValue := factory.createDouble2(operand1.asDouble2() * operand2.asDouble2());
TYP_DOUBLE4:
resultValue := factory.createDouble4(operand1.asDouble4() * operand2.asDouble4());
TYP_DOUBLE8:
resultValue := factory.createDouble8(operand1.asDouble8() * operand2.asDouble8());
TYP_FLOAT:
resultValue := factory.createFloat(operand1.asFloat() * operand2.asFloat());
TYP_FLOAT2:
resultValue := factory.createFloat2(operand1.asFloat2() * operand2.asFloat2());
TYP_FLOAT4:
resultValue := factory.createFloat4(operand1.asFloat4() * operand2.asFloat4());
TYP_FLOAT8:
resultValue := factory.createFloat8(operand1.asFloat8() * operand2.asFloat8());
TYP_INT:
resultValue := factory.createIntegral(operand1.asInt() * operand2.asInt());
TYP_INT2:
resultValue := factory.createInt2(operand1.asInt2() * operand2.asInt2());
TYP_INT4:
resultValue := factory.createInt4(operand1.asInt4() * operand2.asInt4());
TYP_INT8:
resultValue := factory.createInt8(operand1.asInt8() * operand2.asInt8());
TYP_LONG:
resultValue := factory.createLong(operand1.asLong() * operand2.asLong());
TYP_LONG2:
resultValue := factory.createLong2(operand1.asLong2() * operand2.asLong2());
TYP_LONG4:
resultValue := factory.createLong4(operand1.asLong4() * operand2.asLong4());
TYP_LONG8:
resultValue := factory.createLong8(operand1.asLong8() * operand2.asLong8());
else
goto break_label0;
end;
end;
O_SCAL_DIV: begin
if ((kind = TYP_INT) or (kind = TYP_LONG)) and operand2.isDefaultValue() then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'error.int-div-by-zero'));
exception.source := source;
exception.position := before;
raise exception;
end;
case kind of
TYP_REAL:
resultValue := factory.createReal(operand1.asReal() / operand2.asReal());
TYP_DOUBLE:
resultValue := factory.createDouble(operand1.asDouble() / operand2.asDouble());
TYP_DOUBLE2:
resultValue := factory.createDouble2(operand1.asDouble2() / operand2.asDouble2());
TYP_DOUBLE4:
resultValue := factory.createDouble4(operand1.asDouble4() / operand2.asDouble4());
TYP_DOUBLE8:
resultValue := factory.createDouble8(operand1.asDouble8() / operand2.asDouble8());
TYP_FLOAT:
resultValue := factory.createFloat(operand1.asFloat() / operand2.asFloat());
TYP_FLOAT2:
resultValue := factory.createFloat2(operand1.asFloat2() / operand2.asFloat2());
TYP_FLOAT4:
resultValue := factory.createFloat4(operand1.asFloat4() / operand2.asFloat4());
TYP_FLOAT8:
resultValue := factory.createFloat8(operand1.asFloat8() / operand2.asFloat8());
TYP_INT:
resultValue := factory.createIntegral(operand1.asInt() div operand2.asInt());
TYP_LONG:
resultValue := factory.createLong(operand1.asLong() div operand2.asLong());
else
goto break_label0;
end;
end;
O_SCAL_DIVU: begin
if ((kind = TYP_INT) or (kind = TYP_LONG)) and operand2.isDefaultValue() then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'error.int-div-by-zero'));
exception.source := source;
exception.position := before;
raise exception;
end;
case kind of
TYP_REAL:
resultValue := factory.createReal(operand1.asReal() / operand2.asReal());
TYP_DOUBLE:
resultValue := factory.createDouble(operand1.asDouble() / operand2.asDouble());
TYP_DOUBLE2:
resultValue := factory.createDouble2(Scalar.inv(operand2.asDouble2()) * operand1.asDouble2());
TYP_DOUBLE4:
resultValue := factory.createDouble4(Scalar.inv(operand2.asDouble4()) * operand1.asDouble4());
TYP_DOUBLE8:
resultValue := factory.createDouble8(Scalar.inv(operand2.asDouble8()) * operand1.asDouble8());
TYP_FLOAT:
resultValue := factory.createFloat(operand1.asFloat() / operand2.asFloat());
TYP_FLOAT2:
resultValue := factory.createFloat2(Scalar.inv(operand2.asFloat2()) * operand1.asFloat2());
TYP_FLOAT4:
resultValue := factory.createFloat4(Scalar.inv(operand2.asFloat4()) * operand1.asFloat4());
TYP_FLOAT8:
resultValue := factory.createFloat8(Scalar.inv(operand2.asFloat8()) * operand1.asFloat8());
TYP_INT:
resultValue := factory.createIntegral(CoInt.divUnsigned(operand1.asInt(), operand2.asInt()));
TYP_LONG:
resultValue := factory.createLong(CoLong.divUnsigned(operand1.asLong(), operand2.asLong()));
else
goto break_label0;
end;
end;
O_SCAL_REM: begin
if ((kind = TYP_INT) or (kind = TYP_LONG)) and operand2.isDefaultValue() then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'error.int-div-by-zero'));
exception.source := source;
exception.position := before;
raise exception;
end;
case kind of
TYP_REAL:
resultValue := factory.createReal(CoReal.rem(operand1.asReal(), operand2.asReal()));
TYP_DOUBLE:
resultValue := factory.createDouble(CoDouble.rem(operand1.asDouble(), operand2.asDouble()));
TYP_FLOAT:
resultValue := factory.createFloat(CoFloat.rem(operand1.asFloat(), operand2.asFloat()));
TYP_INT:
resultValue := factory.createIntegral(operand1.asInt() mod operand2.asInt());
TYP_LONG:
resultValue := factory.createLong(operand1.asLong() mod operand2.asLong());
else
goto break_label0;
end;
end;
O_SCAL_REMU: begin
if ((kind = TYP_INT) or (kind = TYP_LONG)) and operand2.isDefaultValue() then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'error.int-div-by-zero'));
exception.source := source;
exception.position := before;
raise exception;
end;
case kind of
TYP_REAL:
resultValue := factory.createReal(CoReal.rem(operand1.asReal(), operand2.asReal()));
TYP_DOUBLE:
resultValue := factory.createDouble(CoDouble.rem(operand1.asDouble(), operand2.asDouble()));
TYP_FLOAT:
resultValue := factory.createFloat(CoFloat.rem(operand1.asFloat(), operand2.asFloat()));
TYP_INT:
resultValue := factory.createIntegral(CoInt.remUnsigned(operand1.asInt(), operand2.asInt()));
TYP_LONG:
resultValue := factory.createLong(CoLong.remUnsigned(operand1.asLong(), operand2.asLong()));
else
goto break_label0;
end;
end;
O_VECT_MUL: begin
case kind of
TYP_DOUBLE:
resultValue := factory.createDouble(operand1.asDouble() * operand2.asDouble());
TYP_DOUBLE2:
resultValue := factory.createDouble2(Vector.mul(operand1.asDouble2(), operand2.asDouble2()));
TYP_DOUBLE4:
resultValue := factory.createDouble4(Vector.mul(operand1.asDouble4(), operand2.asDouble4()));
TYP_DOUBLE8:
resultValue := factory.createDouble8(Vector.mul(operand1.asDouble8(), operand2.asDouble8()));
TYP_FLOAT:
resultValue := factory.createFloat(operand1.asFloat() * operand2.asFloat());
TYP_FLOAT2:
resultValue := factory.createFloat2(Vector.mul(operand1.asFloat2(), operand2.asFloat2()));
TYP_FLOAT4:
resultValue := factory.createFloat4(Vector.mul(operand1.asFloat4(), operand2.asFloat4()));
TYP_FLOAT8:
resultValue := factory.createFloat8(Vector.mul(operand1.asFloat8(), operand2.asFloat8()));
TYP_BYTE:
resultValue := factory.createByte(byte(operand1.asByte() * operand2.asByte()));
TYP_BYTE2:
resultValue := factory.createByte2(Vector.mul(operand1.asByte2(), operand2.asByte2()));
TYP_BYTE4:
resultValue := factory.createByte4(Vector.mul(operand1.asByte4(), operand2.asByte4()));
TYP_BYTE8:
resultValue := factory.createByte8(Vector.mul(operand1.asByte8(), operand2.asByte8()));
TYP_SHORT:
resultValue := factory.createShort(short(operand1.asShort() * operand2.asShort()));
TYP_SHORT2:
resultValue := factory.createShort2(Vector.mul(operand1.asShort2(), operand2.asShort2()));
TYP_SHORT4:
resultValue := factory.createShort4(Vector.mul(operand1.asShort4(), operand2.asShort4()));
TYP_SHORT8:
resultValue := factory.createShort8(Vector.mul(operand1.asShort8(), operand2.asShort8()));
TYP_INT:
resultValue := factory.createInt(operand1.asInt() * operand2.asInt());
TYP_INT2:
resultValue := factory.createInt2(Vector.mul(operand1.asInt2(), operand2.asInt2()));
TYP_INT4:
resultValue := factory.createInt4(Vector.mul(operand1.asInt4(), operand2.asInt4()));
TYP_INT8:
resultValue := factory.createInt8(Vector.mul(operand1.asInt8(), operand2.asInt8()));
TYP_LONG:
resultValue := factory.createLong(operand1.asLong() * operand2.asLong());
TYP_LONG2:
resultValue := factory.createLong2(Vector.mul(operand1.asLong2(), operand2.asLong2()));
TYP_LONG4:
resultValue := factory.createLong4(Vector.mul(operand1.asLong4(), operand2.asLong4()));
TYP_LONG8:
resultValue := factory.createLong8(Vector.mul(operand1.asLong8(), operand2.asLong8()));
else
goto break_label0;
end;
end;
O_VECT_DIV: begin
if (kind >= TYP_BYTE) and (kind <= TYP_LONG8) then begin
kind := TYP_DOUBLE + (kind and 3);
end;
case kind of
TYP_DOUBLE:
resultValue := factory.createDouble(operand1.asDouble() / operand2.asDouble());
TYP_DOUBLE2:
resultValue := factory.createDouble2(Vector.&div(operand1.asDouble2(), operand2.asDouble2()));
TYP_DOUBLE4:
resultValue := factory.createDouble4(Vector.&div(operand1.asDouble4(), operand2.asDouble4()));
TYP_DOUBLE8:
resultValue := factory.createDouble8(Vector.&div(operand1.asDouble8(), operand2.asDouble8()));
TYP_FLOAT:
resultValue := factory.createFloat(operand1.asFloat() / operand2.asFloat());
TYP_FLOAT2:
resultValue := factory.createFloat2(Vector.&div(operand1.asFloat2(), operand2.asFloat2()));
TYP_FLOAT4:
resultValue := factory.createFloat4(Vector.&div(operand1.asFloat4(), operand2.asFloat4()));
TYP_FLOAT8:
resultValue := factory.createFloat8(Vector.&div(operand1.asFloat8(), operand2.asFloat8()));
else
goto break_label0;
end;
end;
O_VECT_HMUL: begin
case kind of
TYP_BYTE:
resultValue := factory.createByte(Vector.hmul(operand1.asByte(), operand2.asByte()));
TYP_BYTE2:
resultValue := factory.createByte2(Vector.hmul(operand1.asByte2(), operand2.asByte2()));
TYP_BYTE4:
resultValue := factory.createByte4(Vector.hmul(operand1.asByte4(), operand2.asByte4()));
TYP_BYTE8:
resultValue := factory.createByte8(Vector.hmul(operand1.asByte8(), operand2.asByte8()));
TYP_SHORT:
resultValue := factory.createShort(Vector.hmul(operand1.asShort(), operand2.asShort()));
TYP_SHORT2:
resultValue := factory.createShort2(Vector.hmul(operand1.asShort2(), operand2.asShort2()));
TYP_SHORT4:
resultValue := factory.createShort4(Vector.hmul(operand1.asShort4(), operand2.asShort4()));
TYP_SHORT8:
resultValue := factory.createShort8(Vector.hmul(operand1.asShort8(), operand2.asShort8()));
else
goto break_label0;
end;
end;
O_VECT_HMULU: begin
case kind of
TYP_BYTE:
resultValue := factory.createByte(Vector.hmulu(operand1.asByte(), operand2.asByte()));
TYP_BYTE2:
resultValue := factory.createByte2(Vector.hmulu(operand1.asByte2(), operand2.asByte2()));
TYP_BYTE4:
resultValue := factory.createByte4(Vector.hmulu(operand1.asByte4(), operand2.asByte4()));
TYP_BYTE8:
resultValue := factory.createByte8(Vector.hmulu(operand1.asByte8(), operand2.asByte8()));
TYP_SHORT:
resultValue := factory.createShort(Vector.hmulu(operand1.asShort(), operand2.asShort()));
TYP_SHORT2:
resultValue := factory.createShort2(Vector.hmulu(operand1.asShort2(), operand2.asShort2()));
TYP_SHORT4:
resultValue := factory.createShort4(Vector.hmulu(operand1.asShort4(), operand2.asShort4()));
TYP_SHORT8:
resultValue := factory.createShort8(Vector.hmulu(operand1.asShort8(), operand2.asShort8()));
else
goto break_label0;
end;
end;
else
resultValue := nil;
end;
child1.setData(child1.position, resultValue.&type, LOAD_CONST, resultValue);
__code.removeNode(child2);
goto continue_label0;
end;
case operation of
O_SCAL_MUL: begin
if (kind >= TYP_REAL) and (kind <= TYP_FLOAT8) or (kind >= TYP_INT) and (kind <= TYP_LONG8) then begin
resultType := commonType;
goto break_label2;
end;
goto break_label0;
end;
O_SCAL_DIV,
O_SCAL_DIVU: begin
if (kind >= TYP_REAL) and (kind <= TYP_FLOAT8) or (kind = TYP_INT) or (kind = TYP_LONG) then begin
resultType := commonType;
goto break_label2;
end;
goto break_label0;
end;
O_SCAL_REM,
O_SCAL_REMU: begin
if (kind = TYP_REAL) or (kind = TYP_DOUBLE) or (kind = TYP_FLOAT) or (kind = TYP_INT) or (kind = TYP_LONG) then begin
resultType := commonType;
goto break_label2;
end;
goto break_label0;
end;
O_VECT_MUL: begin
if (kind >= TYP_DOUBLE) and (kind <= TYP_LONG8) then begin
resultType := commonType;
goto break_label2;
end;
goto break_label0;
end;
O_VECT_DIV: begin
if (kind >= TYP_BYTE) and (kind <= TYP_LONG8) then begin
kind := TYP_DOUBLE + (kind and 3);
commonType := getPrimitiveType(kind);
end;
if (kind >= TYP_DOUBLE) and (kind <= TYP_FLOAT8) then begin
resultType := commonType;
goto break_label2;
end;
goto break_label0;
end;
O_VECT_HMUL,
O_VECT_HMULU: begin
if (kind >= TYP_BYTE) and (kind <= TYP_SHORT8) then begin
resultType := commonType;
goto break_label2;
end;
goto break_label0;
end;
else
resultType := nil;
end;
break_label2:
child1 := cast(child1, commonType);
child2 := cast(child2, commonType);
resultNode := __code.createAndAppendNode(parent).setData(before, resultType, operation, commonType);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
goto continue_label0;
end;
break_label1:
dereference := ru.malik.elaborarer.avtoo.lang.ClassType(argument2Type);
arguments := [ argument1Type ];
inc(operation, R_DELTA);
foundOperators := dereference.findOperators(operation, arguments, enclosing);
foundLength := system.length(foundOperators);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereference), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(operation))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundOperator := foundOperators[0];
if not foundOperator.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator'), [
CoObject.create(foundOperator), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundOperator.isVisibleFrom(enclosing, dereference) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosing.specialSimpleName), CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereference.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(operation) + foundOperator.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
child1 := cast(child1, foundOperator.arguments.readComponent(0).&type);
resultNode := __code.createAndAppendNode(parent).setData(before, foundOperator.&type, invokeInstructionFor(foundOperator, dereference), foundOperator);
__code.createAndAppendNode(resultNode).setData(before, nil, SWAP, argument1Type);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
goto continue_label0;
end;
break_label0:
begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.2'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type), CoObject.create(argument2Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
continue_label0:
operation := source.getLexemeKind(position);
until
(operation <> O_SCAL_MUL) and (operation <> O_SCAL_DIV) and (operation <> O_SCAL_DIVU) and (operation <> O_SCAL_REM) and (operation <> O_SCAL_REMU) and
(operation <> O_VECT_MUL) and (operation <> O_VECT_DIV) and (operation <> O_VECT_HMUL) and (operation <> O_VECT_HMULU)
;
end;
result := position;
end;
function ImmediateBuilder.parseAdditive(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
label
break_label0,
break_label1,
break_label2,
continue_label0;
var
operand1AsUChar: uchar;
operand2AsUChar: uchar;
kind: int;
before: int;
operation: int;
foundLength: int;
arguments: Type_Array1d;
foundOperators: Operator_Array1d;
child1: Node;
child2: Node;
__code: Code;
resultNode: Node;
resultType: &Type;
commonType: &Type;
operand1: Constant;
operand2: Constant;
argument1Type: &Type;
argument2Type: &Type;
resultValue: Constant;
operand1AsValue: Value;
operand2AsValue: Value;
factory: ConstantFactory;
foundOperator: &Operator;
enclosing: ru.malik.elaborarer.avtoo.lang.ClassType;
typeString: ru.malik.elaborarer.avtoo.lang.ClassType;
dereference: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
position := parseMultiplicative(parent, source, position, isStaticOnly);
operation := source.getLexemeKind(position);
if
(operation = O_SCAL_ADD) or (operation = O_SCAL_SUB) or (operation = O_VECT_SADD) or (operation = O_VECT_SADDU) or
(operation = O_VECT_ADD) or (operation = O_VECT_SUB) or (operation = O_VECT_SSUB) or (operation = O_VECT_SSUBU)
then begin
__code := parent.parentCode;
enclosing := __code.parentCallable.parentType;
factory := fldConstantFactory;
child1 := parent.readComponent(-1);
typeString := fldTypeString;
repeat
before := position;
position := parseMultiplicative(parent, source, position + 1, isStaticOnly);
child2 := parent.readComponent(-1);
argument1Type := child1.&type;
argument2Type := child2.&type;
begin
begin
if argument1Type is ru.malik.elaborarer.avtoo.lang.ClassType then begin
if (operation = O_SCAL_ADD) and (argument1Type = typeString) and (child1.instruction = LOAD_CONST) and (child2.instruction = LOAD_CONST) then begin
if argument2Type = typeString then begin
operand1AsValue := child1.operandC.asInterface() as Value;
operand2AsValue := child2.operandC.asInterface() as Value;
if (operand1AsValue <> nil) and (operand2AsValue <> nil) then begin
child1.setData(child1.position, typeString, LOAD_CONST, factory.createString(operand1AsValue.asUnicodeString() + operand2AsValue.asUnicodeString()));
__code.removeNode(child2);
goto continue_label0;
end;
end else
if argument2Type = getPrimitiveType(TYP_CHAR) then begin
operand1AsValue := child1.operandC.asInterface() as Value;
if operand1AsValue <> nil then begin
operand2AsUChar := child2.operandC.asUChar();
child1.setData(child1.position, typeString, LOAD_CONST, factory.createString(operand1AsValue.asUnicodeString() + operand2AsUChar));
__code.removeNode(child2);
goto continue_label0;
end;
end;
end;
dereference := ru.malik.elaborarer.avtoo.lang.ClassType(argument1Type);
arguments := [ argument2Type ];
foundOperators := dereference.findOperators(operation, arguments, enclosing);
foundLength := system.length(foundOperators);
if foundLength < 1 then begin
if argument2Type is ru.malik.elaborarer.avtoo.lang.ClassType then goto break_label1;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereference), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(operation))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundOperator := foundOperators[0];
if not foundOperator.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator'), [
CoObject.create(foundOperator), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundOperator.isVisibleFrom(enclosing, dereference) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosing.specialSimpleName), CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereference.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(operation) + foundOperator.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
child2 := cast(child2, foundOperator.arguments.readComponent(0).&type);
resultNode := __code.createAndAppendNode(parent).setData(before, foundOperator.&type, invokeInstructionFor(foundOperator, dereference), foundOperator);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
goto continue_label0;
end;
if argument2Type is ru.malik.elaborarer.avtoo.lang.ClassType then goto break_label1;
if not(argument1Type is PrimitiveType) then goto break_label0;
if operation >= O_VECT_OPERATOR then begin
commonType := argument1Type.getVectorCommonType(argument2Type);
end else begin
commonType := argument1Type.getScalarCommonType(argument2Type);
end;
if commonType = nil then goto break_label0;
kind := commonType.kind;
if (child1.instruction = LOAD_CONST) and (child2.instruction = LOAD_CONST) then begin
operand1 := child1.operandC;
operand2 := child2.operandC;
case operation of
O_SCAL_ADD: begin
case kind of
TYP_REAL:
resultValue := factory.createReal(operand1.asReal() + operand2.asReal());
TYP_DOUBLE:
resultValue := factory.createDouble(operand1.asDouble() + operand2.asDouble());
TYP_DOUBLE2:
resultValue := factory.createDouble2(operand1.asDouble2() + operand2.asDouble2());
TYP_DOUBLE4:
resultValue := factory.createDouble4(operand1.asDouble4() + operand2.asDouble4());
TYP_DOUBLE8:
resultValue := factory.createDouble8(operand1.asDouble8() + operand2.asDouble8());
TYP_FLOAT:
resultValue := factory.createFloat(operand1.asFloat() + operand2.asFloat());
TYP_FLOAT2:
resultValue := factory.createFloat2(operand1.asFloat2() + operand2.asFloat2());
TYP_FLOAT4:
resultValue := factory.createFloat4(operand1.asFloat4() + operand2.asFloat4());
TYP_FLOAT8:
resultValue := factory.createFloat8(operand1.asFloat8() + operand2.asFloat8());
TYP_INT:
resultValue := factory.createIntegral(operand1.asInt() + operand2.asInt());
TYP_INT2:
resultValue := factory.createInt2(operand1.asInt2() + operand2.asInt2());
TYP_INT4:
resultValue := factory.createInt4(operand1.asInt4() + operand2.asInt4());
TYP_INT8:
resultValue := factory.createInt8(operand1.asInt8() + operand2.asInt8());
TYP_LONG:
resultValue := factory.createLong(operand1.asLong() + operand2.asLong());
TYP_LONG2:
resultValue := factory.createLong2(operand1.asLong2() + operand2.asLong2());
TYP_LONG4:
resultValue := factory.createLong4(operand1.asLong4() + operand2.asLong4());
TYP_LONG8:
resultValue := factory.createLong8(operand1.asLong8() + operand2.asLong8());
else
goto break_label0;
end;
end;
O_SCAL_SUB: begin
case kind of
TYP_REAL:
resultValue := factory.createReal(operand1.asReal() - operand2.asReal());
TYP_DOUBLE:
resultValue := factory.createDouble(operand1.asDouble() - operand2.asDouble());
TYP_DOUBLE2:
resultValue := factory.createDouble2(operand1.asDouble2() - operand2.asDouble2());
TYP_DOUBLE4:
resultValue := factory.createDouble4(operand1.asDouble4() - operand2.asDouble4());
TYP_DOUBLE8:
resultValue := factory.createDouble8(operand1.asDouble8() - operand2.asDouble8());
TYP_FLOAT:
resultValue := factory.createFloat(operand1.asFloat() - operand2.asFloat());
TYP_FLOAT2:
resultValue := factory.createFloat2(operand1.asFloat2() - operand2.asFloat2());
TYP_FLOAT4:
resultValue := factory.createFloat4(operand1.asFloat4() - operand2.asFloat4());
TYP_FLOAT8:
resultValue := factory.createFloat8(operand1.asFloat8() - operand2.asFloat8());
TYP_INT:
resultValue := factory.createIntegral(operand1.asInt() - operand2.asInt());
TYP_INT2:
resultValue := factory.createInt2(operand1.asInt2() - operand2.asInt2());
TYP_INT4:
resultValue := factory.createInt4(operand1.asInt4() - operand2.asInt4());
TYP_INT8:
resultValue := factory.createInt8(operand1.asInt8() - operand2.asInt8());
TYP_LONG:
resultValue := factory.createLong(operand1.asLong() - operand2.asLong());
TYP_LONG2:
resultValue := factory.createLong2(operand1.asLong2() - operand2.asLong2());
TYP_LONG4:
resultValue := factory.createLong4(operand1.asLong4() - operand2.asLong4());
TYP_LONG8:
resultValue := factory.createLong8(operand1.asLong8() - operand2.asLong8());
else
goto break_label0;
end;
end;
O_VECT_ADD: begin
case kind of
TYP_DOUBLE:
resultValue := factory.createDouble(operand1.asDouble() + operand2.asDouble());
TYP_DOUBLE2:
resultValue := factory.createDouble2(Vector.add(operand1.asDouble2(), operand2.asDouble2()));
TYP_DOUBLE4:
resultValue := factory.createDouble4(Vector.add(operand1.asDouble4(), operand2.asDouble4()));
TYP_DOUBLE8:
resultValue := factory.createDouble8(Vector.add(operand1.asDouble8(), operand2.asDouble8()));
TYP_FLOAT:
resultValue := factory.createFloat(operand1.asFloat() + operand2.asFloat());
TYP_FLOAT2:
resultValue := factory.createFloat2(Vector.add(operand1.asFloat2(), operand2.asFloat2()));
TYP_FLOAT4:
resultValue := factory.createFloat4(Vector.add(operand1.asFloat4(), operand2.asFloat4()));
TYP_FLOAT8:
resultValue := factory.createFloat8(Vector.add(operand1.asFloat8(), operand2.asFloat8()));
TYP_BYTE:
resultValue := factory.createByte(byte(operand1.asByte() + operand2.asByte()));
TYP_BYTE2:
resultValue := factory.createByte2(Vector.add(operand1.asByte2(), operand2.asByte2()));
TYP_BYTE4:
resultValue := factory.createByte4(Vector.add(operand1.asByte4(), operand2.asByte4()));
TYP_BYTE8:
resultValue := factory.createByte8(Vector.add(operand1.asByte8(), operand2.asByte8()));
TYP_SHORT:
resultValue := factory.createShort(short(operand1.asShort() + operand2.asShort()));
TYP_SHORT2:
resultValue := factory.createShort2(Vector.add(operand1.asShort2(), operand2.asShort2()));
TYP_SHORT4:
resultValue := factory.createShort4(Vector.add(operand1.asShort4(), operand2.asShort4()));
TYP_SHORT8:
resultValue := factory.createShort8(Vector.add(operand1.asShort8(), operand2.asShort8()));
TYP_INT:
resultValue := factory.createInt(operand1.asInt() + operand2.asInt());
TYP_INT2:
resultValue := factory.createInt2(Vector.add(operand1.asInt2(), operand2.asInt2()));
TYP_INT4:
resultValue := factory.createInt4(Vector.add(operand1.asInt4(), operand2.asInt4()));
TYP_INT8:
resultValue := factory.createInt8(Vector.add(operand1.asInt8(), operand2.asInt8()));
TYP_LONG:
resultValue := factory.createLong(operand1.asLong() + operand2.asLong());
TYP_LONG2:
resultValue := factory.createLong2(Vector.add(operand1.asLong2(), operand2.asLong2()));
TYP_LONG4:
resultValue := factory.createLong4(Vector.add(operand1.asLong4(), operand2.asLong4()));
TYP_LONG8:
resultValue := factory.createLong8(Vector.add(operand1.asLong8(), operand2.asLong8()));
else
goto break_label0;
end;
end;
O_VECT_SUB: begin
case kind of
TYP_DOUBLE:
resultValue := factory.createDouble(operand1.asDouble() - operand2.asDouble());
TYP_DOUBLE2:
resultValue := factory.createDouble2(Vector.sub(operand1.asDouble2(), operand2.asDouble2()));
TYP_DOUBLE4:
resultValue := factory.createDouble4(Vector.sub(operand1.asDouble4(), operand2.asDouble4()));
TYP_DOUBLE8:
resultValue := factory.createDouble8(Vector.sub(operand1.asDouble8(), operand2.asDouble8()));
TYP_FLOAT:
resultValue := factory.createFloat(operand1.asFloat() - operand2.asFloat());
TYP_FLOAT2:
resultValue := factory.createFloat2(Vector.sub(operand1.asFloat2(), operand2.asFloat2()));
TYP_FLOAT4:
resultValue := factory.createFloat4(Vector.sub(operand1.asFloat4(), operand2.asFloat4()));
TYP_FLOAT8:
resultValue := factory.createFloat8(Vector.sub(operand1.asFloat8(), operand2.asFloat8()));
TYP_BYTE:
resultValue := factory.createByte(byte(operand1.asByte() - operand2.asByte()));
TYP_BYTE2:
resultValue := factory.createByte2(Vector.sub(operand1.asByte2(), operand2.asByte2()));
TYP_BYTE4:
resultValue := factory.createByte4(Vector.sub(operand1.asByte4(), operand2.asByte4()));
TYP_BYTE8:
resultValue := factory.createByte8(Vector.sub(operand1.asByte8(), operand2.asByte8()));
TYP_SHORT:
resultValue := factory.createShort(short(operand1.asShort() - operand2.asShort()));
TYP_SHORT2:
resultValue := factory.createShort2(Vector.sub(operand1.asShort2(), operand2.asShort2()));
TYP_SHORT4:
resultValue := factory.createShort4(Vector.sub(operand1.asShort4(), operand2.asShort4()));
TYP_SHORT8:
resultValue := factory.createShort8(Vector.sub(operand1.asShort8(), operand2.asShort8()));
TYP_INT:
resultValue := factory.createInt(operand1.asInt() - operand2.asInt());
TYP_INT2:
resultValue := factory.createInt2(Vector.sub(operand1.asInt2(), operand2.asInt2()));
TYP_INT4:
resultValue := factory.createInt4(Vector.sub(operand1.asInt4(), operand2.asInt4()));
TYP_INT8:
resultValue := factory.createInt8(Vector.sub(operand1.asInt8(), operand2.asInt8()));
TYP_LONG:
resultValue := factory.createLong(operand1.asLong() - operand2.asLong());
TYP_LONG2:
resultValue := factory.createLong2(Vector.sub(operand1.asLong2(), operand2.asLong2()));
TYP_LONG4:
resultValue := factory.createLong4(Vector.sub(operand1.asLong4(), operand2.asLong4()));
TYP_LONG8:
resultValue := factory.createLong8(Vector.sub(operand1.asLong8(), operand2.asLong8()));
else
goto break_label0;
end;
end;
O_VECT_SADD: begin
case kind of
TYP_BYTE:
resultValue := factory.createByte(Vector.sadd(operand1.asByte(), operand2.asByte()));
TYP_BYTE2:
resultValue := factory.createByte2(Vector.sadd(operand1.asByte2(), operand2.asByte2()));
TYP_BYTE4:
resultValue := factory.createByte4(Vector.sadd(operand1.asByte4(), operand2.asByte4()));
TYP_BYTE8:
resultValue := factory.createByte8(Vector.sadd(operand1.asByte8(), operand2.asByte8()));
TYP_SHORT:
resultValue := factory.createShort(Vector.sadd(operand1.asShort(), operand2.asShort()));
TYP_SHORT2:
resultValue := factory.createShort2(Vector.sadd(operand1.asShort2(), operand2.asShort2()));
TYP_SHORT4:
resultValue := factory.createShort4(Vector.sadd(operand1.asShort4(), operand2.asShort4()));
TYP_SHORT8:
resultValue := factory.createShort8(Vector.sadd(operand1.asShort8(), operand2.asShort8()));
else
goto break_label0;
end;
end;
O_VECT_SADDU: begin
case kind of
TYP_BYTE:
resultValue := factory.createByte(Vector.saddu(operand1.asByte(), operand2.asByte()));
TYP_BYTE2:
resultValue := factory.createByte2(Vector.saddu(operand1.asByte2(), operand2.asByte2()));
TYP_BYTE4:
resultValue := factory.createByte4(Vector.saddu(operand1.asByte4(), operand2.asByte4()));
TYP_BYTE8:
resultValue := factory.createByte8(Vector.saddu(operand1.asByte8(), operand2.asByte8()));
TYP_SHORT:
resultValue := factory.createShort(Vector.saddu(operand1.asShort(), operand2.asShort()));
TYP_SHORT2:
resultValue := factory.createShort2(Vector.saddu(operand1.asShort2(), operand2.asShort2()));
TYP_SHORT4:
resultValue := factory.createShort4(Vector.saddu(operand1.asShort4(), operand2.asShort4()));
TYP_SHORT8:
resultValue := factory.createShort8(Vector.saddu(operand1.asShort8(), operand2.asShort8()));
else
goto break_label0;
end;
end;
O_VECT_SSUB: begin
case kind of
TYP_BYTE:
resultValue := factory.createByte(Vector.ssub(operand1.asByte(), operand2.asByte()));
TYP_BYTE2:
resultValue := factory.createByte2(Vector.ssub(operand1.asByte2(), operand2.asByte2()));
TYP_BYTE4:
resultValue := factory.createByte4(Vector.ssub(operand1.asByte4(), operand2.asByte4()));
TYP_BYTE8:
resultValue := factory.createByte8(Vector.ssub(operand1.asByte8(), operand2.asByte8()));
TYP_SHORT:
resultValue := factory.createShort(Vector.ssub(operand1.asShort(), operand2.asShort()));
TYP_SHORT2:
resultValue := factory.createShort2(Vector.ssub(operand1.asShort2(), operand2.asShort2()));
TYP_SHORT4:
resultValue := factory.createShort4(Vector.ssub(operand1.asShort4(), operand2.asShort4()));
TYP_SHORT8:
resultValue := factory.createShort8(Vector.ssub(operand1.asShort8(), operand2.asShort8()));
else
goto break_label0;
end;
end;
O_VECT_SSUBU: begin
case kind of
TYP_BYTE:
resultValue := factory.createByte(Vector.ssubu(operand1.asByte(), operand2.asByte()));
TYP_BYTE2:
resultValue := factory.createByte2(Vector.ssubu(operand1.asByte2(), operand2.asByte2()));
TYP_BYTE4:
resultValue := factory.createByte4(Vector.ssubu(operand1.asByte4(), operand2.asByte4()));
TYP_BYTE8:
resultValue := factory.createByte8(Vector.ssubu(operand1.asByte8(), operand2.asByte8()));
TYP_SHORT:
resultValue := factory.createShort(Vector.ssubu(operand1.asShort(), operand2.asShort()));
TYP_SHORT2:
resultValue := factory.createShort2(Vector.ssubu(operand1.asShort2(), operand2.asShort2()));
TYP_SHORT4:
resultValue := factory.createShort4(Vector.ssubu(operand1.asShort4(), operand2.asShort4()));
TYP_SHORT8:
resultValue := factory.createShort8(Vector.ssubu(operand1.asShort8(), operand2.asShort8()));
else
goto break_label0;
end;
end;
else
resultValue := nil;
end;
child1.setData(child1.position, resultValue.&type, LOAD_CONST, resultValue);
__code.removeNode(child2);
goto continue_label0;
end;
case operation of
O_SCAL_ADD,
O_SCAL_SUB: begin
if (kind >= TYP_REAL) and (kind <= TYP_FLOAT8) or (kind >= TYP_INT) and (kind <= TYP_LONG8) then begin
resultType := commonType;
goto break_label2;
end;
goto break_label0;
end;
O_VECT_ADD,
O_VECT_SUB: begin
if (kind >= TYP_DOUBLE) and (kind <= TYP_LONG8) then begin
resultType := commonType;
goto break_label2;
end;
goto break_label0;
end;
O_VECT_SADD,
O_VECT_SADDU,
O_VECT_SSUB,
O_VECT_SSUBU: begin
if (kind >= TYP_BYTE) and (kind <= TYP_SHORT8) then begin
resultType := commonType;
goto break_label2;
end;
goto break_label0;
end;
else
resultType := nil;
end;
break_label2:
child1 := cast(child1, commonType);
child2 := cast(child2, commonType);
resultNode := __code.createAndAppendNode(parent).setData(before, resultType, operation, commonType);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
goto continue_label0;
end;
break_label1:
if
(operation = O_SCAL_ADD) and (argument1Type = getPrimitiveType(TYP_CHAR)) and (argument2Type = typeString) and
(child1.instruction = LOAD_CONST) and (child2.instruction = LOAD_CONST)
then begin
operand2AsValue := child2.operandC.asInterface() as Value;
if operand2AsValue <> nil then begin
operand1AsUChar := child1.operandC.asUChar();
child1.setData(child1.position, typeString, LOAD_CONST, factory.createString(operand1AsUChar + operand2AsValue.asUnicodeString()));
__code.removeNode(child2);
goto continue_label0;
end;
end;
dereference := ru.malik.elaborarer.avtoo.lang.ClassType(argument2Type);
arguments := [ argument1Type ];
inc(operation, R_DELTA);
foundOperators := dereference.findOperators(operation, arguments, enclosing);
foundLength := system.length(foundOperators);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereference), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(operation))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundOperator := foundOperators[0];
if not foundOperator.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator'), [
CoObject.create(foundOperator), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundOperator.isVisibleFrom(enclosing, dereference) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosing.specialSimpleName), CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereference.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(operation) + foundOperator.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
child1 := cast(child1, foundOperator.arguments.readComponent(0).&type);
resultNode := __code.createAndAppendNode(parent).setData(before, foundOperator.&type, invokeInstructionFor(foundOperator, dereference), foundOperator);
__code.createAndAppendNode(resultNode).setData(before, nil, SWAP, argument1Type);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
goto continue_label0;
end;
break_label0:
begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.2'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type), CoObject.create(argument2Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
continue_label0:
operation := source.getLexemeKind(position);
until
(operation <> O_SCAL_ADD) and (operation <> O_SCAL_SUB) and (operation <> O_VECT_SADD) and (operation <> O_VECT_SADDU) and
(operation <> O_VECT_ADD) and (operation <> O_VECT_SUB) and (operation <> O_VECT_SSUB) and (operation <> O_VECT_SSUBU)
;
end;
result := position;
end;
function ImmediateBuilder.parseShift(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
label
break_label0,
break_label1,
break_label2,
continue_label0;
var
kind: int;
before: int;
operation: int;
foundLength: int;
arguments: Type_Array1d;
foundOperators: Operator_Array1d;
child1: Node;
child2: Node;
__code: Code;
resultNode: Node;
resultType: &Type;
commonType: &Type;
operand1: Constant;
operand2: Constant;
argument1Type: &Type;
argument2Type: &Type;
resultValue: Constant;
factory: ConstantFactory;
foundOperator: &Operator;
enclosing: ru.malik.elaborarer.avtoo.lang.ClassType;
dereference: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
position := parseAdditive(parent, source, position, isStaticOnly);
operation := source.getLexemeKind(position);
if
(operation = O_SCAL_SHL) or (operation = O_SCAL_SHR) or (operation = O_SCAL_SHRU) or
(operation = O_VECT_SHL) or (operation = O_VECT_SHR) or (operation = O_VECT_SHRU)
then begin
__code := parent.parentCode;
enclosing := __code.parentCallable.parentType;
factory := fldConstantFactory;
child1 := parent.readComponent(-1);
repeat
before := position;
position := parseAdditive(parent, source, position + 1, isStaticOnly);
child2 := parent.readComponent(-1);
argument1Type := child1.&type;
argument2Type := child2.&type;
begin
begin
if argument1Type is ru.malik.elaborarer.avtoo.lang.ClassType then begin
dereference := ru.malik.elaborarer.avtoo.lang.ClassType(argument1Type);
arguments := [ argument2Type ];
foundOperators := dereference.findOperators(operation, arguments, enclosing);
foundLength := system.length(foundOperators);
if foundLength < 1 then begin
if argument2Type is ru.malik.elaborarer.avtoo.lang.ClassType then goto break_label1;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereference), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(operation))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundOperator := foundOperators[0];
if not foundOperator.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator'), [
CoObject.create(foundOperator), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundOperator.isVisibleFrom(enclosing, dereference) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosing.specialSimpleName), CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereference.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(operation) + foundOperator.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
child2 := cast(child2, foundOperator.arguments.readComponent(0).&type);
resultNode := __code.createAndAppendNode(parent).setData(before, foundOperator.&type, invokeInstructionFor(foundOperator, dereference), foundOperator);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
goto continue_label0;
end;
if argument2Type is ru.malik.elaborarer.avtoo.lang.ClassType then goto break_label1;
if not(argument1Type is PrimitiveType) or not argument2Type.isInt() then goto break_label0;
if operation >= O_VECT_OPERATOR then begin
commonType := argument1Type;
end else begin
commonType := argument1Type.getScalarCommonType(argument1Type);
end;
if commonType = nil then goto break_label0;
kind := commonType.kind;
if (child1.instruction = LOAD_CONST) and (child2.instruction = LOAD_CONST) then begin
operand1 := child1.operandC;
operand2 := child2.operandC;
case operation of
O_SCAL_SHL: begin
case kind of
TYP_INT:
resultValue := factory.createIntegral(operand1.asInt() shl operand2.asInt());
TYP_INT2:
resultValue := factory.createInt2(operand1.asInt2() shl operand2.asInt());
TYP_INT4:
resultValue := factory.createInt4(operand1.asInt4() shl operand2.asInt());
TYP_INT8:
resultValue := factory.createInt8(operand1.asInt8() shl operand2.asInt());
TYP_LONG:
resultValue := factory.createLong(operand1.asLong() shl operand2.asInt());
TYP_LONG2:
resultValue := factory.createLong2(operand1.asLong2() shl operand2.asInt());
TYP_LONG4:
resultValue := factory.createLong4(operand1.asLong4() shl operand2.asInt());
TYP_LONG8:
resultValue := factory.createLong8(operand1.asLong8() shl operand2.asInt());
else
goto break_label0;
end;
end;
O_SCAL_SHR: begin
case kind of
TYP_INT:
resultValue := factory.createIntegral(CoInt.sar(operand1.asInt(), operand2.asInt()));
TYP_INT2:
resultValue := factory.createInt2(Scalar.sar(operand1.asInt2(), operand2.asInt()));
TYP_INT4:
resultValue := factory.createInt4(Scalar.sar(operand1.asInt4(), operand2.asInt()));
TYP_INT8:
resultValue := factory.createInt8(Scalar.sar(operand1.asInt8(), operand2.asInt()));
TYP_LONG:
resultValue := factory.createLong(CoLong.sar(operand1.asLong(), operand2.asInt()));
TYP_LONG2:
resultValue := factory.createLong2(Scalar.sar(operand1.asLong2(), operand2.asInt()));
TYP_LONG4:
resultValue := factory.createLong4(Scalar.sar(operand1.asLong4(), operand2.asInt()));
TYP_LONG8:
resultValue := factory.createLong8(Scalar.sar(operand1.asLong8(), operand2.asInt()));
else
goto break_label0;
end;
end;
O_SCAL_SHRU: begin
case kind of
TYP_INT:
resultValue := factory.createIntegral(operand1.asInt() shr operand2.asInt());
TYP_INT2:
resultValue := factory.createInt2(operand1.asInt2() shr operand2.asInt());
TYP_INT4:
resultValue := factory.createInt4(operand1.asInt4() shr operand2.asInt());
TYP_INT8:
resultValue := factory.createInt8(operand1.asInt8() shr operand2.asInt());
TYP_LONG:
resultValue := factory.createLong(operand1.asLong() shr operand2.asInt());
TYP_LONG2:
resultValue := factory.createLong2(operand1.asLong2() shr operand2.asInt());
TYP_LONG4:
resultValue := factory.createLong4(operand1.asLong4() shr operand2.asInt());
TYP_LONG8:
resultValue := factory.createLong8(operand1.asLong8() shr operand2.asInt());
else
goto break_label0;
end;
end;
O_VECT_SHL: begin
case kind of
TYP_BYTE:
resultValue := factory.createByte(byte(operand1.asInt() shl operand2.asInt()));
TYP_BYTE2:
resultValue := factory.createByte2(Vector.&shl(operand1.asByte2(), operand2.asInt()));
TYP_BYTE4:
resultValue := factory.createByte4(Vector.&shl(operand1.asByte4(), operand2.asInt()));
TYP_BYTE8:
resultValue := factory.createByte8(Vector.&shl(operand1.asByte8(), operand2.asInt()));
TYP_SHORT:
resultValue := factory.createShort(short(operand1.asInt() shl operand2.asInt()));
TYP_SHORT2:
resultValue := factory.createShort2(Vector.&shl(operand1.asShort2(), operand2.asInt()));
TYP_SHORT4:
resultValue := factory.createShort4(Vector.&shl(operand1.asShort4(), operand2.asInt()));
TYP_SHORT8:
resultValue := factory.createShort8(Vector.&shl(operand1.asShort8(), operand2.asInt()));
TYP_INT:
resultValue := factory.createInt(operand1.asInt() shl operand2.asInt());
TYP_INT2:
resultValue := factory.createInt2(Vector.&shl(operand1.asInt2(), operand2.asInt()));
TYP_INT4:
resultValue := factory.createInt4(Vector.&shl(operand1.asInt4(), operand2.asInt()));
TYP_INT8:
resultValue := factory.createInt8(Vector.&shl(operand1.asInt8(), operand2.asInt()));
TYP_LONG:
resultValue := factory.createLong(operand1.asLong() shl operand2.asInt());
TYP_LONG2:
resultValue := factory.createLong2(Vector.&shl(operand1.asLong2(), operand2.asInt()));
TYP_LONG4:
resultValue := factory.createLong4(Vector.&shl(operand1.asLong4(), operand2.asInt()));
TYP_LONG8:
resultValue := factory.createLong8(Vector.&shl(operand1.asLong8(), operand2.asInt()));
else
goto break_label0;
end;
end;
O_VECT_SHR: begin
case kind of
TYP_BYTE:
resultValue := factory.createByte(byte(CoInt.sar(operand1.asInt(), operand2.asInt())));
TYP_BYTE2:
resultValue := factory.createByte2(Vector.sar(operand1.asByte2(), operand2.asInt()));
TYP_BYTE4:
resultValue := factory.createByte4(Vector.sar(operand1.asByte4(), operand2.asInt()));
TYP_BYTE8:
resultValue := factory.createByte8(Vector.sar(operand1.asByte8(), operand2.asInt()));
TYP_SHORT:
resultValue := factory.createShort(short(CoInt.sar(operand1.asInt(), operand2.asInt())));
TYP_SHORT2:
resultValue := factory.createShort2(Vector.sar(operand1.asShort2(), operand2.asInt()));
TYP_SHORT4:
resultValue := factory.createShort4(Vector.sar(operand1.asShort4(), operand2.asInt()));
TYP_SHORT8:
resultValue := factory.createShort8(Vector.sar(operand1.asShort8(), operand2.asInt()));
TYP_INT:
resultValue := factory.createInt(CoInt.sar(operand1.asInt(), operand2.asInt()));
TYP_INT2:
resultValue := factory.createInt2(Vector.sar(operand1.asInt2(), operand2.asInt()));
TYP_INT4:
resultValue := factory.createInt4(Vector.sar(operand1.asInt4(), operand2.asInt()));
TYP_INT8:
resultValue := factory.createInt8(Vector.sar(operand1.asInt8(), operand2.asInt()));
TYP_LONG:
resultValue := factory.createLong(CoLong.sar(operand1.asLong(), operand2.asInt()));
TYP_LONG2:
resultValue := factory.createLong2(Vector.sar(operand1.asLong2(), operand2.asInt()));
TYP_LONG4:
resultValue := factory.createLong4(Vector.sar(operand1.asLong4(), operand2.asInt()));
TYP_LONG8:
resultValue := factory.createLong8(Vector.sar(operand1.asLong8(), operand2.asInt()));
else
goto break_label0;
end;
end;
O_VECT_SHRU: begin
case kind of
TYP_BYTE:
resultValue := factory.createByte(byte(operand1.asInt() shr operand2.asInt()));
TYP_BYTE2:
resultValue := factory.createByte2(Vector.&shr(operand1.asByte2(), operand2.asInt()));
TYP_BYTE4:
resultValue := factory.createByte4(Vector.&shr(operand1.asByte4(), operand2.asInt()));
TYP_BYTE8:
resultValue := factory.createByte8(Vector.&shr(operand1.asByte8(), operand2.asInt()));
TYP_SHORT:
resultValue := factory.createShort(short(operand1.asInt() shr operand2.asInt()));
TYP_SHORT2:
resultValue := factory.createShort2(Vector.&shr(operand1.asShort2(), operand2.asInt()));
TYP_SHORT4:
resultValue := factory.createShort4(Vector.&shr(operand1.asShort4(), operand2.asInt()));
TYP_SHORT8:
resultValue := factory.createShort8(Vector.&shr(operand1.asShort8(), operand2.asInt()));
TYP_INT:
resultValue := factory.createInt(operand1.asInt() shr operand2.asInt());
TYP_INT2:
resultValue := factory.createInt2(Vector.&shr(operand1.asInt2(), operand2.asInt()));
TYP_INT4:
resultValue := factory.createInt4(Vector.&shr(operand1.asInt4(), operand2.asInt()));
TYP_INT8:
resultValue := factory.createInt8(Vector.&shr(operand1.asInt8(), operand2.asInt()));
TYP_LONG:
resultValue := factory.createLong(operand1.asLong() shr operand2.asInt());
TYP_LONG2:
resultValue := factory.createLong2(Vector.&shr(operand1.asLong2(), operand2.asInt()));
TYP_LONG4:
resultValue := factory.createLong4(Vector.&shr(operand1.asLong4(), operand2.asInt()));
TYP_LONG8:
resultValue := factory.createLong8(Vector.&shr(operand1.asLong8(), operand2.asInt()));
else
goto break_label0;
end;
end;
else
resultValue := nil;
end;
child1.setData(child1.position, resultValue.&type, LOAD_CONST, resultValue);
__code.removeNode(child2);
goto continue_label0;
end;
case operation of
O_SCAL_SHL,
O_SCAL_SHR,
O_SCAL_SHRU: begin
if (kind >= TYP_INT) and (kind <= TYP_LONG8) then begin
resultType := commonType;
goto break_label2;
end;
goto break_label0;
end;
O_VECT_SHL,
O_VECT_SHR,
O_VECT_SHRU: begin
if (kind >= TYP_BYTE) and (kind <= TYP_LONG8) then begin
resultType := commonType;
goto break_label2;
end;
goto break_label0;
end;
else
resultType := nil;
end;
break_label2:
child1 := cast(child1, commonType);
resultNode := __code.createAndAppendNode(parent).setData(before, resultType, operation, commonType);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
goto continue_label0;
end;
break_label1:
dereference := ru.malik.elaborarer.avtoo.lang.ClassType(argument2Type);
arguments := [ argument1Type ];
inc(operation, R_DELTA);
foundOperators := dereference.findOperators(operation, arguments, enclosing);
foundLength := system.length(foundOperators);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereference), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(operation))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundOperator := foundOperators[0];
if not foundOperator.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator'), [
CoObject.create(foundOperator), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundOperator.isVisibleFrom(enclosing, dereference) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosing.specialSimpleName), CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereference.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(operation) + foundOperator.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
child1 := cast(child1, foundOperator.arguments.readComponent(0).&type);
resultNode := __code.createAndAppendNode(parent).setData(before, foundOperator.&type, invokeInstructionFor(foundOperator, dereference), foundOperator);
__code.createAndAppendNode(resultNode).setData(before, nil, SWAP, argument1Type);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
goto continue_label0;
end;
break_label0:
begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.2'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type), CoObject.create(argument2Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
continue_label0:
operation := source.getLexemeKind(position);
until
(operation <> O_SCAL_SHL) and (operation <> O_SCAL_SHR) and (operation <> O_SCAL_SHRU) and
(operation <> O_VECT_SHL) and (operation <> O_VECT_SHR) and (operation <> O_VECT_SHRU)
;
end;
result := position;
end;
function ImmediateBuilder.parseRelational(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
label
break_label0,
break_label1,
break_label2,
continue_label0;
var
kind: int;
before: int;
operation: int;
foundLength: int;
arguments: Type_Array1d;
foundOperators: Operator_Array1d;
child1: Node;
child2: Node;
__code: Code;
checkType: &Type;
resultNode: Node;
resultType: &Type;
commonType: &Type;
operand1: Constant;
operand2: Constant;
argument1Type: &Type;
argument2Type: &Type;
resultValue: Constant;
factory: ConstantFactory;
foundOperator: &Operator;
checkTypeHolder: ImmediateBuilderItemHolder;
enclosing: ru.malik.elaborarer.avtoo.lang.ClassType;
dereference: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
position := parseShift(parent, source, position, isStaticOnly);
operation := source.getLexemeKind(position);
if
(operation = O_SCAL_GT) or (operation = O_SCAL_GE) or (operation = O_SCAL_LT) or (operation = O_SCAL_LE) or
(operation = O_VECT_GT) or (operation = O_VECT_GE) or (operation = O_VECT_LT) or (operation = O_VECT_LE) or
(operation = EXP_INSTANCEOF)
then begin
__code := parent.parentCode;
enclosing := __code.parentCallable.parentType;
factory := fldConstantFactory;
child1 := parent.readComponent(-1);
repeat
before := position;
if operation = EXP_INSTANCEOF then begin
argument1Type := child1.&type;
if not(argument1Type is ru.malik.elaborarer.avtoo.lang.ClassType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.1'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
checkTypeHolder := getItemHolder();
position := parseTypeName(source, position + 1, enclosing, checkTypeHolder);
checkType := checkTypeHolder.resultType;
if not(checkType is ru.malik.elaborarer.avtoo.lang.ClassType) then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.name.class-type'));
exception.source := source;
exception.position := before + 1;
raise exception;
end;
if not argument1Type.isCompatibleWith(checkType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'incompatible-types'), [
CoObject.create(argument1Type), CoObject.create(checkType)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
checkType.makeCompilable();
resultNode := __code.createAndAppendNode(parent).setData(before, fldTypeBoolean, EXP_INSTANCEOF, checkType);
__code.moveNode(child1, resultNode, 0);
child1 := resultNode;
goto continue_label0;
end;
position := parseShift(parent, source, position + 1, isStaticOnly);
child2 := parent.readComponent(-1);
argument1Type := child1.&type;
argument2Type := child2.&type;
begin
begin
if argument1Type is ru.malik.elaborarer.avtoo.lang.ClassType then begin
dereference := ru.malik.elaborarer.avtoo.lang.ClassType(argument1Type);
arguments := [ argument2Type ];
foundOperators := dereference.findOperators(operation, arguments, enclosing);
foundLength := system.length(foundOperators);
if foundLength < 1 then begin
if argument2Type is ru.malik.elaborarer.avtoo.lang.ClassType then goto break_label1;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereference), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(operation))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundOperator := foundOperators[0];
if not foundOperator.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator'), [
CoObject.create(foundOperator), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundOperator.isVisibleFrom(enclosing, dereference) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosing.specialSimpleName), CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereference.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(operation) + foundOperator.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
child2 := cast(child2, foundOperator.arguments.readComponent(0).&type);
resultNode := __code.createAndAppendNode(parent).setData(before, foundOperator.&type, invokeInstructionFor(foundOperator, dereference), foundOperator);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
goto continue_label0;
end;
if argument2Type is ru.malik.elaborarer.avtoo.lang.ClassType then goto break_label1;
if not(argument1Type is PrimitiveType) then goto break_label0;
if operation >= O_VECT_OPERATOR then begin
commonType := argument1Type.getVectorCommonType(argument2Type);
end else begin
commonType := argument1Type.getScalarCommonType(argument2Type);
end;
if commonType = nil then goto break_label0;
kind := commonType.kind;
if (child1.instruction = LOAD_CONST) and (child2.instruction = LOAD_CONST) then begin
operand1 := child1.operandC;
operand2 := child2.operandC;
case operation of
O_SCAL_GT: begin
case kind of
TYP_REAL:
resultValue := factory.createBoolean(operand1.asReal() > operand2.asReal());
TYP_DOUBLE:
resultValue := factory.createBoolean(operand1.asDouble() > operand2.asDouble());
TYP_FLOAT:
resultValue := factory.createBoolean(operand1.asFloat() > operand2.asFloat());
TYP_INT:
resultValue := factory.createBoolean(operand1.asInt() > operand2.asInt());
TYP_LONG:
resultValue := factory.createBoolean(operand1.asLong() > operand2.asLong());
else
goto break_label0;
end;
end;
O_SCAL_GE: begin
case kind of
TYP_REAL:
resultValue := factory.createBoolean(operand1.asReal() >= operand2.asReal());
TYP_DOUBLE:
resultValue := factory.createBoolean(operand1.asDouble() >= operand2.asDouble());
TYP_FLOAT:
resultValue := factory.createBoolean(operand1.asFloat() >= operand2.asFloat());
TYP_INT:
resultValue := factory.createBoolean(operand1.asInt() >= operand2.asInt());
TYP_LONG:
resultValue := factory.createBoolean(operand1.asLong() >= operand2.asLong());
else
goto break_label0;
end;
end;
O_SCAL_LT: begin
case kind of
TYP_REAL:
resultValue := factory.createBoolean(operand1.asReal() < operand2.asReal());
TYP_DOUBLE:
resultValue := factory.createBoolean(operand1.asDouble() < operand2.asDouble());
TYP_FLOAT:
resultValue := factory.createBoolean(operand1.asFloat() < operand2.asFloat());
TYP_INT:
resultValue := factory.createBoolean(operand1.asInt() < operand2.asInt());
TYP_LONG:
resultValue := factory.createBoolean(operand1.asLong() < operand2.asLong());
else
goto break_label0;
end;
end;
O_SCAL_LE: begin
case kind of
TYP_REAL:
resultValue := factory.createBoolean(operand1.asReal() <= operand2.asReal());
TYP_DOUBLE:
resultValue := factory.createBoolean(operand1.asDouble() <= operand2.asDouble());
TYP_FLOAT:
resultValue := factory.createBoolean(operand1.asFloat() <= operand2.asFloat());
TYP_INT:
resultValue := factory.createBoolean(operand1.asInt() <= operand2.asInt());
TYP_LONG:
resultValue := factory.createBoolean(operand1.asLong() <= operand2.asLong());
else
goto break_label0;
end;
end;
O_VECT_GT: begin
case kind of
TYP_DOUBLE:
resultValue := factory.createLong(Vector.gt(operand1.asDouble(), operand2.asDouble()));
TYP_DOUBLE2:
resultValue := factory.createLong2(Vector.gt(operand1.asDouble2(), operand2.asDouble2()));
TYP_DOUBLE4:
resultValue := factory.createLong4(Vector.gt(operand1.asDouble4(), operand2.asDouble4()));
TYP_DOUBLE8:
resultValue := factory.createLong8(Vector.gt(operand1.asDouble8(), operand2.asDouble8()));
TYP_FLOAT:
resultValue := factory.createInt(Vector.gt(operand1.asFloat(), operand2.asFloat()));
TYP_FLOAT2:
resultValue := factory.createInt2(Vector.gt(operand1.asFloat2(), operand2.asFloat2()));
TYP_FLOAT4:
resultValue := factory.createInt4(Vector.gt(operand1.asFloat4(), operand2.asFloat4()));
TYP_FLOAT8:
resultValue := factory.createInt8(Vector.gt(operand1.asFloat8(), operand2.asFloat8()));
TYP_BYTE:
resultValue := factory.createByte(Vector.gt(operand1.asByte(), operand2.asByte()));
TYP_BYTE2:
resultValue := factory.createByte2(Vector.gt(operand1.asByte2(), operand2.asByte2()));
TYP_BYTE4:
resultValue := factory.createByte4(Vector.gt(operand1.asByte4(), operand2.asByte4()));
TYP_BYTE8:
resultValue := factory.createByte8(Vector.gt(operand1.asByte8(), operand2.asByte8()));
TYP_SHORT:
resultValue := factory.createShort(Vector.gt(operand1.asShort(), operand2.asShort()));
TYP_SHORT2:
resultValue := factory.createShort2(Vector.gt(operand1.asShort2(), operand2.asShort2()));
TYP_SHORT4:
resultValue := factory.createShort4(Vector.gt(operand1.asShort4(), operand2.asShort4()));
TYP_SHORT8:
resultValue := factory.createShort8(Vector.gt(operand1.asShort8(), operand2.asShort8()));
TYP_INT:
resultValue := factory.createInt(Vector.gt(operand1.asInt(), operand2.asInt()));
TYP_INT2:
resultValue := factory.createInt2(Vector.gt(operand1.asInt2(), operand2.asInt2()));
TYP_INT4:
resultValue := factory.createInt4(Vector.gt(operand1.asInt4(), operand2.asInt4()));
TYP_INT8:
resultValue := factory.createInt8(Vector.gt(operand1.asInt8(), operand2.asInt8()));
TYP_LONG:
resultValue := factory.createLong(Vector.gt(operand1.asLong(), operand2.asLong()));
TYP_LONG2:
resultValue := factory.createLong2(Vector.gt(operand1.asLong2(), operand2.asLong2()));
TYP_LONG4:
resultValue := factory.createLong4(Vector.gt(operand1.asLong4(), operand2.asLong4()));
TYP_LONG8:
resultValue := factory.createLong8(Vector.gt(operand1.asLong8(), operand2.asLong8()));
else
goto break_label0;
end;
end;
O_VECT_GE: begin
case kind of
TYP_DOUBLE:
resultValue := factory.createLong(Vector.ge(operand1.asDouble(), operand2.asDouble()));
TYP_DOUBLE2:
resultValue := factory.createLong2(Vector.ge(operand1.asDouble2(), operand2.asDouble2()));
TYP_DOUBLE4:
resultValue := factory.createLong4(Vector.ge(operand1.asDouble4(), operand2.asDouble4()));
TYP_DOUBLE8:
resultValue := factory.createLong8(Vector.ge(operand1.asDouble8(), operand2.asDouble8()));
TYP_FLOAT:
resultValue := factory.createInt(Vector.ge(operand1.asFloat(), operand2.asFloat()));
TYP_FLOAT2:
resultValue := factory.createInt2(Vector.ge(operand1.asFloat2(), operand2.asFloat2()));
TYP_FLOAT4:
resultValue := factory.createInt4(Vector.ge(operand1.asFloat4(), operand2.asFloat4()));
TYP_FLOAT8:
resultValue := factory.createInt8(Vector.ge(operand1.asFloat8(), operand2.asFloat8()));
TYP_BYTE:
resultValue := factory.createByte(Vector.ge(operand1.asByte(), operand2.asByte()));
TYP_BYTE2:
resultValue := factory.createByte2(Vector.ge(operand1.asByte2(), operand2.asByte2()));
TYP_BYTE4:
resultValue := factory.createByte4(Vector.ge(operand1.asByte4(), operand2.asByte4()));
TYP_BYTE8:
resultValue := factory.createByte8(Vector.ge(operand1.asByte8(), operand2.asByte8()));
TYP_SHORT:
resultValue := factory.createShort(Vector.ge(operand1.asShort(), operand2.asShort()));
TYP_SHORT2:
resultValue := factory.createShort2(Vector.ge(operand1.asShort2(), operand2.asShort2()));
TYP_SHORT4:
resultValue := factory.createShort4(Vector.ge(operand1.asShort4(), operand2.asShort4()));
TYP_SHORT8:
resultValue := factory.createShort8(Vector.ge(operand1.asShort8(), operand2.asShort8()));
TYP_INT:
resultValue := factory.createInt(Vector.ge(operand1.asInt(), operand2.asInt()));
TYP_INT2:
resultValue := factory.createInt2(Vector.ge(operand1.asInt2(), operand2.asInt2()));
TYP_INT4:
resultValue := factory.createInt4(Vector.ge(operand1.asInt4(), operand2.asInt4()));
TYP_INT8:
resultValue := factory.createInt8(Vector.ge(operand1.asInt8(), operand2.asInt8()));
TYP_LONG:
resultValue := factory.createLong(Vector.ge(operand1.asLong(), operand2.asLong()));
TYP_LONG2:
resultValue := factory.createLong2(Vector.ge(operand1.asLong2(), operand2.asLong2()));
TYP_LONG4:
resultValue := factory.createLong4(Vector.ge(operand1.asLong4(), operand2.asLong4()));
TYP_LONG8:
resultValue := factory.createLong8(Vector.ge(operand1.asLong8(), operand2.asLong8()));
else
goto break_label0;
end;
end;
O_VECT_LT: begin
case kind of
TYP_DOUBLE:
resultValue := factory.createLong(Vector.lt(operand1.asDouble(), operand2.asDouble()));
TYP_DOUBLE2:
resultValue := factory.createLong2(Vector.lt(operand1.asDouble2(), operand2.asDouble2()));
TYP_DOUBLE4:
resultValue := factory.createLong4(Vector.lt(operand1.asDouble4(), operand2.asDouble4()));
TYP_DOUBLE8:
resultValue := factory.createLong8(Vector.lt(operand1.asDouble8(), operand2.asDouble8()));
TYP_FLOAT:
resultValue := factory.createInt(Vector.lt(operand1.asFloat(), operand2.asFloat()));
TYP_FLOAT2:
resultValue := factory.createInt2(Vector.lt(operand1.asFloat2(), operand2.asFloat2()));
TYP_FLOAT4:
resultValue := factory.createInt4(Vector.lt(operand1.asFloat4(), operand2.asFloat4()));
TYP_FLOAT8:
resultValue := factory.createInt8(Vector.lt(operand1.asFloat8(), operand2.asFloat8()));
TYP_BYTE:
resultValue := factory.createByte(Vector.lt(operand1.asByte(), operand2.asByte()));
TYP_BYTE2:
resultValue := factory.createByte2(Vector.lt(operand1.asByte2(), operand2.asByte2()));
TYP_BYTE4:
resultValue := factory.createByte4(Vector.lt(operand1.asByte4(), operand2.asByte4()));
TYP_BYTE8:
resultValue := factory.createByte8(Vector.lt(operand1.asByte8(), operand2.asByte8()));
TYP_SHORT:
resultValue := factory.createShort(Vector.lt(operand1.asShort(), operand2.asShort()));
TYP_SHORT2:
resultValue := factory.createShort2(Vector.lt(operand1.asShort2(), operand2.asShort2()));
TYP_SHORT4:
resultValue := factory.createShort4(Vector.lt(operand1.asShort4(), operand2.asShort4()));
TYP_SHORT8:
resultValue := factory.createShort8(Vector.lt(operand1.asShort8(), operand2.asShort8()));
TYP_INT:
resultValue := factory.createInt(Vector.lt(operand1.asInt(), operand2.asInt()));
TYP_INT2:
resultValue := factory.createInt2(Vector.lt(operand1.asInt2(), operand2.asInt2()));
TYP_INT4:
resultValue := factory.createInt4(Vector.lt(operand1.asInt4(), operand2.asInt4()));
TYP_INT8:
resultValue := factory.createInt8(Vector.lt(operand1.asInt8(), operand2.asInt8()));
TYP_LONG:
resultValue := factory.createLong(Vector.lt(operand1.asLong(), operand2.asLong()));
TYP_LONG2:
resultValue := factory.createLong2(Vector.lt(operand1.asLong2(), operand2.asLong2()));
TYP_LONG4:
resultValue := factory.createLong4(Vector.lt(operand1.asLong4(), operand2.asLong4()));
TYP_LONG8:
resultValue := factory.createLong8(Vector.lt(operand1.asLong8(), operand2.asLong8()));
else
goto break_label0;
end;
end;
O_VECT_LE: begin
case kind of
TYP_DOUBLE:
resultValue := factory.createLong(Vector.le(operand1.asDouble(), operand2.asDouble()));
TYP_DOUBLE2:
resultValue := factory.createLong2(Vector.le(operand1.asDouble2(), operand2.asDouble2()));
TYP_DOUBLE4:
resultValue := factory.createLong4(Vector.le(operand1.asDouble4(), operand2.asDouble4()));
TYP_DOUBLE8:
resultValue := factory.createLong8(Vector.le(operand1.asDouble8(), operand2.asDouble8()));
TYP_FLOAT:
resultValue := factory.createInt(Vector.le(operand1.asFloat(), operand2.asFloat()));
TYP_FLOAT2:
resultValue := factory.createInt2(Vector.le(operand1.asFloat2(), operand2.asFloat2()));
TYP_FLOAT4:
resultValue := factory.createInt4(Vector.le(operand1.asFloat4(), operand2.asFloat4()));
TYP_FLOAT8:
resultValue := factory.createInt8(Vector.le(operand1.asFloat8(), operand2.asFloat8()));
TYP_BYTE:
resultValue := factory.createByte(Vector.le(operand1.asByte(), operand2.asByte()));
TYP_BYTE2:
resultValue := factory.createByte2(Vector.le(operand1.asByte2(), operand2.asByte2()));
TYP_BYTE4:
resultValue := factory.createByte4(Vector.le(operand1.asByte4(), operand2.asByte4()));
TYP_BYTE8:
resultValue := factory.createByte8(Vector.le(operand1.asByte8(), operand2.asByte8()));
TYP_SHORT:
resultValue := factory.createShort(Vector.le(operand1.asShort(), operand2.asShort()));
TYP_SHORT2:
resultValue := factory.createShort2(Vector.le(operand1.asShort2(), operand2.asShort2()));
TYP_SHORT4:
resultValue := factory.createShort4(Vector.le(operand1.asShort4(), operand2.asShort4()));
TYP_SHORT8:
resultValue := factory.createShort8(Vector.le(operand1.asShort8(), operand2.asShort8()));
TYP_INT:
resultValue := factory.createInt(Vector.le(operand1.asInt(), operand2.asInt()));
TYP_INT2:
resultValue := factory.createInt2(Vector.le(operand1.asInt2(), operand2.asInt2()));
TYP_INT4:
resultValue := factory.createInt4(Vector.le(operand1.asInt4(), operand2.asInt4()));
TYP_INT8:
resultValue := factory.createInt8(Vector.le(operand1.asInt8(), operand2.asInt8()));
TYP_LONG:
resultValue := factory.createLong(Vector.le(operand1.asLong(), operand2.asLong()));
TYP_LONG2:
resultValue := factory.createLong2(Vector.le(operand1.asLong2(), operand2.asLong2()));
TYP_LONG4:
resultValue := factory.createLong4(Vector.le(operand1.asLong4(), operand2.asLong4()));
TYP_LONG8:
resultValue := factory.createLong8(Vector.le(operand1.asLong8(), operand2.asLong8()));
else
goto break_label0;
end;
end;
else
resultValue := nil;
end;
child1.setData(child1.position, resultValue.&type, LOAD_CONST, resultValue);
__code.removeNode(child2);
goto continue_label0;
end;
case operation of
O_SCAL_GT,
O_SCAL_GE,
O_SCAL_LT,
O_SCAL_LE: begin
if (kind = TYP_REAL) or (kind = TYP_DOUBLE) or (kind = TYP_FLOAT) or (kind = TYP_INT) or (kind = TYP_LONG) then begin
resultType := fldTypeBoolean;
goto break_label2;
end;
goto break_label0;
end;
O_VECT_GT,
O_VECT_GE,
O_VECT_LT,
O_VECT_LE: begin
if (kind >= TYP_DOUBLE) and (kind <= TYP_DOUBLE8) then begin
resultType := getPrimitiveType(kind + (TYP_LONG - TYP_DOUBLE));
goto break_label2;
end;
if (kind >= TYP_FLOAT) and (kind <= TYP_FLOAT8) then begin
resultType := getPrimitiveType(kind + (TYP_INT - TYP_FLOAT));
goto break_label2;
end;
if (kind >= TYP_BYTE) and (kind <= TYP_LONG8) then begin
resultType := commonType;
goto break_label2;
end;
goto break_label0;
end;
else
resultType := nil;
end;
break_label2:
child1 := cast(child1, commonType);
child2 := cast(child2, commonType);
resultNode := __code.createAndAppendNode(parent).setData(before, resultType, operation, commonType);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
goto continue_label0;
end;
break_label1:
dereference := ru.malik.elaborarer.avtoo.lang.ClassType(argument2Type);
arguments := [ argument1Type ];
inc(operation, R_DELTA);
foundOperators := dereference.findOperators(operation, arguments, enclosing);
foundLength := system.length(foundOperators);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereference), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(operation))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundOperator := foundOperators[0];
if not foundOperator.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator'), [
CoObject.create(foundOperator), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundOperator.isVisibleFrom(enclosing, dereference) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosing.specialSimpleName), CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereference.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(operation) + foundOperator.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
child1 := cast(child1, foundOperator.arguments.readComponent(0).&type);
resultNode := __code.createAndAppendNode(parent).setData(before, foundOperator.&type, invokeInstructionFor(foundOperator, dereference), foundOperator);
__code.createAndAppendNode(resultNode).setData(before, nil, SWAP, argument1Type);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
goto continue_label0;
end;
break_label0:
begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.2'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type), CoObject.create(argument2Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
continue_label0:
operation := source.getLexemeKind(position);
until
(operation <> O_SCAL_GT) and (operation <> O_SCAL_GE) and (operation <> O_SCAL_LT) and (operation <> O_SCAL_LE) and
(operation <> O_VECT_GT) and (operation <> O_VECT_GE) and (operation <> O_VECT_LT) and (operation <> O_VECT_LE) and
(operation <> EXP_INSTANCEOF)
;
end;
result := position;
end;
function ImmediateBuilder.parseEquality(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
label
break_label0,
break_label1,
break_label2,
continue_label0;
var
kind: int;
before: int;
operation: int;
foundLength: int;
arguments: Type_Array1d;
foundOperators: Operator_Array1d;
child1: Node;
child2: Node;
__code: Code;
resultNode: Node;
resultType: &Type;
commonType: &Type;
operand1: Constant;
operand2: Constant;
argument1Type: &Type;
argument2Type: &Type;
resultValue: Constant;
factory: ConstantFactory;
foundOperator: &Operator;
operand1AsObject: TObject;
operand2AsObject: TObject;
enclosing: ru.malik.elaborarer.avtoo.lang.ClassType;
dereference: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
position := parseRelational(parent, source, position, isStaticOnly);
operation := source.getLexemeKind(position);
if (operation = O_SCAL_EQ) or (operation = O_SCAL_NE) or (operation = O_VECT_EQ) or (operation = O_VECT_NE) then begin
__code := parent.parentCode;
enclosing := __code.parentCallable.parentType;
factory := fldConstantFactory;
child1 := parent.readComponent(-1);
repeat
before := position;
position := parseRelational(parent, source, position + 1, isStaticOnly);
child2 := parent.readComponent(-1);
argument1Type := child1.&type;
argument2Type := child2.&type;
begin
if ((operation = O_SCAL_EQ) or (operation = O_SCAL_NE)) and (argument1Type is ReferenceType) then begin
if not argument1Type.isCompatibleWith(argument2Type) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'incompatible-types'), [
CoObject.create(argument1Type), CoObject.create(argument2Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if (child1.instruction = LOAD_CONST) and (child2.instruction = LOAD_CONST) then begin
operand1AsObject := child1.operandC.asObject();
operand2AsObject := child2.operandC.asObject();
if operation = O_SCAL_EQ then begin
resultValue := factory.createBoolean(operand1AsObject.equals(operand2AsObject));
end else begin
resultValue := factory.createBoolean(not operand1AsObject.equals(operand2AsObject));
end;
child1.setData(child1.position, resultValue.&type, LOAD_CONST, resultValue);
__code.removeNode(child2);
goto continue_label0;
end;
resultNode := __code.createAndAppendNode(parent).setData(before, fldTypeBoolean, operation + (REF_EQ - O_SCAL_EQ));
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
goto continue_label0;
end;
begin
if (operation = O_VECT_EQ) or (operation = O_VECT_NE) then begin
if argument1Type is ru.malik.elaborarer.avtoo.lang.ClassType then begin
dereference := ru.malik.elaborarer.avtoo.lang.ClassType(argument1Type);
arguments := [ argument2Type ];
foundOperators := dereference.findOperators(operation, arguments, enclosing);
foundLength := system.length(foundOperators);
if foundLength < 1 then begin
if argument2Type is ru.malik.elaborarer.avtoo.lang.ClassType then goto break_label1;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereference), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(operation))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundOperator := foundOperators[0];
if not foundOperator.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator'), [
CoObject.create(foundOperator), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundOperator.isVisibleFrom(enclosing, dereference) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosing.specialSimpleName), CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereference.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(operation) + foundOperator.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
child2 := cast(child2, foundOperator.arguments.readComponent(0).&type);
resultNode := __code.createAndAppendNode(parent).setData(before, foundOperator.&type, invokeInstructionFor(foundOperator, dereference), foundOperator);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
goto continue_label0;
end;
if argument2Type is ru.malik.elaborarer.avtoo.lang.ClassType then goto break_label1;
end;
if not(argument1Type is PrimitiveType) then goto break_label0;
if operation >= O_VECT_OPERATOR then begin
commonType := argument1Type.getVectorCommonType(argument2Type);
end else begin
commonType := argument1Type.getScalarCommonType(argument2Type);
end;
if commonType = nil then goto break_label0;
kind := commonType.kind;
if (child1.instruction = LOAD_CONST) and (child2.instruction = LOAD_CONST) then begin
operand1 := child1.operandC;
operand2 := child2.operandC;
case operation of
O_SCAL_EQ: begin
case kind of
TYP_BOOLEAN:
resultValue := factory.createBoolean(operand1.asBoolean() = operand2.asBoolean());
TYP_REAL:
resultValue := factory.createBoolean(operand1.asReal() = operand2.asReal());
TYP_DOUBLE:
resultValue := factory.createBoolean(operand1.asDouble() = operand2.asDouble());
TYP_DOUBLE2:
resultValue := factory.createBoolean(operand1.asDouble2() = operand2.asDouble2());
TYP_DOUBLE4:
resultValue := factory.createBoolean(operand1.asDouble4() = operand2.asDouble4());
TYP_DOUBLE8:
resultValue := factory.createBoolean(operand1.asDouble8() = operand2.asDouble8());
TYP_FLOAT:
resultValue := factory.createBoolean(operand1.asFloat() = operand2.asFloat());
TYP_FLOAT2:
resultValue := factory.createBoolean(operand1.asFloat2() = operand2.asFloat2());
TYP_FLOAT4:
resultValue := factory.createBoolean(operand1.asFloat4() = operand2.asFloat4());
TYP_FLOAT8:
resultValue := factory.createBoolean(operand1.asFloat8() = operand2.asFloat8());
TYP_INT:
resultValue := factory.createBoolean(operand1.asInt() = operand2.asInt());
TYP_INT2:
resultValue := factory.createBoolean(operand1.asInt2() = operand2.asInt2());
TYP_INT4:
resultValue := factory.createBoolean(operand1.asInt4() = operand2.asInt4());
TYP_INT8:
resultValue := factory.createBoolean(operand1.asInt8() = operand2.asInt8());
TYP_LONG:
resultValue := factory.createBoolean(operand1.asLong() = operand2.asLong());
TYP_LONG2:
resultValue := factory.createBoolean(operand1.asLong2() = operand2.asLong2());
TYP_LONG4:
resultValue := factory.createBoolean(operand1.asLong4() = operand2.asLong4());
TYP_LONG8:
resultValue := factory.createBoolean(operand1.asLong8() = operand2.asLong8());
else
goto break_label0;
end;
end;
O_SCAL_NE: begin
case kind of
TYP_BOOLEAN:
resultValue := factory.createBoolean(operand1.asBoolean() <> operand2.asBoolean());
TYP_REAL:
resultValue := factory.createBoolean(operand1.asReal() <> operand2.asReal());
TYP_DOUBLE:
resultValue := factory.createBoolean(operand1.asDouble() <> operand2.asDouble());
TYP_DOUBLE2:
resultValue := factory.createBoolean(operand1.asDouble2() <> operand2.asDouble2());
TYP_DOUBLE4:
resultValue := factory.createBoolean(operand1.asDouble4() <> operand2.asDouble4());
TYP_DOUBLE8:
resultValue := factory.createBoolean(operand1.asDouble8() <> operand2.asDouble8());
TYP_FLOAT:
resultValue := factory.createBoolean(operand1.asFloat() <> operand2.asFloat());
TYP_FLOAT2:
resultValue := factory.createBoolean(operand1.asFloat2() <> operand2.asFloat2());
TYP_FLOAT4:
resultValue := factory.createBoolean(operand1.asFloat4() <> operand2.asFloat4());
TYP_FLOAT8:
resultValue := factory.createBoolean(operand1.asFloat8() <> operand2.asFloat8());
TYP_INT:
resultValue := factory.createBoolean(operand1.asInt() <> operand2.asInt());
TYP_INT2:
resultValue := factory.createBoolean(operand1.asInt2() <> operand2.asInt2());
TYP_INT4:
resultValue := factory.createBoolean(operand1.asInt4() <> operand2.asInt4());
TYP_INT8:
resultValue := factory.createBoolean(operand1.asInt8() <> operand2.asInt8());
TYP_LONG:
resultValue := factory.createBoolean(operand1.asLong() <> operand2.asLong());
TYP_LONG2:
resultValue := factory.createBoolean(operand1.asLong2() <> operand2.asLong2());
TYP_LONG4:
resultValue := factory.createBoolean(operand1.asLong4() <> operand2.asLong4());
TYP_LONG8:
resultValue := factory.createBoolean(operand1.asLong8() <> operand2.asLong8());
else
goto break_label0;
end;
end;
O_VECT_EQ: begin
case kind of
TYP_DOUBLE:
resultValue := factory.createLong(Vector.eq(operand1.asDouble(), operand2.asDouble()));
TYP_DOUBLE2:
resultValue := factory.createLong2(Vector.eq(operand1.asDouble2(), operand2.asDouble2()));
TYP_DOUBLE4:
resultValue := factory.createLong4(Vector.eq(operand1.asDouble4(), operand2.asDouble4()));
TYP_DOUBLE8:
resultValue := factory.createLong8(Vector.eq(operand1.asDouble8(), operand2.asDouble8()));
TYP_FLOAT:
resultValue := factory.createInt(Vector.eq(operand1.asFloat(), operand2.asFloat()));
TYP_FLOAT2:
resultValue := factory.createInt2(Vector.eq(operand1.asFloat2(), operand2.asFloat2()));
TYP_FLOAT4:
resultValue := factory.createInt4(Vector.eq(operand1.asFloat4(), operand2.asFloat4()));
TYP_FLOAT8:
resultValue := factory.createInt8(Vector.eq(operand1.asFloat8(), operand2.asFloat8()));
TYP_BYTE:
resultValue := factory.createByte(Vector.eq(operand1.asByte(), operand2.asByte()));
TYP_BYTE2:
resultValue := factory.createByte2(Vector.eq(operand1.asByte2(), operand2.asByte2()));
TYP_BYTE4:
resultValue := factory.createByte4(Vector.eq(operand1.asByte4(), operand2.asByte4()));
TYP_BYTE8:
resultValue := factory.createByte8(Vector.eq(operand1.asByte8(), operand2.asByte8()));
TYP_SHORT:
resultValue := factory.createShort(Vector.eq(operand1.asShort(), operand2.asShort()));
TYP_SHORT2:
resultValue := factory.createShort2(Vector.eq(operand1.asShort2(), operand2.asShort2()));
TYP_SHORT4:
resultValue := factory.createShort4(Vector.eq(operand1.asShort4(), operand2.asShort4()));
TYP_SHORT8:
resultValue := factory.createShort8(Vector.eq(operand1.asShort8(), operand2.asShort8()));
TYP_INT:
resultValue := factory.createInt(Vector.eq(operand1.asInt(), operand2.asInt()));
TYP_INT2:
resultValue := factory.createInt2(Vector.eq(operand1.asInt2(), operand2.asInt2()));
TYP_INT4:
resultValue := factory.createInt4(Vector.eq(operand1.asInt4(), operand2.asInt4()));
TYP_INT8:
resultValue := factory.createInt8(Vector.eq(operand1.asInt8(), operand2.asInt8()));
TYP_LONG:
resultValue := factory.createLong(Vector.eq(operand1.asLong(), operand2.asLong()));
TYP_LONG2:
resultValue := factory.createLong2(Vector.eq(operand1.asLong2(), operand2.asLong2()));
TYP_LONG4:
resultValue := factory.createLong4(Vector.eq(operand1.asLong4(), operand2.asLong4()));
TYP_LONG8:
resultValue := factory.createLong8(Vector.eq(operand1.asLong8(), operand2.asLong8()));
else
goto break_label0;
end;
end;
O_VECT_NE: begin
case kind of
TYP_DOUBLE:
resultValue := factory.createLong(Vector.ne(operand1.asDouble(), operand2.asDouble()));
TYP_DOUBLE2:
resultValue := factory.createLong2(Vector.ne(operand1.asDouble2(), operand2.asDouble2()));
TYP_DOUBLE4:
resultValue := factory.createLong4(Vector.ne(operand1.asDouble4(), operand2.asDouble4()));
TYP_DOUBLE8:
resultValue := factory.createLong8(Vector.ne(operand1.asDouble8(), operand2.asDouble8()));
TYP_FLOAT:
resultValue := factory.createInt(Vector.ne(operand1.asFloat(), operand2.asFloat()));
TYP_FLOAT2:
resultValue := factory.createInt2(Vector.ne(operand1.asFloat2(), operand2.asFloat2()));
TYP_FLOAT4:
resultValue := factory.createInt4(Vector.ne(operand1.asFloat4(), operand2.asFloat4()));
TYP_FLOAT8:
resultValue := factory.createInt8(Vector.ne(operand1.asFloat8(), operand2.asFloat8()));
TYP_BYTE:
resultValue := factory.createByte(Vector.ne(operand1.asByte(), operand2.asByte()));
TYP_BYTE2:
resultValue := factory.createByte2(Vector.ne(operand1.asByte2(), operand2.asByte2()));
TYP_BYTE4:
resultValue := factory.createByte4(Vector.ne(operand1.asByte4(), operand2.asByte4()));
TYP_BYTE8:
resultValue := factory.createByte8(Vector.ne(operand1.asByte8(), operand2.asByte8()));
TYP_SHORT:
resultValue := factory.createShort(Vector.ne(operand1.asShort(), operand2.asShort()));
TYP_SHORT2:
resultValue := factory.createShort2(Vector.ne(operand1.asShort2(), operand2.asShort2()));
TYP_SHORT4:
resultValue := factory.createShort4(Vector.ne(operand1.asShort4(), operand2.asShort4()));
TYP_SHORT8:
resultValue := factory.createShort8(Vector.ne(operand1.asShort8(), operand2.asShort8()));
TYP_INT:
resultValue := factory.createInt(Vector.ne(operand1.asInt(), operand2.asInt()));
TYP_INT2:
resultValue := factory.createInt2(Vector.ne(operand1.asInt2(), operand2.asInt2()));
TYP_INT4:
resultValue := factory.createInt4(Vector.ne(operand1.asInt4(), operand2.asInt4()));
TYP_INT8:
resultValue := factory.createInt8(Vector.ne(operand1.asInt8(), operand2.asInt8()));
TYP_LONG:
resultValue := factory.createLong(Vector.ne(operand1.asLong(), operand2.asLong()));
TYP_LONG2:
resultValue := factory.createLong2(Vector.ne(operand1.asLong2(), operand2.asLong2()));
TYP_LONG4:
resultValue := factory.createLong4(Vector.ne(operand1.asLong4(), operand2.asLong4()));
TYP_LONG8:
resultValue := factory.createLong8(Vector.ne(operand1.asLong8(), operand2.asLong8()));
else
goto break_label0;
end;
end;
else
resultValue := nil;
end;
child1.setData(child1.position, resultValue.&type, LOAD_CONST, resultValue);
__code.removeNode(child2);
goto continue_label0;
end;
case operation of
O_SCAL_EQ,
O_SCAL_NE: begin
if (kind = TYP_BOOLEAN) or (kind >= TYP_REAL) and (kind <= TYP_FLOAT8) or (kind >= TYP_INT) and (kind <= TYP_LONG8) then begin
resultType := fldTypeBoolean;
goto break_label2;
end;
goto break_label0;
end;
O_VECT_EQ,
O_VECT_NE: begin
if (kind >= TYP_DOUBLE) and (kind <= TYP_DOUBLE8) then begin
resultType := getPrimitiveType(kind + (TYP_LONG - TYP_DOUBLE));
goto break_label2;
end;
if (kind >= TYP_FLOAT) and (kind <= TYP_FLOAT8) then begin
resultType := getPrimitiveType(kind + (TYP_INT - TYP_FLOAT));
goto break_label2;
end;
if (kind >= TYP_BYTE) and (kind <= TYP_LONG8) then begin
resultType := commonType;
goto break_label2;
end;
goto break_label0;
end;
else
resultType := nil;
end;
break_label2:
child1 := cast(child1, commonType);
child2 := cast(child2, commonType);
resultNode := __code.createAndAppendNode(parent).setData(before, resultType, operation, commonType);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
goto continue_label0;
end;
break_label1:
dereference := ru.malik.elaborarer.avtoo.lang.ClassType(argument2Type);
arguments := [ argument1Type ];
inc(operation, R_DELTA);
foundOperators := dereference.findOperators(operation, arguments, enclosing);
foundLength := system.length(foundOperators);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereference), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(operation))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundOperator := foundOperators[0];
if not foundOperator.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator'), [
CoObject.create(foundOperator), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundOperator.isVisibleFrom(enclosing, dereference) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosing.specialSimpleName), CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereference.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(operation) + foundOperator.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
child1 := cast(child1, foundOperator.arguments.readComponent(0).&type);
resultNode := __code.createAndAppendNode(parent).setData(before, foundOperator.&type, invokeInstructionFor(foundOperator, dereference), foundOperator);
__code.createAndAppendNode(resultNode).setData(before, nil, SWAP, argument1Type);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
goto continue_label0;
end;
break_label0:
begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.2'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type), CoObject.create(argument2Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
continue_label0:
operation := source.getLexemeKind(position);
until (operation <> O_SCAL_EQ) and (operation <> O_SCAL_NE) and (operation <> O_VECT_EQ) and (operation <> O_VECT_NE);
end;
result := position;
end;
function ImmediateBuilder.parseBitAnd(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
label
break_label0,
break_label1;
var
kind: int;
before: int;
foundLength: int;
arguments: Type_Array1d;
foundOperators: Operator_Array1d;
child1: Node;
child2: Node;
__code: Code;
resultNode: Node;
resultType: &Type;
commonType: &Type;
operand1: Constant;
operand2: Constant;
argument1Type: &Type;
argument2Type: &Type;
resultValue: Constant;
factory: ConstantFactory;
foundOperator: &Operator;
enclosing: ru.malik.elaborarer.avtoo.lang.ClassType;
dereference: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
position := parseEquality(parent, source, position, isStaticOnly);
if source.getLexemeKind(position) = O_BIT_AND then begin
__code := parent.parentCode;
enclosing := __code.parentCallable.parentType;
factory := fldConstantFactory;
child1 := parent.readComponent(-1);
repeat
before := position;
position := parseEquality(parent, source, position + 1, isStaticOnly);
child2 := parent.readComponent(-1);
argument1Type := child1.&type;
argument2Type := child2.&type;
begin
begin
if argument1Type is ru.malik.elaborarer.avtoo.lang.ClassType then begin
dereference := ru.malik.elaborarer.avtoo.lang.ClassType(argument1Type);
arguments := [ argument2Type ];
foundOperators := dereference.findOperators(O_BIT_AND, arguments, enclosing);
foundLength := system.length(foundOperators);
if foundLength < 1 then begin
if argument2Type is ru.malik.elaborarer.avtoo.lang.ClassType then goto break_label1;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereference), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(O_BIT_AND))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundOperator := foundOperators[0];
if not foundOperator.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator'), [
CoObject.create(foundOperator), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundOperator.isVisibleFrom(enclosing, dereference) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosing.specialSimpleName), CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereference.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(O_BIT_AND) + foundOperator.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
child2 := cast(child2, foundOperator.arguments.readComponent(0).&type);
resultNode := __code.createAndAppendNode(parent).setData(before, foundOperator.&type, invokeInstructionFor(foundOperator, dereference), foundOperator);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
continue;
end;
if argument2Type is ru.malik.elaborarer.avtoo.lang.ClassType then goto break_label1;
if not(argument1Type is PrimitiveType) then goto break_label0;
commonType := argument1Type.getVectorCommonType(argument2Type);
if commonType = nil then goto break_label0;
kind := commonType.kind;
if (child1.instruction = LOAD_CONST) and (child2.instruction = LOAD_CONST) then begin
operand1 := child1.operandC;
operand2 := child2.operandC;
case kind of
TYP_BOOLEAN:
resultValue := factory.createBoolean(operand1.asBoolean() and operand2.asBoolean());
TYP_BYTE:
resultValue := factory.createByte(operand1.asByte() and operand2.asByte());
TYP_BYTE2:
resultValue := factory.createByte2(operand1.asByte2() and operand2.asByte2());
TYP_BYTE4:
resultValue := factory.createByte4(operand1.asByte4() and operand2.asByte4());
TYP_BYTE8:
resultValue := factory.createByte8(operand1.asByte8() and operand2.asByte8());
TYP_SHORT:
resultValue := factory.createShort(operand1.asShort() and operand2.asShort());
TYP_SHORT2:
resultValue := factory.createShort2(operand1.asShort2() and operand2.asShort2());
TYP_SHORT4:
resultValue := factory.createShort4(operand1.asShort4() and operand2.asShort4());
TYP_SHORT8:
resultValue := factory.createShort8(operand1.asShort8() and operand2.asShort8());
TYP_INT:
resultValue := factory.createInt(operand1.asInt() and operand2.asInt());
TYP_INT2:
resultValue := factory.createInt2(operand1.asInt2() and operand2.asInt2());
TYP_INT4:
resultValue := factory.createInt4(operand1.asInt4() and operand2.asInt4());
TYP_INT8:
resultValue := factory.createInt8(operand1.asInt8() and operand2.asInt8());
TYP_LONG:
resultValue := factory.createLong(operand1.asLong() and operand2.asLong());
TYP_LONG2:
resultValue := factory.createLong2(operand1.asLong2() and operand2.asLong2());
TYP_LONG4:
resultValue := factory.createLong4(operand1.asLong4() and operand2.asLong4());
TYP_LONG8:
resultValue := factory.createLong8(operand1.asLong8() and operand2.asLong8());
else
goto break_label0;
end;
child1.setData(child1.position, resultValue.&type, LOAD_CONST, resultValue);
__code.removeNode(child2);
continue;
end;
if (kind = TYP_BOOLEAN) or (kind >= TYP_BYTE) and (kind <= TYP_LONG8) then begin
resultType := commonType;
child1 := cast(child1, commonType);
child2 := cast(child2, commonType);
resultNode := __code.createAndAppendNode(parent).setData(before, resultType, O_BIT_AND, commonType);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
continue;
end;
goto break_label0;
end;
break_label1:
dereference := ru.malik.elaborarer.avtoo.lang.ClassType(argument2Type);
arguments := [ argument1Type ];
foundOperators := dereference.findOperators(R_BIT_AND, arguments, enclosing);
foundLength := system.length(foundOperators);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereference), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(R_BIT_AND))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundOperator := foundOperators[0];
if not foundOperator.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator'), [
CoObject.create(foundOperator), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundOperator.isVisibleFrom(enclosing, dereference) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosing.specialSimpleName), CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereference.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(R_BIT_AND) + foundOperator.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
child1 := cast(child1, foundOperator.arguments.readComponent(0).&type);
resultNode := __code.createAndAppendNode(parent).setData(before, foundOperator.&type, invokeInstructionFor(foundOperator, dereference), foundOperator);
__code.createAndAppendNode(resultNode).setData(before, nil, SWAP, argument1Type);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
continue;
end;
break_label0:
begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.2'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type), CoObject.create(argument2Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
until source.getLexemeKind(position) <> O_BIT_AND;
end;
result := position;
end;
function ImmediateBuilder.parseBitXor(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
label
break_label0,
break_label1;
var
kind: int;
before: int;
foundLength: int;
arguments: Type_Array1d;
foundOperators: Operator_Array1d;
child1: Node;
child2: Node;
__code: Code;
resultNode: Node;
resultType: &Type;
commonType: &Type;
operand1: Constant;
operand2: Constant;
argument1Type: &Type;
argument2Type: &Type;
resultValue: Constant;
factory: ConstantFactory;
foundOperator: &Operator;
enclosing: ru.malik.elaborarer.avtoo.lang.ClassType;
dereference: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
position := parseBitAnd(parent, source, position, isStaticOnly);
if source.getLexemeKind(position) = O_BIT_XOR then begin
__code := parent.parentCode;
enclosing := __code.parentCallable.parentType;
factory := fldConstantFactory;
child1 := parent.readComponent(-1);
repeat
before := position;
position := parseBitAnd(parent, source, position + 1, isStaticOnly);
child2 := parent.readComponent(-1);
argument1Type := child1.&type;
argument2Type := child2.&type;
begin
begin
if argument1Type is ru.malik.elaborarer.avtoo.lang.ClassType then begin
dereference := ru.malik.elaborarer.avtoo.lang.ClassType(argument1Type);
arguments := [ argument2Type ];
foundOperators := dereference.findOperators(O_BIT_XOR, arguments, enclosing);
foundLength := system.length(foundOperators);
if foundLength < 1 then begin
if argument2Type is ru.malik.elaborarer.avtoo.lang.ClassType then goto break_label1;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereference), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(O_BIT_XOR))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundOperator := foundOperators[0];
if not foundOperator.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator'), [
CoObject.create(foundOperator), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundOperator.isVisibleFrom(enclosing, dereference) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosing.specialSimpleName), CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereference.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(O_BIT_XOR) + foundOperator.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
child2 := cast(child2, foundOperator.arguments.readComponent(0).&type);
resultNode := __code.createAndAppendNode(parent).setData(before, foundOperator.&type, invokeInstructionFor(foundOperator, dereference), foundOperator);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
continue;
end;
if argument2Type is ru.malik.elaborarer.avtoo.lang.ClassType then goto break_label1;
if not(argument1Type is PrimitiveType) then goto break_label0;
commonType := argument1Type.getVectorCommonType(argument2Type);
if commonType = nil then goto break_label0;
kind := commonType.kind;
if (child1.instruction = LOAD_CONST) and (child2.instruction = LOAD_CONST) then begin
operand1 := child1.operandC;
operand2 := child2.operandC;
case kind of
TYP_BOOLEAN:
resultValue := factory.createBoolean(operand1.asBoolean() xor operand2.asBoolean());
TYP_BYTE:
resultValue := factory.createByte(operand1.asByte() xor operand2.asByte());
TYP_BYTE2:
resultValue := factory.createByte2(operand1.asByte2() xor operand2.asByte2());
TYP_BYTE4:
resultValue := factory.createByte4(operand1.asByte4() xor operand2.asByte4());
TYP_BYTE8:
resultValue := factory.createByte8(operand1.asByte8() xor operand2.asByte8());
TYP_SHORT:
resultValue := factory.createShort(operand1.asShort() xor operand2.asShort());
TYP_SHORT2:
resultValue := factory.createShort2(operand1.asShort2() xor operand2.asShort2());
TYP_SHORT4:
resultValue := factory.createShort4(operand1.asShort4() xor operand2.asShort4());
TYP_SHORT8:
resultValue := factory.createShort8(operand1.asShort8() xor operand2.asShort8());
TYP_INT:
resultValue := factory.createInt(operand1.asInt() xor operand2.asInt());
TYP_INT2:
resultValue := factory.createInt2(operand1.asInt2() xor operand2.asInt2());
TYP_INT4:
resultValue := factory.createInt4(operand1.asInt4() xor operand2.asInt4());
TYP_INT8:
resultValue := factory.createInt8(operand1.asInt8() xor operand2.asInt8());
TYP_LONG:
resultValue := factory.createLong(operand1.asLong() xor operand2.asLong());
TYP_LONG2:
resultValue := factory.createLong2(operand1.asLong2() xor operand2.asLong2());
TYP_LONG4:
resultValue := factory.createLong4(operand1.asLong4() xor operand2.asLong4());
TYP_LONG8:
resultValue := factory.createLong8(operand1.asLong8() xor operand2.asLong8());
else
goto break_label0;
end;
child1.setData(child1.position, resultValue.&type, LOAD_CONST, resultValue);
__code.removeNode(child2);
continue;
end;
if (kind = TYP_BOOLEAN) or (kind >= TYP_BYTE) and (kind <= TYP_LONG8) then begin
resultType := commonType;
child1 := cast(child1, commonType);
child2 := cast(child2, commonType);
resultNode := __code.createAndAppendNode(parent).setData(before, resultType, O_BIT_XOR, commonType);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
continue;
end;
goto break_label0;
end;
break_label1:
dereference := ru.malik.elaborarer.avtoo.lang.ClassType(argument2Type);
arguments := [ argument1Type ];
foundOperators := dereference.findOperators(R_BIT_XOR, arguments, enclosing);
foundLength := system.length(foundOperators);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereference), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(R_BIT_XOR))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundOperator := foundOperators[0];
if not foundOperator.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator'), [
CoObject.create(foundOperator), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundOperator.isVisibleFrom(enclosing, dereference) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosing.specialSimpleName), CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereference.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(R_BIT_XOR) + foundOperator.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
child1 := cast(child1, foundOperator.arguments.readComponent(0).&type);
resultNode := __code.createAndAppendNode(parent).setData(before, foundOperator.&type, invokeInstructionFor(foundOperator, dereference), foundOperator);
__code.createAndAppendNode(resultNode).setData(before, nil, SWAP, argument1Type);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
continue;
end;
break_label0:
begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.2'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type), CoObject.create(argument2Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
until source.getLexemeKind(position) <> O_BIT_XOR;
end;
result := position;
end;
function ImmediateBuilder.parseBitOr(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
label
break_label0,
break_label1;
var
kind: int;
before: int;
foundLength: int;
arguments: Type_Array1d;
foundOperators: Operator_Array1d;
child1: Node;
child2: Node;
__code: Code;
resultNode: Node;
resultType: &Type;
commonType: &Type;
operand1: Constant;
operand2: Constant;
argument1Type: &Type;
argument2Type: &Type;
resultValue: Constant;
factory: ConstantFactory;
foundOperator: &Operator;
enclosing: ru.malik.elaborarer.avtoo.lang.ClassType;
dereference: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
position := parseBitXor(parent, source, position, isStaticOnly);
if source.getLexemeKind(position) = O_BIT_OR then begin
__code := parent.parentCode;
enclosing := __code.parentCallable.parentType;
factory := fldConstantFactory;
child1 := parent.readComponent(-1);
repeat
before := position;
position := parseBitXor(parent, source, position + 1, isStaticOnly);
child2 := parent.readComponent(-1);
argument1Type := child1.&type;
argument2Type := child2.&type;
begin
begin
if argument1Type is ru.malik.elaborarer.avtoo.lang.ClassType then begin
dereference := ru.malik.elaborarer.avtoo.lang.ClassType(argument1Type);
arguments := [ argument2Type ];
foundOperators := dereference.findOperators(O_BIT_OR, arguments, enclosing);
foundLength := system.length(foundOperators);
if foundLength < 1 then begin
if argument2Type is ru.malik.elaborarer.avtoo.lang.ClassType then goto break_label1;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereference), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(O_BIT_OR))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundOperator := foundOperators[0];
if not foundOperator.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator'), [
CoObject.create(foundOperator), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundOperator.isVisibleFrom(enclosing, dereference) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosing.specialSimpleName), CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereference.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(O_BIT_OR) + foundOperator.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
child2 := cast(child2, foundOperator.arguments.readComponent(0).&type);
resultNode := __code.createAndAppendNode(parent).setData(before, foundOperator.&type, invokeInstructionFor(foundOperator, dereference), foundOperator);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
continue;
end;
if argument2Type is ru.malik.elaborarer.avtoo.lang.ClassType then goto break_label1;
if not(argument1Type is PrimitiveType) then goto break_label0;
commonType := argument1Type.getVectorCommonType(argument2Type);
if commonType = nil then goto break_label0;
kind := commonType.kind;
if (child1.instruction = LOAD_CONST) and (child2.instruction = LOAD_CONST) then begin
operand1 := child1.operandC;
operand2 := child2.operandC;
case kind of
TYP_BOOLEAN:
resultValue := factory.createBoolean(operand1.asBoolean() or operand2.asBoolean());
TYP_BYTE:
resultValue := factory.createByte(operand1.asByte() or operand2.asByte());
TYP_BYTE2:
resultValue := factory.createByte2(operand1.asByte2() or operand2.asByte2());
TYP_BYTE4:
resultValue := factory.createByte4(operand1.asByte4() or operand2.asByte4());
TYP_BYTE8:
resultValue := factory.createByte8(operand1.asByte8() or operand2.asByte8());
TYP_SHORT:
resultValue := factory.createShort(operand1.asShort() or operand2.asShort());
TYP_SHORT2:
resultValue := factory.createShort2(operand1.asShort2() or operand2.asShort2());
TYP_SHORT4:
resultValue := factory.createShort4(operand1.asShort4() or operand2.asShort4());
TYP_SHORT8:
resultValue := factory.createShort8(operand1.asShort8() or operand2.asShort8());
TYP_INT:
resultValue := factory.createInt(operand1.asInt() or operand2.asInt());
TYP_INT2:
resultValue := factory.createInt2(operand1.asInt2() or operand2.asInt2());
TYP_INT4:
resultValue := factory.createInt4(operand1.asInt4() or operand2.asInt4());
TYP_INT8:
resultValue := factory.createInt8(operand1.asInt8() or operand2.asInt8());
TYP_LONG:
resultValue := factory.createLong(operand1.asLong() or operand2.asLong());
TYP_LONG2:
resultValue := factory.createLong2(operand1.asLong2() or operand2.asLong2());
TYP_LONG4:
resultValue := factory.createLong4(operand1.asLong4() or operand2.asLong4());
TYP_LONG8:
resultValue := factory.createLong8(operand1.asLong8() or operand2.asLong8());
else
goto break_label0;
end;
child1.setData(child1.position, resultValue.&type, LOAD_CONST, resultValue);
__code.removeNode(child2);
continue;
end;
if (kind = TYP_BOOLEAN) or (kind >= TYP_BYTE) and (kind <= TYP_LONG8) then begin
resultType := commonType;
child1 := cast(child1, commonType);
child2 := cast(child2, commonType);
resultNode := __code.createAndAppendNode(parent).setData(before, resultType, O_BIT_OR, commonType);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
continue;
end;
goto break_label0;
end;
break_label1:
dereference := ru.malik.elaborarer.avtoo.lang.ClassType(argument2Type);
arguments := [ argument1Type ];
foundOperators := dereference.findOperators(R_BIT_OR, arguments, enclosing);
foundLength := system.length(foundOperators);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereference), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(R_BIT_OR))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundOperator := foundOperators[0];
if not foundOperator.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator'), [
CoObject.create(foundOperator), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundOperator.isVisibleFrom(enclosing, dereference) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosing.specialSimpleName), CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereference.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(R_BIT_OR) + foundOperator.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
child1 := cast(child1, foundOperator.arguments.readComponent(0).&type);
resultNode := __code.createAndAppendNode(parent).setData(before, foundOperator.&type, invokeInstructionFor(foundOperator, dereference), foundOperator);
__code.createAndAppendNode(resultNode).setData(before, nil, SWAP, argument1Type);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
continue;
end;
break_label0:
begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.2'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type), CoObject.create(argument2Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
until source.getLexemeKind(position) <> O_BIT_OR;
end;
result := position;
end;
function ImmediateBuilder.parseBoolAnd(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
var
before: int;
child1: Node;
child2: Node;
__code: Code;
resultNode: Node;
argument1Type: &Type;
argument2Type: &Type;
resultValue: Constant;
factory: ConstantFactory;
exception: TextSourceException;
begin
position := parseBitOr(parent, source, position, isStaticOnly);
if source.getLexemeKind(position) = BOOL_AND then begin
__code := parent.parentCode;
factory := fldConstantFactory;
child1 := parent.readComponent(-1);
repeat
before := position;
position := parseBitOr(parent, source, position + 1, isStaticOnly);
child2 := parent.readComponent(-1);
argument1Type := child1.&type;
argument2Type := child2.&type;
if argument1Type.isBoolean() and argument2Type.isBoolean() then begin
if (child1.instruction = LOAD_CONST) and (child2.instruction = LOAD_CONST) then begin
resultValue := factory.createBoolean(child1.operandC.asBoolean() and child2.operandC.asBoolean());
child1.setData(child1.position, resultValue.&type, LOAD_CONST, resultValue);
__code.removeNode(child2);
continue;
end;
resultNode := __code.createAndAppendNode(parent).setData(before, argument1Type, BOOL_AND);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
continue;
end;
begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.2'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type), CoObject.create(argument2Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
until source.getLexemeKind(position) <> BOOL_AND;
end;
result := position;
end;
function ImmediateBuilder.parseBoolOr(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
var
before: int;
child1: Node;
child2: Node;
__code: Code;
resultNode: Node;
argument1Type: &Type;
argument2Type: &Type;
resultValue: Constant;
factory: ConstantFactory;
exception: TextSourceException;
begin
position := parseBoolAnd(parent, source, position, isStaticOnly);
if source.getLexemeKind(position) = BOOL_OR then begin
__code := parent.parentCode;
factory := fldConstantFactory;
child1 := parent.readComponent(-1);
repeat
before := position;
position := parseBoolAnd(parent, source, position + 1, isStaticOnly);
child2 := parent.readComponent(-1);
argument1Type := child1.&type;
argument2Type := child2.&type;
if argument1Type.isBoolean() and argument2Type.isBoolean() then begin
if (child1.instruction = LOAD_CONST) and (child2.instruction = LOAD_CONST) then begin
resultValue := factory.createBoolean(child1.operandC.asBoolean() or child2.operandC.asBoolean());
child1.setData(child1.position, resultValue.&type, LOAD_CONST, resultValue);
__code.removeNode(child2);
continue;
end;
resultNode := __code.createAndAppendNode(parent).setData(before, argument1Type, BOOL_OR);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
child1 := resultNode;
continue;
end;
begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.2'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(argument1Type), CoObject.create(argument2Type)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
until source.getLexemeKind(position) <> BOOL_OR;
end;
result := position;
end;
function ImmediateBuilder.parseConditional(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
var
__colon: int;
__question: int;
child1: Node;
child2: Node;
child3: Node;
__code: Code;
resultNode: Node;
commonType: &Type;
argument1Type: &Type;
argument2Type: &Type;
argument3Type: &Type;
exception: TextSourceException;
begin
position := parseBoolOr(parent, source, position, isStaticOnly);
if source.getLexemeKind(position) = QUESTION then begin
__question := position;
child1 := parent.readComponent(-1);
argument1Type := child1.&type;
if not argument1Type.isBoolean() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.expression.type'), [
CoObject.create(fldTypeBoolean), CoObject.create(argument1Type)
]
));
exception.source := source;
exception.position := __question;
raise exception;
end;
if child1.instruction = LOAD_CONST then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.const-expression-before-question'));
exception.source := source;
exception.position := __question;
raise exception;
end;
position := parseExpression(parent, source, position + 1, isStaticOnly);
__colon := position;
if source.getLexemeKind(position) <> COLON then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.colon'));
exception.source := source;
exception.position := position;
raise exception;
end;
position := parseExpression(parent, source, position + 1, isStaticOnly);
child2 := parent.readComponent(-2);
child3 := parent.readComponent(-1);
requiresValue(child2);
requiresValue(child3);
argument2Type := child2.&type;
argument3Type := child3.&type;
commonType := argument2Type.getVectorCommonType(argument3Type);
if commonType = nil then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-define.common-type'), [
CoObject.create(argument2Type), CoObject.create(argument3Type)
]
));
exception.source := source;
exception.position := __colon;
raise exception;
end;
child2 := cast(child2, commonType);
child3 := cast(child3, commonType);
__code := parent.parentCode;
resultNode := __code.createAndAppendNode(parent).setData(__question, commonType, BOOL_COND);
__code.moveNode(child1, resultNode, 0);
__code.moveNode(child2, resultNode, 1);
__code.moveNode(child3, resultNode, 2);
end;
result := position;
end;
function ImmediateBuilder.parseExpression(parent: Node; source: TextSource; position: int; isStaticOnly: boolean): int;
label
break_label0,
break_label1,
break_label2;
var
isChar: boolean;
isUseSuper: boolean;
kind: int;
before: int;
operation: int;
instruction: int;
foundLength: int;
arguments: Type_Array1d;
foundOperators: Operator_Array1d;
load: Node;
read: Node;
index: Node;
value: Node;
action: Node;
__code: Code;
typeInt: &Type;
leftNode: Node;
leftType: &Type;
mustType: &Type;
rightNode: Node;
rightType: &Type;
resultType: &Type;
foundLocal: Local;
foundField: Field;
foundItem: TableItem;
foundOperator: &Operator;
foundFieldoid: TypedMember;
foundReadOperator: &Operator;
foundWriteOperator: &Operator;
enclosingCallable: ru.malik.elaborarer.avtoo.lang.Callable;
enclosingClassType: ru.malik.elaborarer.avtoo.lang.ClassType;
dereferenceClassType: ru.malik.elaborarer.avtoo.lang.ClassType;
impliedParentClassType: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
position := parseConditional(parent, source, position, isStaticOnly);
operation := source.getLexemeKind(position);
case operation of
EQUAL: begin
leftNode := parent.readComponent(-1);
before := position;
instruction := leftNode.instruction;
case instruction of
LOAD_LOCAL:
begin
foundLocal := leftNode.operand1 as Local;
if foundLocal.isFinal() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.access.local-final.write'), [
CoObject.create(foundLocal)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
leftType := foundLocal.&type;
position := parseExpression(leftNode, source, position + 1, isStaticOnly);
rightNode := leftNode.readComponent(-1);
requiresValue(rightNode);
rightType := rightNode.&type;
if not leftType.isConvertableFrom(rightType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.type'), [
CoObject.create(rightType), CoObject.create(leftType)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
cast(rightNode, leftType);
leftNode.setData(before, nil, STORE_LOCAL, foundLocal);
goto break_label0;
end;
LOAD_STATIC:
begin
foundField := leftNode.operand1 as Field;
enclosingCallable := parent.parentCode.parentCallable;
enclosingClassType := enclosingCallable.parentType;
if foundField.isFinal() and (not(enclosingCallable is ClassInit) or (foundField.parentType <> enclosingClassType) or (foundField.value <> nil)) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.access.field-final.write'), [
CoObject.create(foundField)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
leftType := foundField.&type;
position := parseExpression(leftNode, source, position + 1, isStaticOnly);
rightNode := leftNode.readComponent(-1);
requiresValue(rightNode);
rightType := rightNode.&type;
if not leftType.isConvertableFrom(rightType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.type'), [
CoObject.create(rightType), CoObject.create(leftType)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
cast(rightNode, leftType);
leftNode.setData(before, nil, STORE_STATIC, foundField);
goto break_label0;
end;
WRITE_SPECIAL,
WRITE_PROPERTY,
READ_FIELD,
READ_SPECIAL,
READ_PROPERTY:
if (instruction <> WRITE_SPECIAL) and (instruction <> WRITE_PROPERTY) or (leftNode.getLength() = 1) then begin
foundFieldoid := leftNode.operand1 as TypedMember;
if Lang.isInstance(foundFieldoid, &Property) then begin
if not &Property(Lang.cast(foundFieldoid, &Property)).hasWrite() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.access.property-read-only.write'), [
CoSimple.create(foundFieldoid)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
end else begin
load := leftNode.readComponent(0);
enclosingCallable := parent.parentCode.parentCallable;
enclosingClassType := enclosingCallable.parentType;
if
foundFieldoid.isFinal() and (
not(enclosingCallable is InstInit) or (foundFieldoid.parentType <> enclosingClassType) or
(load.instruction <> LOAD_LOCAL) or (load.operand1 <> enclosingCallable.arguments.thisArgument)
)
then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.access.field-final.write'), [
CoSimple.create(foundFieldoid)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
end;
leftType := foundFieldoid.&type;
position := parseExpression(leftNode, source, position + 1, isStaticOnly);
rightNode := leftNode.readComponent(-1);
requiresValue(rightNode);
rightType := rightNode.&type;
if not leftType.isConvertableFrom(rightType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.type'), [
CoObject.create(rightType), CoObject.create(leftType)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
cast(rightNode, leftType);
if instruction < WRITE_OPERATOR then inc(instruction, A_DELTA);
leftNode.setData(before, nil, instruction, TableItem(Lang.cast(foundFieldoid, TableItem)));
goto break_label0;
end;
READ_COMPONENT:
begin
leftType := leftNode.operand1 as &Type;
position := parseExpression(leftNode, source, position + 1, isStaticOnly);
rightNode := leftNode.readComponent(-1);
requiresValue(rightNode);
rightType := rightNode.&type;
if not leftType.isConvertableFrom(rightType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.type'), [
CoObject.create(rightType), CoObject.create(leftType)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
cast(rightNode, leftType);
leftNode.setData(before, nil, WRITE_COMPONENT, leftType);
goto break_label0;
end;
INVOKE_VIRTUAL:
if leftNode.operand1 = nil then begin
position := parseExpression(leftNode, source, position + 1, isStaticOnly);
load := leftNode.readComponent(0);
index := leftNode.readComponent(1);
value := leftNode.readComponent(2);
requiresValue(value);
enclosingClassType := parent.parentCode.parentCallable.parentType;
dereferenceClassType := load.&type as ru.malik.elaborarer.avtoo.lang.ClassType;
isUseSuper := load.useSuper;
if isUseSuper then begin
impliedParentClassType := enclosingClassType;
end else begin
impliedParentClassType := dereferenceClassType;
end;
arguments := [ index.&type, value.&type ];
foundOperators := dereferenceClassType.findOperators(WRITE_COMPONENT, arguments, enclosingClassType);
foundLength := system.length(foundOperators);
if foundLength < 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.operator'), [
CoObject.create(dereferenceClassType), CoAnsiString.create(VIEWNAME_OPERATOR + &Operator.kindToSymbol(WRITE_COMPONENT))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundOperator := foundOperators[0];
if not foundOperator.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.operator'), [
CoObject.create(foundOperator), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundOperator.isVisibleFrom(enclosingClassType, impliedParentClassType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosingClassType.specialSimpleName), CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.operator'), [
CoAnsiString.create(dereferenceClassType.toString() + ('.' + VIEWNAME_OPERATOR) + &Operator.kindToSymbol(WRITE_COMPONENT) + foundOperator.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if isUseSuper and foundOperator.isAbstract() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.direct-access-abstract.operator'), [
CoObject.create(foundOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
with foundOperator.arguments do begin
cast(index, readComponent(0).&type);
cast(value, readComponent(1).&type);
end;
if isUseSuper then begin
instruction := INVOKE_SPECIAL;
end else begin
instruction := invokeInstructionFor(foundOperator, dereferenceClassType);
end;
leftNode.setData(before, nil, instruction, foundOperator);
goto break_label0;
end;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'applicable.operator.assignment'), [
CoUnicodeString.create(source.getLexemeString(before))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
A_BIT_AND,
A_BIT_OR,
A_BIT_XOR,
A_SCAL_MUL,
A_SCAL_DIV,
A_SCAL_DIVU,
A_SCAL_REM,
A_SCAL_REMU,
A_SCAL_ADD,
A_SCAL_SUB,
A_SCAL_SHL,
A_SCAL_SHR,
A_SCAL_SHRU,
A_VECT_MUL,
A_VECT_DIV,
A_VECT_ADD,
A_VECT_SUB,
A_VECT_SHL,
A_VECT_SHR,
A_VECT_SHRU,
A_VECT_GT,
A_VECT_GE,
A_VECT_LT,
A_VECT_LE,
A_VECT_EQ,
A_VECT_NE,
A_VECT_HMUL,
A_VECT_HMULU,
A_VECT_SADD,
A_VECT_SADDU,
A_VECT_SSUB,
A_VECT_SSUBU: begin
leftNode := parent.readComponent(-1);
__code := parent.parentCode;
before := position;
dec(operation, A_DELTA);
begin
instruction := leftNode.instruction;
case instruction of
LOAD_LOCAL: begin
foundLocal := leftNode.operand1 as Local;
if foundLocal.isFinal() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.access.local-final.write'), [
CoObject.create(foundLocal)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
leftType := foundLocal.&type;
action := __code.createAndAppendNode(leftNode);
position := parseExpression(action, source, position + 1, isStaticOnly);
rightNode := action.readComponent(-1);
requiresValue(rightNode);
__code.createAndPrependNode(action).setData(leftNode.position, leftType, LOAD_LOCAL, foundLocal);
leftNode.setData(before, nil, STORE_LOCAL, foundLocal);
goto break_label1;
end;
LOAD_STATIC: begin
foundField := leftNode.operand1 as Field;
enclosingCallable := parent.parentCode.parentCallable;
enclosingClassType := enclosingCallable.parentType;
if foundField.isFinal() and (not(enclosingCallable is ClassInit) or (foundField.parentType <> enclosingClassType) or (foundField.value <> nil)) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.access.field-final.write'), [
CoObject.create(foundField)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
leftType := foundField.&type;
action := __code.createAndAppendNode(leftNode);
position := parseExpression(action, source, position + 1, isStaticOnly);
rightNode := action.readComponent(-1);
requiresValue(rightNode);
__code.createAndPrependNode(action).setData(leftNode.position, leftType, LOAD_STATIC, foundField);
leftNode.setData(before, nil, STORE_STATIC, foundField);
goto break_label1;
end;
READ_FIELD,
READ_SPECIAL,
READ_PROPERTY: begin
foundFieldoid := leftNode.operand1 as TypedMember;
if Lang.isInstance(foundFieldoid, &Property) then begin
if not &Property(Lang.cast(foundFieldoid, &Property)).hasWrite() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.access.property-read-only.write'), [
CoSimple.create(foundFieldoid)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
end else begin
load := leftNode.readComponent(0);
enclosingCallable := parent.parentCode.parentCallable;
enclosingClassType := enclosingCallable.parentType;
if
foundFieldoid.isFinal() and (
not(enclosingCallable is InstInit) or (foundFieldoid.parentType <> enclosingClassType) or
(load.instruction <> LOAD_LOCAL) or (load.operand1 <> enclosingCallable.arguments.thisArgument)
)
then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.access.field-final.write'), [
CoSimple.create(foundFieldoid)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
end;
leftType := foundFieldoid.&type;
action := __code.createAndAppendNode(leftNode);
position := parseExpression(action, source, position + 1, isStaticOnly);
rightNode := action.readComponent(-1);
requiresValue(rightNode);
foundItem := TableItem(Lang.cast(foundFieldoid, TableItem));
read := __code.createAndPrependNode(action).setData(leftNode.position, leftType, instruction, foundItem);
__code.createAndAppendNode(read).setData(-1, nil, DUP1, fldTypeObject);
leftNode.setData(before, nil, instruction + A_DELTA, foundItem);
goto break_label1;
end;
READ_COMPONENT: begin
leftType := leftNode.operand1 as &Type;
action := __code.createAndAppendNode(leftNode);
position := parseExpression(action, source, position + 1, isStaticOnly);
rightNode := action.readComponent(-1);
requiresValue(rightNode);
read := __code.createAndPrependNode(action).setData(leftNode.position, leftType, READ_COMPONENT, leftType);
__code.createAndAppendNode(read).setData(-1, nil, DUP2, fldTypeInt);
leftNode.setData(before, nil, WRITE_COMPONENT, leftType);
goto break_label1;
end;
INVOKE_SERVICE,
INVOKE_SPECIAL,
INVOKE_VIRTUAL: begin
foundItem := leftNode.operand1;
if foundItem is &Operator then begin
foundReadOperator := &Operator(foundItem);
if foundReadOperator.kind = READ_COMPONENT then begin
leftType := foundReadOperator.&type;
load := leftNode.readComponent(0);
enclosingClassType := parent.parentCode.parentCallable.parentType;
dereferenceClassType := load.&type as ru.malik.elaborarer.avtoo.lang.ClassType;
isUseSuper := load.useSuper;
if isUseSuper then begin
impliedParentClassType := enclosingClassType;
end else begin
impliedParentClassType := dereferenceClassType;
end;
arguments := [ foundReadOperator.arguments.readComponent(0).&type, leftType ];
foundOperators := dereferenceClassType.findOperators(WRITE_COMPONENT, arguments, enclosingClassType);
if system.length(foundOperators) <> 1 then begin
foundWriteOperator := nil;
end else begin
foundWriteOperator := foundOperators[0];
end;
if (foundWriteOperator = nil) or not foundWriteOperator.isIdentityArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-found.operator'), [
CoObject.create(dereferenceClassType), CoAnsiString.create(&Operator.kindToSymbol(WRITE_COMPONENT) + ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundWriteOperator.isVisibleFrom(enclosingClassType, impliedParentClassType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.operator'), [
CoAnsiString.create(enclosingClassType.specialSimpleName), CoObject.create(foundWriteOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if isUseSuper and foundWriteOperator.isAbstract() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.direct-access-abstract.operator'), [
CoObject.create(foundWriteOperator)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
action := __code.createAndAppendNode(leftNode);
position := parseExpression(action, source, position + 1, isStaticOnly);
rightNode := action.readComponent(-1);
requiresValue(rightNode);
read := __code.createAndPrependNode(action).setData(leftNode.position, leftType, instruction, foundReadOperator);
__code.createAndAppendNode(read).setData(-1, nil, DUP2, arguments[0]);
if isUseSuper then begin
instruction := INVOKE_SPECIAL;
end else begin
instruction := invokeInstructionFor(foundWriteOperator, dereferenceClassType);
end;
leftNode.setData(before, nil, instruction, foundWriteOperator);
goto break_label1;
end;
end;
end;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'applicable.operator.assignment'), [
CoUnicodeString.create(source.getLexemeString(before))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
break_label1:
rightType := rightNode.&type;
if
not(leftType is PrimitiveType) or not leftType.isBoolean() and not leftType.isNumeric() or
not(rightType is PrimitiveType) or not rightType.isBoolean() and not rightType.isNumeric()
then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.2'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(leftType), CoObject.create(rightType)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
isChar := leftType.isChar();
typeInt := fldTypeInt;
case operation of
O_SCAL_SHL,
O_SCAL_SHR,
O_SCAL_SHRU,
O_VECT_SHL,
O_VECT_SHR,
O_VECT_SHRU: begin
mustType := typeInt;
end;
else
if isChar then begin
mustType := typeInt;
end else begin
mustType := leftType;
end;
end;
if not mustType.isConvertableFrom(rightType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.type'), [
CoObject.create(rightType), CoObject.create(mustType)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
cast(rightNode, mustType);
kind := leftType.kind;
begin
case operation of
O_BIT_AND,
O_BIT_OR,
O_BIT_XOR: begin
if kind = TYP_CHAR then begin
resultType := typeInt;
goto break_label2;
end;
if (kind = TYP_BOOLEAN) or (kind >= TYP_BYTE) and (kind <= TYP_LONG8) then begin
resultType := leftType;
goto break_label2;
end;
end;
O_SCAL_MUL,
O_SCAL_ADD,
O_SCAL_SUB: begin
if kind = TYP_CHAR then begin
resultType := typeInt;
goto break_label2;
end;
if (kind >= TYP_BYTE) and (kind <= TYP_SHORT8) then begin
resultType := getPrimitiveType(TYP_INT + (kind and 3));
goto break_label2;
end;
if (kind >= TYP_REAL) and (kind <= TYP_FLOAT8) or (kind >= TYP_INT) and (kind <= TYP_LONG8) then begin
resultType := leftType;
goto break_label2;
end;
end;
O_SCAL_DIV,
O_SCAL_DIVU: begin
if (kind = TYP_CHAR) or (kind = TYP_BYTE) or (kind = TYP_SHORT) then begin
resultType := typeInt;
goto break_label2;
end;
if (kind >= TYP_REAL) and (kind <= TYP_FLOAT8) or (kind = TYP_INT) or (kind = TYP_LONG) then begin
resultType := leftType;
goto break_label2;
end;
end;
O_SCAL_REM,
O_SCAL_REMU: begin
if (kind = TYP_CHAR) or (kind = TYP_BYTE) or (kind = TYP_SHORT) then begin
resultType := typeInt;
goto break_label2;
end;
if (kind = TYP_REAL) or (kind = TYP_DOUBLE) or (kind = TYP_FLOAT) or (kind = TYP_INT) or (kind = TYP_LONG) then begin
resultType := leftType;
goto break_label2;
end;
end;
O_SCAL_SHL,
O_SCAL_SHR,
O_SCAL_SHRU: begin
if kind = TYP_CHAR then begin
resultType := typeInt;
goto break_label2;
end;
if (kind >= TYP_BYTE) and (kind <= TYP_SHORT8) then begin
resultType := getPrimitiveType(TYP_INT + (kind and 3));
goto break_label2;
end;
if (kind >= TYP_INT) and (kind <= TYP_LONG8) then begin
resultType := leftType;
goto break_label2;
end;
end;
O_VECT_MUL,
O_VECT_ADD,
O_VECT_SUB: begin
if kind = TYP_CHAR then begin
resultType := typeInt;
goto break_label2;
end;
if (kind >= TYP_DOUBLE) and (kind <= TYP_LONG8) then begin
resultType := leftType;
goto break_label2;
end;
end;
O_VECT_DIV: begin
if (kind >= TYP_DOUBLE) and (kind <= TYP_FLOAT8) then begin
resultType := leftType;
goto break_label2;
end;
end;
O_VECT_SHL,
O_VECT_SHR,
O_VECT_SHRU,
O_VECT_GT,
O_VECT_GE,
O_VECT_LT,
O_VECT_LE,
O_VECT_EQ,
O_VECT_NE: begin
if kind = TYP_CHAR then begin
resultType := typeInt;
goto break_label2;
end;
if (kind >= TYP_BYTE) and (kind <= TYP_LONG8) then begin
resultType := leftType;
goto break_label2;
end;
end;
O_VECT_HMUL,
O_VECT_HMULU,
O_VECT_SADD,
O_VECT_SADDU,
O_VECT_SSUB,
O_VECT_SSUBU: begin
if (kind >= TYP_BYTE) and (kind <= TYP_SHORT8) then begin
resultType := leftType;
goto break_label2;
end;
end;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-defined.operator.2'), [
CoUnicodeString.create(source.getLexemeString(before)), CoObject.create(leftType), CoObject.create(rightType)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
break_label2:
if isChar then begin
action.setData(before, resultType, operation, typeInt);
end else begin
action.setData(before, resultType, operation, leftType);
end;
cast(action, leftType);
end;
end;
break_label0:
result := position;
end;
function ImmediateBuilder.parseDeclareLocal(parent: Node; source: TextSource; position: int; isLocalAllowed: boolean): int;
label
break_label0;
var
isName: boolean;
isFinal: boolean;
kind: int;
after: int;
before: int;
instruction: int;
localName: AnsiString;
dup: Node;
last: Node;
value: Node;
__code: Code;
declare: Node;
valueType: &Type;
localType: &Type;
localValue: Constant;
foundCallable: Callable;
localTypeHolder: ImmediateBuilderItemHolder;
enclosingClassType: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
__code := parent.parentCode;
begin
if isLocalAllowed then begin
kind := source.getLexemeKind(position);
isFinal := false;
if kind = DCL_FINAL then begin
isFinal := true;
inc(position);
kind := source.getLexemeKind(position);
end;
isName := kind = L_NAME;
if (kind >= TYP_VOID) and (kind < TYP_VOID + PRIMITIVES_LENGTH) or isName then begin
enclosingClassType := __code.parentCallable.parentType;
localTypeHolder := getItemHolder();
if isName then begin
after := tryParseName(parent, source, position, source.getLexemeString(position).toUTF8(), localTypeHolder);
end else begin
after := tryParseTypeName(source, position, enclosingClassType, localTypeHolder);
end;
localType := localTypeHolder.resultType;
if (localType <> nil) and (source.getLexemeKind(after) = L_NAME) then begin
if not localType.isVisibleFrom(enclosingClassType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.type'), [
CoAnsiString.create(localType.specialCanonicalName)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
position := after;
if localType.isVoid() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'type.not-suitable.local'), [
CoObject.create(localType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
localName := source.getLexemeString(position).toUTF8();
tryParseName(parent, source, position, localName, localTypeHolder);
if localTypeHolder.resultItem is Local then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'duplicate.name.local'), [
CoAnsiString.create(localName)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
before := position;
inc(position);
declare := __code.createAndAppendNode(parent);
if source.getLexemeKind(position) = EQUAL then begin
position := parseExpression(declare, source, position + 1, false);
value := declare.readComponent(-1);
requiresValue(value);
valueType := value.&type;
if not localType.isConvertableFrom(valueType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.type'), [
CoObject.create(valueType), CoObject.create(localType)
]
));
exception.source := source;
exception.position := before + 1;
raise exception;
end;
cast(value, localType);
if isFinal and (value.instruction = LOAD_CONST) then begin
localValue := value.operandC;
if not localValue.isReference() or localValue.isReflective() or localValue.isNull() then begin
declare.setData(before + 1, nil, DECLARE_LOCAL, __code.createLocal(true, localType, localName, localValue, before));
__code.removeNode(value);
goto break_label0;
end;
end;
declare.setData(before + 1, nil, DECLARE_LOCAL, __code.createLocal(isFinal, localType, localName, nil, before));
goto break_label0;
end;
if isFinal then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.equals'));
exception.source := source;
exception.position := position;
raise exception;
end;
if localType is ru.malik.elaborarer.avtoo.lang.ClassType then begin
__code.createAndAppendNode(declare).setData(-1, localType, LOAD_CONST, fldConstantFactory.createNull().castTo(localType));
end else
if localType.isNumeric() then begin
__code.createAndAppendNode(declare).setData(-1, localType, LOAD_CONST, fldConstantFactory.createByte(0).castTo(localType));
end else begin
__code.createAndAppendNode(declare).setData(-1, localType, LOAD_CONST, fldConstantFactory.createBoolean(false));
end;
declare.setData(-1, nil, DECLARE_LOCAL, __code.createLocal(false, localType, localName, nil, before));
goto break_label0;
end;
end;
if isFinal then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.declaration.local'));
exception.source := source;
exception.position := position;
raise exception;
end;
end;
position := parseExpression(parent, source, position, false);
value := parent.readComponent(-1);
instruction := value.instruction;
case instruction of
INC_POST_LOAD_LOCAL,
INC_PRED_LOAD_LOCAL: begin
value.setData(value.position, nil, INC_LOCAL, value.operand1);
end;
DEC_POST_LOAD_LOCAL,
DEC_PRED_LOAD_LOCAL: begin
value.setData(value.position, nil, DEC_LOCAL, value.operand1);
end;
INVOKE_STATIC: begin
if not (value.operand1 as Callable).&type.isVoid() then value.weak := true;
value.&type := nil;
end;
INVOKE_SERVICE,
INVOKE_SPECIAL,
INVOKE_VIRTUAL,
WRITE_COMPONENT: begin
if instruction <> WRITE_COMPONENT then begin
foundCallable := value.operand1 as Callable;
if not(foundCallable is &Operator) or (&Operator(foundCallable).kind <> WRITE_COMPONENT) then begin
if not foundCallable.&type.isVoid() then value.weak := true;
value.&type := nil;
goto break_label0;
end;
end;
last := value.readComponent(-1);
if last.instruction = DUP1X2 then begin
__code.removeNode(last);
value.&type := nil;
goto break_label0;
end;
if value.getLength() = 4 then begin
if last.instruction = CAST_TO then last := last.readComponent(0);
instruction := last.instruction;
if (instruction = O_SCAL_ADD) or (instruction = O_VECT_ADD) then begin
dup := last.readComponent(0);
if dup.instruction = DUP1X2 then begin
__code.removeNode(dup);
__code.moveNode(value.readComponent(-2), last, 0);
value.&type := nil;
end;
end;
end;
end;
WRITE_FIELD,
WRITE_SPECIAL,
WRITE_PROPERTY: begin
last := value.readComponent(-1);
if last.instruction = DUP1X1 then begin
__code.removeNode(last);
value.&type := nil;
goto break_label0;
end;
if value.getLength() = 3 then begin
if last.instruction = CAST_TO then last := last.readComponent(0);
instruction := last.instruction;
if (instruction = O_SCAL_ADD) or (instruction = O_VECT_ADD) then begin
dup := last.readComponent(0);
if dup.instruction = DUP1X1 then begin
__code.removeNode(dup);
__code.moveNode(value.readComponent(-2), last, 0);
value.&type := nil;
end;
end;
end;
end;
STORE_LOCAL,
STORE_STATIC: begin
last := value.readComponent(-1);
if last.instruction = DUP1 then begin
__code.removeNode(last);
value.&type := nil;
goto break_label0;
end;
if value.getLength() = 2 then begin
if last.instruction = CAST_TO then last := last.readComponent(0);
instruction := last.instruction;
if (instruction = O_SCAL_ADD) or (instruction = O_VECT_ADD) then begin
dup := last.readComponent(0);
if dup.instruction = DUP1 then begin
__code.removeNode(dup);
__code.moveNode(value.readComponent(-2), last, 0);
value.&type := nil;
end;
end;
end;
end;
NEW_INSTANCE: begin
dup := value.readComponent(-1).readComponent(0);
if dup.instruction = DUP1 then begin
__code.removeNode(dup);
value.&type := nil;
end;
end;
else
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.invocation-or-assignment'));
exception.source := source;
exception.position := position;
raise exception;
end;
end;
break_label0:
result := position;
end;
function ImmediateBuilder.parseDeclareWith(parent: Node; source: TextSource; position: int; isSynchronized: boolean): int;
label
break_label0;
var
isName: boolean;
isFinal: boolean;
kind: int;
after: int;
before: int;
instruction: int;
message: AnsiString;
localName: AnsiString;
value: Node;
__code: Code;
declare: Node;
valueType: &Type;
localType: &Type;
localValue: Constant;
localTypeHolder: ImmediateBuilderItemHolder;
enclosingClassType: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
__code := parent.parentCode;
begin
begin
kind := source.getLexemeKind(position);
isFinal := false;
if kind = DCL_FINAL then begin
isFinal := true;
inc(position);
kind := source.getLexemeKind(position);
end;
isName := kind = L_NAME;
if (kind >= TYP_VOID) and (kind < TYP_VOID + PRIMITIVES_LENGTH) or isName then begin
enclosingClassType := __code.parentCallable.parentType;
localTypeHolder := getItemHolder();
if isName then begin
after := tryParseName(parent, source, position, source.getLexemeString(position).toUTF8(), localTypeHolder);
end else begin
after := tryParseTypeName(source, position, enclosingClassType, localTypeHolder);
end;
localType := localTypeHolder.resultType;
if (localType <> nil) and (source.getLexemeKind(after) = L_NAME) then begin
if not localType.isVisibleFrom(enclosingClassType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.type'), [
CoAnsiString.create(localType.specialCanonicalName)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
position := after;
if not(localType is ru.malik.elaborarer.avtoo.lang.ClassType) then begin
if isSynchronized then begin
message := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-be.class-type.local.synchronized');
end else begin
message := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-be.class-type.local.with');
end;
exception := TextSourceException.create(AnsiString.format(message, [
CoObject.create(localType), CoObject.create(fldTypeObject)
]));
exception.source := source;
exception.position := position;
raise exception;
end;
localName := source.getLexemeString(position).toUTF8();
tryParseName(parent, source, position, localName, localTypeHolder);
if localTypeHolder.resultItem is Local then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'duplicate.name.local'), [
CoAnsiString.create(localName)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
before := position;
inc(position);
if source.getLexemeKind(position) <> EQUAL then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.equals'));
exception.source := source;
exception.position := position;
raise exception;
end;
declare := __code.createAndAppendNode(parent);
position := parseExpression(declare, source, position + 1, false);
value := declare.readComponent(-1);
requiresValue(value);
valueType := value.&type;
if not localType.isConvertableFrom(valueType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.type'), [
CoObject.create(valueType), CoObject.create(localType)
]
));
exception.source := source;
exception.position := before + 1;
raise exception;
end;
cast(value, localType);
if isSynchronized then begin
instruction := DECLARE_LOCAL;
end else begin
instruction := DECLARE_WITH;
end;
if value.instruction = LOAD_CONST then begin
localValue := value.operandC;
if localValue.isReflective() or localValue.isNull() then begin
declare.setData(before + 1, nil, instruction, __code.createLocal(true, localType, localName, localValue, before));
__code.removeNode(value);
goto break_label0;
end;
end;
declare.setData(before + 1, nil, instruction, __code.createLocal(true, localType, localName, nil, before));
goto break_label0;
end;
end;
if isFinal then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.declaration.local'));
exception.source := source;
exception.position := position;
raise exception;
end;
end;
declare := __code.createAndAppendNode(parent);
position := parseExpression(declare, source, position, false);
value := declare.readComponent(-1);
requiresValue(value);
valueType := value.&type;
if not(valueType is ru.malik.elaborarer.avtoo.lang.ClassType) then begin
if isSynchronized then begin
message := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-be.class-type.expression.synchronized');
end else begin
message := AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-be.class-type.expression.with');
end;
exception := TextSourceException.create(AnsiString.format(message, [
CoObject.create(valueType), CoObject.create(fldTypeObject)
]));
exception.source := source;
exception.position := position;
raise exception;
end;
if value.instruction = LOAD_CONST then begin
localValue := value.operandC;
if localValue.isReference() or localValue.isNull() then begin
if isSynchronized then begin
declare.setData(-1, nil, DECLARE_LOCAL, __code.createMonitorLocal(ru.malik.elaborarer.avtoo.lang.ClassType(valueType), localValue));
end else begin
declare.setData(-1, nil, DECLARE_WITH, __code.createWithLocal(ru.malik.elaborarer.avtoo.lang.ClassType(valueType), nil));
end;
__code.removeNode(value);
goto break_label0;
end;
end;
if isSynchronized then begin
declare.setData(-1, nil, DECLARE_LOCAL, __code.createMonitorLocal(ru.malik.elaborarer.avtoo.lang.ClassType(valueType), nil));
end else begin
declare.setData(-1, nil, DECLARE_WITH, __code.createWithLocal(ru.malik.elaborarer.avtoo.lang.ClassType(valueType), nil));
end;
end;
break_label0:
result := position;
end;
function ImmediateBuilder.parseBlock(control: Node; source: TextSource; position: int): int;
var
exception: TextSourceException;
begin
if source.getLexemeKind(position) <> CURLY_CLOSED then repeat
position := parseControl(control, source, position);
case source.getLexemeKind(position) of
L_END: begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
CURLY_CLOSED: break;
end;
until false;
result := position + 1;
end;
function ImmediateBuilder.parseBreak(control: Node; source: TextSource; position: int): int;
label
break_label0;
var
__node: Node;
labelName: TObject;
exception: TextSourceException;
begin
labelName := nil;
try
begin
if source.getLexemeKind(position) <> L_NAME then begin
{ без метки }
__node := control.parentNode;
while __node <> nil do begin
case __node.instruction of
FINALLY_ENTER: begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-transfer.outside-finally'));
exception.source := source;
exception.position := position;
raise exception;
end;
FCT_DO,
FCT_FOR,
FCT_WHILE,
FCT_SWITCH: begin
control.setData(control.position, FCT_BREAK, __node);
goto break_label0;
end;
end;
__node := __node.parentNode;
end;
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-use.break'));
exception.source := source;
exception.position := position;
raise exception;
end;
{ с меткой }
labelName := CoAnsiString.create(source.getLexemeString(position).toUTF8());
__node := control.parentNode;
while __node <> nil do begin
case __node.instruction of
FINALLY_ENTER: begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-transfer.outside-finally'));
exception.source := source;
exception.position := position;
raise exception;
end;
FCT_LABEL: begin
if labelName.equals(__node.reference1) then begin
control.setData(control.position, FCT_BREAK, __node);
inc(position);
goto break_label0;
end;
end;
end;
__node := __node.parentNode;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-found.label'), [
CoAnsiString.create(labelName.toString())
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
break_label0:
finally
labelName.free();
end;
if source.getLexemeKind(position) <> SEMICOLON then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.semicolon'));
exception.source := source;
exception.position := position;
raise exception;
end;
result := position + 1;
end;
function ImmediateBuilder.parseContinue(control: Node; source: TextSource; position: int): int;
label
break_label0;
var
instruction: int;
__node: Node;
labelName: TObject;
exception: TextSourceException;
begin
labelName := nil;
try
begin
if source.getLexemeKind(position) <> L_NAME then begin
{ без метки }
__node := control.parentNode;
while __node <> nil do begin
case __node.instruction of
FINALLY_ENTER: begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-transfer.outside-finally'));
exception.source := source;
exception.position := position;
raise exception;
end;
FCT_DO,
FCT_FOR,
FCT_WHILE: begin
control.setData(control.position, FCT_CONTINUE, __node);
goto break_label0;
end;
end;
__node := __node.parentNode;
end;
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-use.continue'));
exception.source := source;
exception.position := position;
raise exception;
end;
{ с меткой }
labelName := CoAnsiString.create(source.getLexemeString(position).toUTF8());
__node := control.parentNode;
while __node <> nil do begin
case __node.instruction of
FINALLY_ENTER: begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-transfer.outside-finally'));
exception.source := source;
exception.position := position;
raise exception;
end;
FCT_LABEL: begin
if labelName.equals(__node.reference1) then begin
__node := __node.readComponent(0);
instruction := __node.instruction;
if (instruction <> FCT_DO) and (instruction <> FCT_FOR) and (instruction <> FCT_WHILE) then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-use.continue'));
exception.source := source;
exception.position := position;
raise exception;
end;
control.setData(control.position, FCT_CONTINUE, __node);
inc(position);
goto break_label0;
end;
end;
end;
__node := __node.parentNode;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-found.label'), [
CoAnsiString.create(labelName.toString())
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
break_label0:
finally
labelName.free();
end;
if source.getLexemeKind(position) <> SEMICOLON then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.semicolon'));
exception.source := source;
exception.position := position;
raise exception;
end;
result := position + 1;
end;
function ImmediateBuilder.parseDo(control: Node; source: TextSource; position: int): int;
var
condition: Node;
conditionType: &Type;
exception: TextSourceException;
begin
{ тело цикла }
position := parseControl(control, source, position);
if source.getLexemeKind(position) <> FCT_WHILE then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.while'));
exception.source := source;
exception.position := position;
raise exception;
end;
{ условие повтора }
inc(position);
if source.getLexemeKind(position) <> PARENTH_OPENED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
position := parseExpression(control, source, position + 1, false);
condition := control.readComponent(-1);
requiresValue(condition);
conditionType := condition.&type;
if not conditionType.isBoolean() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-use.expression.repeat-condition'), [
CoObject.create(conditionType), CoObject.create(fldTypeBoolean)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if source.getLexemeKind(position) <> PARENTH_CLOSED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
{ точка с запятой }
inc(position);
if source.getLexemeKind(position) <> SEMICOLON then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.semicolon'));
exception.source := source;
exception.position := position;
raise exception;
end;
result := position + 1;
end;
function ImmediateBuilder.parseFor(control: Node; source: TextSource; position: int): int;
var
index: int;
step: Node;
__code: Code;
condition: Node;
conditionType: &Type;
exception: TextSourceException;
begin
{ инициализация }
if source.getLexemeKind(position) <> PARENTH_OPENED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
inc(position);
if source.getLexemeKind(position) <> SEMICOLON then repeat
position := parseDeclareLocal(control, source, position, true);
case source.getLexemeKind(position) of
SEMICOLON:
break;
COMMA:
inc(position);
else
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.semicolon'));
exception.source := source;
exception.position := position;
raise exception;
end;
until false;
__code := control.parentCode;
__code.createAndAppendNode(control).setData(-1, FCT_JUMP);
{ условие повтора }
inc(position);
if source.getLexemeKind(position) = SEMICOLON then begin
condition := __code.createAndAppendNode(control).setData(-1, fldTypeBoolean, LOAD_CONST, fldConstantFactory.createBoolean(true));
end else begin
position := parseExpression(control, source, position, false);
condition := control.readComponent(-1);
requiresValue(condition);
conditionType := condition.&type;
if not conditionType.isBoolean() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-use.expression.repeat-condition'), [
CoObject.create(conditionType), CoObject.create(fldTypeBoolean)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if source.getLexemeKind(position) <> SEMICOLON then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.semicolon'));
exception.source := source;
exception.position := position;
raise exception;
end;
end;
{ шаг }
step := __code.createAndAppendNode(control).setData(-1, FCT_BLOCK);
inc(position);
if source.getLexemeKind(position) <> PARENTH_CLOSED then repeat
position := parseDeclareLocal(step, source, position, false);
case source.getLexemeKind(position) of
PARENTH_CLOSED:
break;
COMMA:
inc(position);
else
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
until false;
{ тело цикла }
position := parseControl(control, source, position + 1);
{ перестановка узлов }
index := control.getLength();
__code.moveNode(step, index);
__code.moveNode(condition, index);
result := position;
end;
function ImmediateBuilder.parseIf(control: Node; source: TextSource; position: int): int;
var
condition: Node;
conditionType: &Type;
exception: TextSourceException;
begin
{ условие ветвления }
if source.getLexemeKind(position) <> PARENTH_OPENED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
position := parseExpression(control, source, position + 1, false);
condition := control.readComponent(-1);
requiresValue(condition);
conditionType := condition.&type;
if not conditionType.isBoolean() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-use.expression.branch-condition'), [
CoObject.create(conditionType), CoObject.create(fldTypeBoolean)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if source.getLexemeKind(position) <> PARENTH_CLOSED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
{ ветка «тогда» }
position := parseControl(control, source, position + 1);
if source.getLexemeKind(position) = FCT_ELSE then begin
{ ветка «иначе» }
control.parentCode.createAndAppendNode(control).setData(-1, FCT_JUMP).special := true;
position := parseControl(control, source, position + 1);
end;
result := position;
end;
function ImmediateBuilder.parseReturn(control: Node; source: TextSource; position: int): int;
var
value: Node;
__node: Node;
valueType: &Type;
targetType: &Type;
exception: TextSourceException;
begin
targetType := control.parentCode.parentCallable.&type;
if not targetType.isVoid() then begin
position := parseExpression(control, source, position, false);
value := control.readComponent(-1);
requiresValue(value);
valueType := value.&type;
if not targetType.isConvertableFrom(valueType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.type'), [
CoObject.create(valueType), CoObject.create(targetType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
cast(value, targetType);
end;
__node := control.parentNode;
while __node <> nil do begin
if __node.instruction = FINALLY_ENTER then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-transfer.outside-finally'));
exception.source := source;
exception.position := position;
raise exception;
end;
__node := __node.parentNode;
end;
if source.getLexemeKind(position) <> SEMICOLON then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.semicolon'));
exception.source := source;
exception.position := position;
raise exception;
end;
result := position + 1;
end;
function ImmediateBuilder.parseSwitch(control: Node; source: TextSource; position: int): int;
var
ldefault: boolean;
before: int;
llength: int;
labelValue: int;
labels: int_Array1d;
buffer: int_Array1d;
__code: Code;
branch: Node;
target: Node;
__label: Node;
labelType: &Type;
targetType: &Type;
exception: TextSourceException;
begin
{ выражение ветвления }
if source.getLexemeKind(position) <> PARENTH_OPENED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
__code := control.parentCode;
branch := __code.createAndAppendNode(control).setData(-1, FCT_BRANCH);
position := parseExpression(branch, source, position + 1, false);
target := branch.readComponent(-1);
requiresValue(target);
targetType := target.&type;
if not targetType.isInt() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-use.expression.branch-switch'), [
CoObject.create(targetType), CoObject.create(fldTypeInt)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if source.getLexemeKind(position) <> PARENTH_CLOSED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
{ тело ветвления }
inc(position);
if source.getLexemeKind(position) <> CURLY_OPENED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
inc(position);
__label := nil;
labels := &Array.newInt1d($1f);
llength := 0;
ldefault := false;
while true do case source.getLexemeKind(position) of
CURLY_CLOSED: begin
if not ldefault then __code.createAndAppendNode(control).setData(position, FCT_DEFAULT);
break;
end;
FCT_CASE: begin
before := position;
position := parseExpression(control, source, position + 1, false);
__label := control.readComponent(-1);
if __label.instruction <> LOAD_CONST then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'must-be.constant.case-label'));
exception.source := source;
exception.position := position;
raise exception;
end;
labelType := __label.&type;
if not targetType.isConvertableFrom(labelType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.converted.type'), [
CoObject.create(labelType), CoObject.create(targetType)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
labelValue := __label.operandC.asInt();
if (llength > 0) and (&Array.indexOf(labelValue, labels, 0, llength) >= 0) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'duplicate.label.case'), [
CoAnsiString.create(CoInt.toString(labelValue))
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if source.getLexemeKind(position) <> COLON then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.colon'));
exception.source := source;
exception.position := position;
raise exception;
end;
if llength = system.length(labels) then begin
buffer := &Array.newInt1d((llength shl 1) or 1);
&Array.copyPrimitives(labels, 0, buffer, 0, llength);
labels := buffer;
end;
__label.setData(before, FCT_CASE, CoInt.create(labelValue));
labels[llength] := labelValue;
inc(llength);
inc(position);
end;
FCT_DEFAULT: begin
before := position;
inc(position);
if ldefault then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'duplicate.label.default'));
exception.source := source;
exception.position := position;
raise exception;
end;
if source.getLexemeKind(position) <> COLON then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.colon'));
exception.source := source;
exception.position := position;
raise exception;
end;
__label := __code.createAndAppendNode(control).setData(before, FCT_DEFAULT);
ldefault := true;
inc(position);
end;
else
if __label = nil then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.case-or-default'));
exception.source := source;
exception.position := position;
raise exception;
end;
position := parseControl(__label, source, position);
end;
result := position + 1;
end;
function ImmediateBuilder.parseSynchronized(control: Node; source: TextSource; position: int): int;
var
isConstant: boolean;
isSynchronizedWith: boolean;
enter: Node;
leave: Node;
__code: Code;
blockTry: Node;
blockFin: Node;
monitor: Local;
value: Constant;
typeObject: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
isSynchronizedWith := false;
if source.getLexemeKind(position) = FCT_WITH then begin
isSynchronizedWith := true;
inc(position);
end;
{ переменная синхронизации }
if source.getLexemeKind(position) <> PARENTH_OPENED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
position := parseDeclareWith(control, source, position + 1, not isSynchronizedWith);
monitor := control.readComponent(-1).operand1 as Local;
typeObject := fldTypeObject;
__code := control.parentCode;
enter := __code.createAndAppendNode(control).setData(-1, MONITOR_ENTER);
value := monitor.value;
isConstant := monitor.isConstant();
if isConstant then begin
__code.createAndAppendNode(enter).setData(-1, typeObject, LOAD_CONST, value);
end else begin
__code.createAndAppendNode(enter).setData(-1, typeObject, LOAD_LOCAL, monitor);
end;
if source.getLexemeKind(position) <> PARENTH_CLOSED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
{ тело синхронизации }
inc(position);
if source.getLexemeKind(position) <> CURLY_OPENED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
control := __code.createAndAppendNode(control).setData(-1, FCT_TRY);
blockTry := __code.createAndAppendNode(control).setData(-1, FCT_BEGIN);
position := parseBlock(blockTry, source, position + 1) - 1;
blockTry := __code.createAndAppendNode(blockTry).setData(-1, FCT_END);
blockFin := __code.createAndAppendNode(control).setData(-1, FINALLY_ENTER);
leave := __code.createAndAppendNode(blockFin).setData(-1, MONITOR_LEAVE);
if isConstant then begin
__code.createAndAppendNode(leave).setData(-1, typeObject, LOAD_CONST, value);
end else begin
__code.createAndAppendNode(leave).setData(-1, typeObject, LOAD_LOCAL, monitor);
end;
__code.createAndAppendNode(blockFin).setData(-1, FINALLY_LEAVE).special := true;
__code.createAndAppendNode(blockTry).setData(-1, INVOKE_FINALLY, blockFin).special := true;
__code.createAndAppendNode(blockTry).setData(-1, FCT_JUMP).special := true;
result := position + 1;
end;
function ImmediateBuilder.parseThrow(control: Node; source: TextSource; position: int): int;
var
target: Node;
targetType: &Type;
typeThrowable: &Type;
exception: TextSourceException;
begin
{ выражение }
position := parseExpression(control, source, position, false);
target := control.readComponent(-1);
requiresValue(target);
targetType := target.&type;
typeThrowable := fldTypeThrowable;
if not typeThrowable.isConvertableFrom(targetType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.thrown'), [
CoObject.create(targetType), CoObject.create(typeThrowable)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
{ точка с запятой }
if source.getLexemeKind(position) <> SEMICOLON then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.semicolon'));
exception.source := source;
exception.position := position;
raise exception;
end;
control.setData(control.position, FCT_THROW, targetType);
result := position + 1;
end;
function ImmediateBuilder.parseTry(control: Node; source: TextSource; position: int): int;
var
block: int;
before: int;
localName: AnsiString;
__code: Code;
__node: Node;
parent: Node;
blockTry: Node;
blockFin: Node;
blockCat: Node;
localType: &Type;
localTypeHolder: ImmediateBuilderItemHolder;
enclosing: ru.malik.elaborarer.avtoo.lang.ClassType;
typeThrowable: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
{ проверка на вложение в блок finally }
__node := control.parentNode;
while __node <> nil do begin
if __node.instruction = FINALLY_ENTER then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.try-inside-finally'));
exception.source := source;
exception.position := position - 1;
raise exception;
end;
__node := __node.parentNode;
end;
{ тело блока }
if source.getLexemeKind(position) <> CURLY_OPENED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
__code := control.parentCode;
blockTry := __code.createAndAppendNode(control).setData(position, FCT_BEGIN);
position := parseBlock(blockTry, source, position + 1);
blockTry := __code.createAndAppendNode(blockTry).setData(-1, FCT_END);
case source.getLexemeKind(position) of
FCT_CATCH: begin
blockCat := nil;
parent := control.parentNode;
typeThrowable := fldTypeThrowable;
enclosing := __code.parentCallable.parentType;
localTypeHolder := getItemHolder();
repeat
{ тело блока catch }
block := position;
if blockCat <> nil then begin
__code.createAndAppendNode(blockCat).setData(-1, FCT_JUMP).special := true;
end;
inc(position);
if source.getLexemeKind(position) <> PARENTH_OPENED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
inc(position);
if source.getLexemeKind(position) <> L_NAME then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.name.exception.type'));
exception.source := source;
exception.position := position;
raise exception;
end;
position := parseTypeName(source, position, enclosing, localTypeHolder);
localType := localTypeHolder.resultType;
if not typeThrowable.isAssignableFrom(localType) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-be.thrown'), [
CoObject.create(localType), CoObject.create(typeThrowable)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if source.getLexemeKind(position) <> L_NAME then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.name.exception.local'));
exception.source := source;
exception.position := position;
raise exception;
end;
before := position;
localName := source.getLexemeString(position).toUTF8();
tryParseName(parent, source, position, localName, localTypeHolder);
if localTypeHolder.resultItem is Local then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'duplicate.name.local'), [
CoAnsiString.create(localName)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
inc(position);
if source.getLexemeKind(position) <> PARENTH_CLOSED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
inc(position);
if source.getLexemeKind(position) <> CURLY_OPENED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
blockCat := __code.createAndAppendNode(control).setData(block, FCT_CATCH, localType);
__code.createAndAppendNode(blockCat).setData(-1, nil, DECLARE_LOCAL, __code.createLocal(true, localType, localName, nil, before));
position := parseBlock(blockCat, source, position + 1);
until source.getLexemeKind(position) <> FCT_CATCH;
__code.createAndAppendNode(blockTry).setData(-1, FCT_JUMP).special := true;
end;
FCT_FINALLY: begin
{ тело блока finally }
inc(position);
if source.getLexemeKind(position) <> CURLY_OPENED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
blockFin := __code.createAndAppendNode(control).setData(-1, FINALLY_ENTER);
position := parseBlock(blockFin, source, position + 1);
__code.createAndAppendNode(blockFin).setData(-1, FINALLY_LEAVE).special := true;
__code.createAndAppendNode(blockTry).setData(-1, INVOKE_FINALLY, blockFin).special := true;
__code.createAndAppendNode(blockTry).setData(-1, FCT_JUMP).special := true;
end;
else
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.catch-or-finally'));
exception.source := source;
exception.position := position;
raise exception;
end;
result := position;
end;
function ImmediateBuilder.parseWhile(control: Node; source: TextSource; position: int): int;
var
__code: Code;
condition: Node;
conditionType: &Type;
exception: TextSourceException;
begin
{ условие повтора }
if source.getLexemeKind(position) <> PARENTH_OPENED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
position := parseExpression(control, source, position + 1, false);
condition := control.readComponent(-1);
requiresValue(condition);
conditionType := condition.&type;
if not conditionType.isBoolean() then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-use.expression.repeat-condition'), [
CoObject.create(conditionType), CoObject.create(fldTypeBoolean)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if source.getLexemeKind(position) <> PARENTH_CLOSED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
{ тело цикла }
position := parseControl(control, source, position + 1);
__code := control.parentCode;
__code.moveNode(condition, control.getLength());
__code.createAndPrependNode(control).setData(-1, FCT_JUMP);
result := position;
end;
function ImmediateBuilder.parseWith(control: Node; source: TextSource; position: int): int;
var
exception: TextSourceException;
begin
{ переменные ссылочного типа для быстрого доступа к членам их типов }
if source.getLexemeKind(position) <> PARENTH_OPENED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
inc(position);
repeat
position := parseDeclareWith(control, source, position, false);
case source.getLexemeKind(position) of
PARENTH_CLOSED:
break;
COMMA:
inc(position);
else
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
until false;
{ тело с быстрым доступом к членам типов переменных }
result := parseControl(control, source, position + 1);
end;
function ImmediateBuilder.parseControl(parent: Node; source: TextSource; position: int): int;
var
__code: Code;
control: Node;
exception: TextSourceException;
begin
__code := parent.parentCode;
while (source.getLexemeKind(position) = L_NAME) and (source.getLexemeKind(position + 1) = COLON) do begin
parent := __code.createAndAppendNode(parent).setData(position, FCT_LABEL, CoAnsiString.create(source.getLexemeString(position).toUTF8()));
inc(position, 2);
end;
case source.getLexemeKind(position) of
SEMICOLON: begin
__code.createAndAppendNode(parent).setData(position, FCT_BLOCK);
inc(position);
end;
CURLY_OPENED: begin
control := __code.createAndAppendNode(parent).setData(position, FCT_BLOCK);
inc(position);
position := parseBlock(control, source, position);
end;
FCT_BREAK: begin
control := __code.createAndAppendNode(parent).setData(position, FCT_BREAK, nil);
inc(position);
position := parseBreak(control, source, position);
end;
FCT_CONTINUE: begin
control := __code.createAndAppendNode(parent).setData(position, FCT_CONTINUE, nil);
inc(position);
position := parseContinue(control, source, position);
end;
FCT_DO: begin
control := __code.createAndAppendNode(parent).setData(position, FCT_DO);
inc(position);
position := parseDo(control, source, position);
end;
FCT_FOR: begin
control := __code.createAndAppendNode(parent).setData(position, FCT_FOR);
inc(position);
position := parseFor(control, source, position);
end;
FCT_IF: begin
control := __code.createAndAppendNode(parent).setData(position, FCT_IF);
inc(position);
position := parseIf(control, source, position);
end;
FCT_RETURN: begin
control := __code.createAndAppendNode(parent).setData(position, FCT_RETURN);
inc(position);
position := parseReturn(control, source, position);
end;
FCT_SWITCH: begin
control := __code.createAndAppendNode(parent).setData(position, FCT_SWITCH);
inc(position);
position := parseSwitch(control, source, position);
end;
FCT_SYNCHRONIZED: begin
control := __code.createAndAppendNode(parent).setData(position, FCT_BLOCK);
inc(position);
position := parseSynchronized(control, source, position);
end;
FCT_THROW: begin
control := __code.createAndAppendNode(parent).setData(position, FCT_THROW, nil);
inc(position);
position := parseThrow(control, source, position);
end;
FCT_TRY: begin
control := __code.createAndAppendNode(parent).setData(position, FCT_TRY);
inc(position);
position := parseTry(control, source, position);
end;
FCT_WHILE: begin
control := __code.createAndAppendNode(parent).setData(position, FCT_WHILE);
inc(position);
position := parseWhile(control, source, position);
end;
FCT_WITH: begin
control := __code.createAndAppendNode(parent).setData(position, FCT_BLOCK);
inc(position);
position := parseWith(control, source, position);
end;
else
position := parseDeclareLocal(parent, source, position, true);
if source.getLexemeKind(position) <> SEMICOLON then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.semicolon'));
exception.source := source;
exception.position := position;
raise exception;
end;
inc(position);
end;
result := position;
end;
function ImmediateBuilder.tryParseName(parent: Node; source: TextSource; position: int; const name: AnsiString; parsed: ImmediateBuilderItemHolder): int;
label
break_label0;
var
after: int;
index: int;
child: Node;
__local: Local;
resultWith: Local;
resultItem: TableItem;
enclosingCallable: Callable;
enclosingClassType: ru.malik.elaborarer.avtoo.lang.ClassType;
begin
enclosingCallable := parent.parentCode.parentCallable;
enclosingClassType := enclosingCallable.parentType;
resultItem := nil;
resultWith := nil;
begin
{ поиск среди локальных переменных }
repeat
for index := parent.getLength() - 1 downto 0 do begin
child := parent.readComponent(index);
case child.instruction of
DECLARE_WITH: begin
__local := child.operand1 as Local;
resultItem := (__local.&type as ru.malik.elaborarer.avtoo.lang.ClassType).resolveName(name, enclosingClassType, true);
if resultItem <> nil then begin
resultWith := __local;
goto break_label0;
end;
if name = __local.specialSimpleName then begin
resultItem := __local;
goto break_label0;
end;
end;
DECLARE_LOCAL: begin
__local := child.operand1 as Local;
if name = __local.specialSimpleName then begin
resultItem := __local;
goto break_label0;
end;
end;
end;
end;
parent := parent.parentNode;
until parent = nil;
{ поиск среди аргументов метода }
begin
__local := enclosingCallable.getArgument(name);
if __local <> nil then begin
resultItem := __local;
goto break_label0;
end;
end;
{ поиск среди членов типа }
begin
resultItem := enclosingClassType.resolveName(name, enclosingClassType, true);
if resultItem <> nil then begin
resultWith := enclosingCallable.arguments.thisArgument;
goto break_label0;
end;
end;
{ поиск среди типов и пакетов }
if (name.length <= 0) or (name[1] <> '<') then begin
after := tryParseTypeName(source, position, enclosingClassType, parsed);
if parsed.resultType <> nil then begin
result := after;
exit;
end;
result := tryParsePackageName(source, position, enclosingClassType, parsed);
exit;
end;
end;
break_label0:
parsed.resultWith := resultWith;
parsed.resultItem := resultItem;
result := position + 1;
end;
function ImmediateBuilder.tryParsePackageName(source: TextSource; position: int; enclosing: ClassType; parsed: PackageHolder): int;
var
lastPosition: int;
specialSimpleName: AnsiString;
specialCanonicalName: AnsiString;
lastResult: Package;
resultPack: Package;
begin
if source.getLexemeKind(position) <> L_NAME then begin
parsed.resultPack := nil;
result := position;
exit;
end;
begin
specialSimpleName := source.getLexemeString(position).toUTF8();
inc(position);
{ последние позиция и результат }
lastPosition := position;
lastResult := getPackage(specialSimpleName);
resultPack := lastResult;
{ распознавание канонического имени пакета }
specialCanonicalName := specialSimpleName.copy();
while (source.getLexemeKind(position) = PERIOD) and (source.getLexemeKind(position + 1) = L_NAME) do begin
inc(position);
specialCanonicalName := specialCanonicalName + '.' + source.getLexemeString(position).toUTF8();
inc(position);
resultPack := getPackage(specialCanonicalName);
if resultPack <> nil then begin
lastPosition := position;
lastResult := resultPack;
end;
end;
if resultPack = nil then begin
position := lastPosition;
resultPack := lastResult;
end;
end;
parsed.resultPack := resultPack;
result := position;
end;
function ImmediateBuilder.tryParseClassName(source: TextSource; position: int; enclosing: ClassType; parsed: TypeHolder): int;
label
break_label0;
var
length: int;
specialSimpleName: AnsiString;
specialCanonicalName: AnsiString;
foundTypes: ClassType_Array1d;
resultType: ru.malik.elaborarer.avtoo.lang.ClassType;
begin
if source.getLexemeKind(position) <> L_NAME then begin
parsed.resultType := nil;
result := position;
exit;
end;
begin
specialSimpleName := source.getLexemeString(position).toUTF8();
inc(position);
{ поиск среди типов в исходном коде }
resultType := source.getDeclaredType(specialSimpleName);
if resultType <> nil then goto break_label0;
resultType := source.getImportedType(specialSimpleName);
if resultType <> nil then goto break_label0;
{ поиск в родительском пакете }
resultType := source.owner.getChildType(specialSimpleName) as ru.malik.elaborarer.avtoo.lang.ClassType;
if (resultType <> nil) and resultType.isVisibleFrom(enclosing) then goto break_label0;
{ поиск среди неявно импортированных типов }
foundTypes := source.findImplicitlyImportedTypes(specialSimpleName, enclosing);
length := system.length(foundTypes);
if length > 0 then begin
resultType := foundTypes[0];
if resultType.isVisibleFrom(enclosing) then begin
if length > 1 then resultType := nil;
goto break_label0;
end;
end;
{ поиск в языковом пакете }
resultType := getLanguagePackage().getChildType(specialSimpleName) as ru.malik.elaborarer.avtoo.lang.ClassType;
if (resultType <> nil) and resultType.isVisibleFrom(enclosing) then goto break_label0;
{ распознавание канонического имени типа }
specialCanonicalName := specialSimpleName.copy();
while source.getLexemeKind(position) = PERIOD do begin
inc(position);
if source.getLexemeKind(position) <> L_NAME then begin
resultType := nil;
goto break_label0;
end;
specialCanonicalName := specialCanonicalName + '.' + source.getLexemeString(position).toUTF8();
inc(position);
resultType := getClassType(specialCanonicalName);
if resultType <> nil then goto break_label0;
end;
resultType := nil;
end;
break_label0:
if not parsed.helpersAllowed and (resultType <> nil) and resultType.isHelper() then resultType := nil;
parsed.resultType := resultType;
result := position;
end;
function ImmediateBuilder.tryParseTypeName(source: TextSource; position: int; enclosing: ClassType; parsed: TypeHolder): int;
var
kind: int;
dimCount: int;
resultType: &Type;
begin
kind := source.getLexemeKind(position);
if kind = TYP_VOID then begin
parsed.resultType := getPrimitiveType(TYP_VOID);
result := position + 1;
exit;
end;
if (kind > TYP_VOID) and (kind < TYP_VOID + PRIMITIVES_LENGTH) and isPrimitiveKind(kind) then begin
inc(position);
resultType := getPrimitiveType(kind);
end else begin
position := tryParseClassName(source, position, enclosing, parsed);
resultType := parsed.resultType;
if (resultType = nil) or resultType.isHelper() then begin
parsed.resultType := resultType;
result := position;
exit;
end;
end;
dimCount := 0;
while (dimCount < LIMIT_DIMENSIONS_COUNT) and (source.getLexemeKind(position) = BRACKET_OPENED) and (source.getLexemeKind(position + 1) = BRACKET_CLOSED) do begin
resultType := acquireArrayType(resultType);
inc(position, 2);
inc(dimCount);
end;
parsed.resultType := resultType;
result := position;
end;
function ImmediateBuilder.appendIncrementCode(parent: Node; argumentType: PrimitiveType; isUseIncrement: boolean): Node;
var
raw: byte;
__code: Code;
typeInt: &Type;
delta: Constant;
resultNode: Node;
begin
__code := parent.parentCode;
if isUseIncrement then begin
raw := 1;
end else begin
raw := -1;
end;
case argumentType.kind of
TYP_REAL: begin
delta := fldConstantFactory.createReal(raw);
resultNode := __code.createAndAppendNode(parent).setData(-1, argumentType, O_SCAL_ADD, argumentType);
__code.createAndAppendNode(resultNode).setData(-1, argumentType, LOAD_CONST, delta);
end;
TYP_CHAR: begin
typeInt := fldTypeInt;
delta := fldConstantFactory.createInt(raw);
resultNode := __code.createAndAppendNode(parent).setData(-1, argumentType, CAST_TO, argumentType, typeInt);
resultNode := __code.createAndAppendNode(resultNode).setData(-1, typeInt, O_SCAL_ADD, typeInt);
__code.createAndAppendNode(resultNode).setData(-1, typeInt, LOAD_CONST, delta);
end;
else
delta := fldConstantFactory.createByte(raw).castTo(argumentType);
resultNode := __code.createAndAppendNode(parent).setData(-1, argumentType, O_VECT_ADD, argumentType);
__code.createAndAppendNode(resultNode).setData(-1, argumentType, LOAD_CONST, delta);
end;
result := resultNode;
end;
function ImmediateBuilder.getAdditionalOperand(operand: int; locals: HashtableOfAnsiStringToLocal; constants: ObjectArray; index: int): TableItem;
var
name: AnsiString;
begin
case operand of
OPERAND_LOCAL: begin
if index <= 0 then begin
name := SPECNAME_THIS;
end else begin
name := (constants.readComponent(index) as CoUnicodeString).asAnsiString();
end;
result := locals[name];
end;
OPERAND_GLOBAL: begin
result := (constants.readComponent(index) as FieldElement).getItem();
end;
else
result := nil;
end;
end;
function ImmediateBuilder.getAdditionalConstant(constants: ObjectArray; index: int): Constant;
var
element: TObject;
begin
element := constants.readComponent(index);
if element is RecompilableElement then begin
result := fldConstantFactory.createFrom(RecompilableElement(element).getItem());
exit;
end;
result := fldConstantFactory.createFrom(element);
end;
function ImmediateBuilder.getItemHolder(): ImmediateBuilderItemHolder;
var
threadItemHolder: CompilerParallelWorker;
begin
threadItemHolder := fldThreadItemHolder;
if threadItemHolder = nil then begin
result := fldGlobalItemHolder;
exit;
end;
result := threadItemHolder.threadObject() as ImmediateBuilderItemHolder;
end;
procedure ImmediateBuilder.readCallableBody(__callable: Callable);
var
hasBooleanJump: boolean;
value: int;
store: int;
index: int;
length: int;
__type: int;
__name: int;
method: int;
cindex: int;
blabel: int;
elabel: int;
flabel: int;
tlabel: int;
jindex: int;
jlabel: int;
jvalue: int;
jlength: int;
dlength: int;
llength: int;
encoded: int;
decoded: int;
operand: int;
__local: int;
__global: int;
capacity: int;
fieldoid: int;
lineIndex: int;
debugIndex: int;
labelIndex: int;
jcase: int2;
localName: AnsiString;
jmap: int2_Array2d;
jbuf: int2_Array2d;
jumps: int2_Array1d;
debugs: Node_Array1d;
labels: Node_Array1d;
buffer: Node_Array1d;
root: Node;
__next: Node;
__node: Node;
__code: Code;
argument: Local;
element: TObject;
localType: &Type;
typeObject: &Type;
operandC: Constant;
operand1: TableItem;
operand2: TableItem;
thisArgument: Local;
source: BinarySource;
constants: ObjectVector;
factory: ConstantFactory;
arguments: ArgumentArray;
primLocals: HashtableOfAnsiStringToLocal;
refsLocals: HashtableOfAnsiStringToLocal;
exception: BinarySourceException;
begin
__code := __callable.code;
source := BinarySource(Lang.cast(__callable.source, BinarySource));
factory := fldConstantFactory;
constants := source.readComponent(1) as ObjectVector;
with source.chunks.readComponent(__callable.declarationPosition + 1) do if (&type = CHUNK_CODE) and (__code <> nil) then begin
{ чтение аргументов и локальных переменных }
primLocals := nil;
refsLocals := nil;
try
primLocals := HashtableOfAnsiStringToLocal.create();
refsLocals := HashtableOfAnsiStringToLocal.create();
arguments := __callable.arguments;
thisArgument := arguments.thisArgument;
if thisArgument <> nil then begin
refsLocals[SPECNAME_THIS] := thisArgument;
end;
length := arguments.getLength();
for index := 0 to length - 1 do begin
argument := arguments.readComponent(index);
if argument.&type.isPrimitive() then begin
primLocals[argument.specialSimpleName] := argument;
end else begin
refsLocals[argument.specialSimpleName] := argument;
end;
end;
length := readUnsignedShort();
for index := 0 to length - 1 do begin
__type := readInt();
__name := readInt();
localName := (constants.readComponent(__name) as CoUnicodeString).asAnsiString();
localType := (constants.readComponent(__type) as TypeElement).getItem();
argument := __code.createLocal(false, localType, localName, nil, -1);
if localType.isPrimitive() then begin
primLocals[argument.specialSimpleName] := argument;
end else begin
refsLocals[argument.specialSimpleName] := argument;
end;
end;
{ чтение перекомпилируемого кода }
dlength := $0f;
llength := $0f;
jmap := VArray.newInt2_2d($0f);
debugs := Node_Array1d(&Array.newTObject1d(dlength));
labels := Node_Array1d(&Array.newTObject1d(llength));
typeObject := fldTypeObject;
root := __code.root;
cindex := 0;
while available() > 0 do begin
if cindex = system.length(jmap) then begin
jbuf := VArray.newInt2_2d((cindex shl 1) or 1);
&Array.copyArrays(jmap, 0, jbuf, 0, cindex);
jmap := jbuf;
end;
lineIndex := -1;
labelIndex := -1;
debugIndex := -1;
encoded := readUnsignedShort();
if not isInstruction(encoded) and not decodeDeclareLabel(encoded) then begin
if isLongNumber(encoded) then encoded := (encoded shl $10) + readUnsignedShort();
lineIndex := decodeDeclareNumber(encoded);
encoded := readUnsignedShort();
end;
if not isInstruction(encoded) and decodeDeclareLabel(encoded) then begin
if isLongNumber(encoded) then encoded := (encoded shl $10) + readUnsignedShort();
decoded := decodeDeclareNumber(encoded);
if decoded >= 0 then begin
labelIndex := decoded;
end else begin
debugIndex := not decoded;
if __code.createDebugIndex(lineIndex) <> debugIndex then begin
exception := BinarySourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'binary.invalid-debug-label-index'));
exception.source := source;
exception.offset := dataOffsetToSourceOffset(position);
raise exception;
end;
end;
encoded := readUnsignedShort();
end;
if not isInstruction(encoded) then begin
exception := BinarySourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'binary.expected.instruction-code'));
exception.source := source;
exception.offset := dataOffsetToSourceOffset(position);
raise exception;
end;
hasBooleanJump := false;
__node := nil;
case encoded shr 8 of
INST_METHOD_ENTER shr 8: begin
operand := readIndex();
__node := __code.createAndAppendNode(root).setData(-1, METHOD_ENTER, CoInt.create(operand));
end;
INST_SWAP shr 8: begin
decoded := decodeType(encoded);
if decoded = TYP_REF then begin
operand1 := typeObject;
end else begin
operand1 := getPrimitiveType(decoded);
end;
__node := __code.createAndAppendNode(root).setData(-1, nil, SWAP, operand1);
end;
INST_BOUND shr 8: begin
__node := __code.createAndAppendNode(root).setData(-1, FCT_BOUND);
end;
INST_THROW shr 8: begin
__type := readIndex();
operand1 := (constants.readComponent(__type) as TypeElement).getItem();
__node := __code.createAndAppendNode(root).setData(-1, FCT_THROW, operand1);
end;
INST_LOAD_STATIC shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
__global := readIndex();
operand1 := (constants.readComponent(__global) as FieldElement).getItem();
__node := __code.createAndAppendNode(root).setData(-1, nil, LOAD_STATIC, operand1);
end;
INST_LOAD_STATICW shr 8: begin
__global := readIndex();
operand1 := (constants.readComponent(__global) as FieldElement).getItem();
__node := __code.createAndAppendNode(root).setData(-1, nil, LOAD_STATIC, operand1);
__node.weak := true;
end;
INST_LOAD_LOCAL shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
__local := readIndex();
decoded := decodeType(encoded);
if decoded = TYP_REF then begin
operand2 := typeObject;
end else begin
operand2 := getPrimitiveType(decoded);
end;
if __local <= 0 then begin
operand1 := thisArgument;
end else
if decoded = TYP_REF then begin
operand1 := refsLocals[(constants.readComponent(__local) as CoUnicodeString).asAnsiString()];
end else begin
operand1 := primLocals[(constants.readComponent(__local) as CoUnicodeString).asAnsiString()];
end;
__node := __code.createAndAppendNode(root).setData(-1, nil, LOAD_LOCAL, operand1, operand2);
end;
INST_LOAD_LOCALW shr 8: begin
__local := readIndex();
if __local <= 0 then begin
operand1 := thisArgument;
end else begin
operand1 := refsLocals[(constants.readComponent(__local) as CoUnicodeString).asAnsiString()];
end;
__node := __code.createAndAppendNode(root).setData(-1, nil, LOAD_LOCAL, operand1, typeObject);
__node.weak := true;
end;
INST_LOAD_CONST shr 8,
INST_LOAD_CONSTW shr 8: begin
value := readIndex();
element := constants.readComponent(value);
if element is RecompilableElement then begin
operandC := factory.createFrom(RecompilableElement(element).getItem());
end else begin
operandC := factory.createFrom(element);
end;
if operandC.isClass() then (operandC.asObject() as ru.malik.elaborarer.avtoo.lang.&Type).makeCompilable();
__node := __code.createAndAppendNode(root).setData(-1, nil, LOAD_CONST, operandC);
if (encoded and FLAG_WEAK) <> 0 then __node.weak := true;
end;
INST_READ_ELEMENT shr 8: begin
operand1 := getPrimitiveType(decodeType(encoded));
__node := __code.createAndAppendNode(root).setData(-1, nil, READ_ELEMENT, operand1);
end;
INST_READ_ELEMENTI shr 8: begin
operand1 := getPrimitiveType(decodeType(encoded));
operandC := factory.createInt(decodeVectorIndex(encoded));
__node := __code.createAndAppendNode(root).setData(-1, nil, READ_ELEMENT, operand1, operandC);
end;
INST_READ_COMPONENT shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
decoded := decodeType(encoded);
if decoded = TYP_REF then begin
operand1 := typeObject;
end else begin
operand1 := getPrimitiveType(decoded);
end;
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, READ_COMPONENT, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, READ_COMPONENT, operand1, operand2);
end;
end;
INST_READ_FIELD shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
fieldoid := readIndex();
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := (constants.readComponent(fieldoid) as FieldElement).getItem();
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, READ_FIELD, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, refsLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, READ_FIELD, operand1, operand2);
end;
end;
INST_READ_SPECIAL shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
fieldoid := readIndex();
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := (constants.readComponent(fieldoid) as PropertyElement).getItem();
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, READ_SPECIAL, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, refsLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, READ_SPECIAL, operand1, operand2);
end;
end;
INST_READ_PROPERTY shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
fieldoid := readIndex();
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := (constants.readComponent(fieldoid) as PropertyElement).getItem();
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, READ_PROPERTY, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, refsLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, READ_PROPERTY, operand1, operand2);
end;
end;
INST_STORE_STATIC shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
__global := readIndex();
operand1 := (constants.readComponent(__global) as FieldElement).getItem();
__node := __code.createAndAppendNode(root).setData(-1, nil, STORE_STATIC, operand1);
end;
INST_STORE_STATIC_NULL shr 8: begin
__global := readIndex();
operand1 := (constants.readComponent(__global) as FieldElement).getItem();
__node := __code.createAndAppendNode(root).setData(-1, nil, STORE_STATIC, operand1, factory.createNull());
end;
INST_STORE_STATIC_SHORT shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
__global := readIndex();
value := readShort();
operand1 := (constants.readComponent(__global) as FieldElement).getItem();
if Field(operand1).&type.isBoolean() then begin
operandC := factory.createBoolean(value <> 0);
end else begin
operandC := factory.createInt(value);
end;
__node := __code.createAndAppendNode(root).setData(-1, nil, STORE_STATIC, operand1, operandC);
end;
INST_STORE_STATIC_INT shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
__global := readIndex();
value := readInt();
operand1 := (constants.readComponent(__global) as FieldElement).getItem();
if Field(operand1).&type.isBoolean() then begin
operandC := factory.createBoolean(value <> 0);
end else begin
operandC := factory.createInt(value);
end;
__node := __code.createAndAppendNode(root).setData(-1, nil, STORE_STATIC, operand1, operandC);
end;
INST_STORE_LOCAL shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
store := decodeStore(encoded) - STORE_NORMAL;
__local := readIndex();
decoded := decodeType(encoded);
if decoded = TYP_REF then begin
operand2 := typeObject;
end else begin
operand2 := getPrimitiveType(decoded);
end;
if __local <= 0 then begin
operand1 := thisArgument;
end else
if decoded = TYP_REF then begin
operand1 := refsLocals[(constants.readComponent(__local) as CoUnicodeString).asAnsiString()];
end else begin
operand1 := primLocals[(constants.readComponent(__local) as CoUnicodeString).asAnsiString()];
end;
__node := __code.createAndAppendNode(root).setData(-1, nil, STORE_LOCAL + store, operand1, operand2);
end;
INST_STORE_LOCAL_NULL shr 8: begin
store := decodeStore(encoded) - STORE_NORMAL;
__local := readIndex();
if __local <= 0 then begin
operand1 := thisArgument;
end else begin
operand1 := refsLocals[(constants.readComponent(__local) as CoUnicodeString).asAnsiString()];
end;
__node := __code.createAndAppendNode(root).setData(-1, nil, STORE_LOCAL + store, operand1, factory.createNull());
end;
INST_STORE_LOCAL_SHORT shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
store := decodeStore(encoded) - STORE_NORMAL;
__local := readIndex();
value := readShort();
if __local <= 0 then begin
operand1 := thisArgument;
end else begin
operand1 := primLocals[(constants.readComponent(__local) as CoUnicodeString).asAnsiString()];
end;
__node := __code.createAndAppendNode(root).setData(-1, nil, STORE_LOCAL + store, operand1, factory.createInt(value));
end;
INST_STORE_LOCAL_INT shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
store := decodeStore(encoded) - STORE_NORMAL;
__local := readIndex();
value := readInt();
if __local <= 0 then begin
operand1 := thisArgument;
end else begin
operand1 := primLocals[(constants.readComponent(__local) as CoUnicodeString).asAnsiString()];
end;
__node := __code.createAndAppendNode(root).setData(-1, nil, STORE_LOCAL + store, operand1, factory.createInt(value));
end;
INST_INC_PRED_LOAD_LOCAL shr 8: begin
__local := readIndex();
if __local <= 0 then begin
operand1 := thisArgument;
end else begin
operand1 := primLocals[(constants.readComponent(__local) as CoUnicodeString).asAnsiString()];
end;
operand2 := getPrimitiveType(decodeType(encoded));
__node := __code.createAndAppendNode(root).setData(-1, nil, INC_PRED_LOAD_LOCAL, operand1, operand2);
end;
INST_INC_POST_LOAD_LOCAL shr 8: begin
__local := readIndex();
if __local <= 0 then begin
operand1 := thisArgument;
end else begin
operand1 := primLocals[(constants.readComponent(__local) as CoUnicodeString).asAnsiString()];
end;
operand2 := getPrimitiveType(decodeType(encoded));
__node := __code.createAndAppendNode(root).setData(-1, nil, INC_POST_LOAD_LOCAL, operand1, operand2);
end;
INST_DEC_PRED_LOAD_LOCAL shr 8: begin
__local := readIndex();
if __local <= 0 then begin
operand1 := thisArgument;
end else begin
operand1 := primLocals[(constants.readComponent(__local) as CoUnicodeString).asAnsiString()];
end;
operand2 := getPrimitiveType(decodeType(encoded));
__node := __code.createAndAppendNode(root).setData(-1, nil, DEC_PRED_LOAD_LOCAL, operand1, operand2);
end;
INST_DEC_POST_LOAD_LOCAL shr 8: begin
__local := readIndex();
if __local <= 0 then begin
operand1 := thisArgument;
end else begin
operand1 := primLocals[(constants.readComponent(__local) as CoUnicodeString).asAnsiString()];
end;
operand2 := getPrimitiveType(decodeType(encoded));
__node := __code.createAndAppendNode(root).setData(-1, nil, DEC_POST_LOAD_LOCAL, operand1, operand2);
end;
INST_WRITE_COMPONENT shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
decoded := decodeType(encoded);
if decoded = TYP_REF then begin
operand1 := typeObject;
end else begin
operand1 := getPrimitiveType(decoded);
end;
__node := __code.createAndAppendNode(root).setData(-1, nil, WRITE_COMPONENT, operand1);
end;
INST_WRITE_FIELD shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
fieldoid := readIndex();
operand1 := (constants.readComponent(fieldoid) as FieldElement).getItem();
__node := __code.createAndAppendNode(root).setData(-1, nil, WRITE_FIELD, operand1);
end;
INST_WRITE_SPECIAL shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
fieldoid := readIndex();
operand1 := (constants.readComponent(fieldoid) as PropertyElement).getItem();
__node := __code.createAndAppendNode(root).setData(-1, nil, WRITE_SPECIAL, operand1);
end;
INST_WRITE_PROPERTY shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
fieldoid := readIndex();
operand1 := (constants.readComponent(fieldoid) as PropertyElement).getItem();
__node := __code.createAndAppendNode(root).setData(-1, nil, WRITE_PROPERTY, operand1);
end;
INST_SWITCH_TABLE shr 8: begin
jvalue := readInt();
jlength := readIndex();
jumps := VArray.newInt2_1d(jlength + 1);
for jindex := 0 to jlength - 1 do begin
jlabel := readLabel();
jumps[jindex] := Vector.newInt2(jlabel, jvalue);
inc(jvalue);
end;
begin
jlabel := readLabel();
jumps[jlength] := jlabel;
end;
jmap[cindex] := jumps;
__node := __code.createAndAppendNode(root).setData(-1, FCT_BRANCH);
end;
INST_SWITCH_LOOKUP shr 8: begin
jlength := readIndex();
jumps := VArray.newInt2_1d(jlength + 1);
for jindex := 0 to jlength - 1 do begin
jvalue := readInt();
jlabel := readLabel();
jumps[jindex] := Vector.newInt2(jlabel, jvalue);
end;
begin
jlabel := readLabel();
jumps[jlength] := jlabel;
end;
jmap[cindex] := jumps;
__node := __code.createAndAppendNode(root).setData(-1, FCT_BRANCH);
end;
INST_JUMP shr 8: begin
jlabel := readLabel();
jmap[cindex] := [ jlabel ];
__node := __code.createAndAppendNode(root).setData(-1, FCT_JUMP);
end;
INST_LOAD_INTERRUPT shr 8: begin
method := readIndex();
operand1 := (constants.readComponent(method) as CallableElement).getItem();
__node := __code.createAndAppendNode(root).setData(-1, nil, LOAD_INTERRUPT, operand1);
end;
INST_LOAD_CONST_BYTE shr 8: begin
__node := __code.createAndAppendNode(root).setData(-1, nil, LOAD_CONST, factory.createInt(byte(encoded)));
end;
INST_LOAD_CONST_NULL shr 8: begin
__node := __code.createAndAppendNode(root).setData(-1, nil, LOAD_CONST, factory.createNull());
end;
INST_LOAD_CONST_SHORT shr 8: begin
value := readShort();
__node := __code.createAndAppendNode(root).setData(-1, nil, LOAD_CONST, factory.createInt(value));
end;
INST_LOAD_CONST_INT shr 8: begin
value := readInt();
__node := __code.createAndAppendNode(root).setData(-1, nil, LOAD_CONST, factory.createInt(value));
end;
INST_REF_EQ shr 8,
INST_REF_EQW shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, REF_EQ, operandC);
end else begin
operand1 := getAdditionalOperand(operand, refsLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, REF_EQ, operand1);
end;
if (encoded and FLAG_WEAK) <> 0 then __node.weak := true;
end;
INST_REF_NE shr 8,
INST_REF_NEW shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, REF_NE, operandC);
end else begin
operand1 := getAdditionalOperand(operand, refsLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, REF_NE, operand1);
end;
if (encoded and FLAG_WEAK) <> 0 then __node.weak := true;
end;
INST_REF_IS_NULL shr 8,
INST_REF_IS_NULLW shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
__node := __code.createAndAppendNode(root).setData(-1, nil, REF_IS_NULL);
if (encoded and FLAG_WEAK) <> 0 then __node.weak := true;
end;
INST_REF_IS_OBJECT shr 8,
INST_REF_IS_OBJECTW shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
__node := __code.createAndAppendNode(root).setData(-1, nil, REF_IS_OBJECT);
if (encoded and FLAG_WEAK) <> 0 then __node.weak := true;
end;
INST_CLINIT_TRY_LOCK shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
__type := readIndex();
operand1 := (constants.readComponent(__type) as TypeElement).getItem();
ru.malik.elaborarer.avtoo.lang.&Type(operand1).makeCompilable();
__node := __code.createAndAppendNode(root).setData(-1, nil, CLINIT_TRY_LOCK, operand1);
end;
INST_CLINIT_UNLOCK shr 8: begin
__type := readIndex();
operand1 := (constants.readComponent(__type) as TypeElement).getItem();
ru.malik.elaborarer.avtoo.lang.&Type(operand1).makeCompilable();
__node := __code.createAndAppendNode(root).setData(-1, nil, CLINIT_UNLOCK, operand1);
end;
INST_MONITOR_ENTER shr 8: begin
__node := __code.createAndAppendNode(root).setData(-1, MONITOR_ENTER);
end;
INST_MONITOR_LEAVE shr 8: begin
__node := __code.createAndAppendNode(root).setData(-1, MONITOR_LEAVE);
end;
INST_FINALLY_ENTER shr 8: begin
__node := __code.createAndAppendNode(root).setData(-1, FINALLY_ENTER);
end;
INST_FINALLY_LEAVE shr 8: begin
__node := __code.createAndAppendNode(root).setData(-1, FINALLY_LEAVE);
end;
INST_NEW_ARRAY shr 8: begin
__type := readIndex();
length := readInt();
operand1 := (constants.readComponent(__type) as TypeElement).getItem();
ru.malik.elaborarer.avtoo.lang.&Type(operand1).makeCompilable();
__node := __code.createAndAppendNode(root).setData(-1, nil, NEW_ARRAY, operand1, factory.createInt(length));
end;
INST_INVOKE_FINALLY shr 8: begin
tlabel := readLabel();
jmap[cindex] := [ tlabel ];
__node := __code.createAndAppendNode(root).setData(-1, INVOKE_FINALLY, nil);
end;
INST_INVOKE_STATIC shr 8,
INST_INVOKE_STATICD shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
method := readIndex();
operand1 := (constants.readComponent(method) as CallableElement).getItem();
__node := __code.createAndAppendNode(root).setData(-1, nil, INVOKE_STATIC, operand1);
if (encoded and FLAG_DISCARD) <> 0 then __node.weak := true;
end;
INST_INVOKE_SPECIAL shr 8,
INST_INVOKE_SPECIALD shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
method := readIndex();
operand1 := (constants.readComponent(method) as CallableElement).getItem();
__node := __code.createAndAppendNode(root).setData(-1, nil, INVOKE_SPECIAL, operand1);
if (encoded and FLAG_DISCARD) <> 0 then __node.weak := true;
end;
INST_INVOKE_VIRTUAL shr 8,
INST_INVOKE_VIRTUALD shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
method := readIndex();
operand1 := (constants.readComponent(method) as CallableElement).getItem();
__node := __code.createAndAppendNode(root).setData(-1, nil, INVOKE_VIRTUAL, operand1);
if (encoded and FLAG_DISCARD) <> 0 then __node.weak := true;
end;
INST_INVOKE_SERVICE shr 8,
INST_INVOKE_SERVICED shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
method := readIndex();
operand1 := (constants.readComponent(method) as CallableElement).getItem();
__node := __code.createAndAppendNode(root).setData(-1, nil, INVOKE_SERVICE, operand1);
if (encoded and FLAG_DISCARD) <> 0 then __node.weak := true;
end;
INST_VECT_DIV shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_DIV, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_DIV, operand1, operand2);
end;
end;
INST_VECT_PCK shr 8: begin
operand1 := getPrimitiveType(decodeType(encoded));
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_PCK, operand1);
end;
INST_VECT_LUP shr 8: begin
operand1 := getPrimitiveType(decodeType(encoded));
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_LUP, operand1);
end;
INST_VECT_UUP shr 8: begin
operand1 := getPrimitiveType(decodeType(encoded));
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_UUP, operand1);
end;
INST_VECT_MUL shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_MUL, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_MUL, operand1, operand2);
end;
end;
INST_VECT_SHL shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_SHL, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_SHL, operand1, operand2);
end;
end;
INST_VECT_SHR shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_SHR, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_SHR, operand1, operand2);
end;
end;
INST_VECT_SHRU shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_SHRU, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_SHRU, operand1, operand2);
end;
end;
INST_VECT_ADD shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_ADD, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_ADD, operand1, operand2);
end;
end;
INST_VECT_SUB shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_SUB, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_SUB, operand1, operand2);
end;
end;
INST_VECT_EQ shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_EQ, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_EQ, operand1, operand2);
end;
end;
INST_VECT_NE shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_NE, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_NE, operand1, operand2);
end;
end;
INST_VECT_GT shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_GT, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_GT, operand1, operand2);
end;
end;
INST_VECT_GE shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_GE, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_GE, operand1, operand2);
end;
end;
INST_VECT_LT shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_LT, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_LT, operand1, operand2);
end;
end;
INST_VECT_LE shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_LE, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_LE, operand1, operand2);
end;
end;
INST_SCAL_DIV shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_DIV, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_DIV, operand1, operand2);
end;
end;
INST_SCAL_DIVU shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_DIVU, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_DIVU, operand1, operand2);
end;
end;
INST_SCAL_REM shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_REM, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_REM, operand1, operand2);
end;
end;
INST_SCAL_REMU shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_REMU, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_REMU, operand1, operand2);
end;
end;
INST_SCAL_MUL shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_MUL, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_MUL, operand1, operand2);
end;
end;
INST_SCAL_SHL shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_SHL, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_SHL, operand1, operand2);
end;
end;
INST_SCAL_SHR shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_SHR, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_SHR, operand1, operand2);
end;
end;
INST_SCAL_SHRU shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_SHRU, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_SHRU, operand1, operand2);
end;
end;
INST_SCAL_ADD shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_ADD, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_ADD, operand1, operand2);
end;
end;
INST_SCAL_SUB shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_SUB, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_SUB, operand1, operand2);
end;
end;
INST_SCAL_EQ shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_EQ, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_EQ, operand1, operand2);
end;
end;
INST_SCAL_NE shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_NE, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_NE, operand1, operand2);
end;
end;
INST_SCAL_GT shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_GT, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_GT, operand1, operand2);
end;
end;
INST_SCAL_GE shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_GE, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_GE, operand1, operand2);
end;
end;
INST_SCAL_LT shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_LT, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_LT, operand1, operand2);
end;
end;
INST_SCAL_LE shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_LE, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_LE, operand1, operand2);
end;
end;
INST_VECT_NEG shr 8: begin
operand1 := getPrimitiveType(decodeType(encoded));
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_NEG, operand1);
end;
INST_CAST_TO shr 8: begin
__type := readIndex();
operand1 := (constants.readComponent(__type) as TypeElement).getItem();
decoded := decodeType(encoded);
if decoded = TYP_REF then begin
operand2 := typeObject;
end else begin
operand2 := getPrimitiveType(decoded);
end;
ru.malik.elaborarer.avtoo.lang.&Type(operand1).makeCompilable();
__node := __code.createAndAppendNode(root).setData(-1, nil, CAST_TO, operand1, operand2);
end;
INST_INC_LOCAL shr 8: begin
__local := readIndex();
if __local <= 0 then begin
operand1 := thisArgument;
end else begin
operand1 := primLocals[(constants.readComponent(__local) as CoUnicodeString).asAnsiString()];
end;
operand2 := getPrimitiveType(decodeType(encoded));
__node := __code.createAndAppendNode(root).setData(-1, nil, INC_LOCAL, operand1, operand2);
end;
INST_DEC_LOCAL shr 8: begin
__local := readIndex();
if __local <= 0 then begin
operand1 := thisArgument;
end else begin
operand1 := primLocals[(constants.readComponent(__local) as CoUnicodeString).asAnsiString()];
end;
operand2 := getPrimitiveType(decodeType(encoded));
__node := __code.createAndAppendNode(root).setData(-1, nil, DEC_LOCAL, operand1, operand2);
end;
INST_BIT_NOT shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
operand1 := getPrimitiveType(decodeType(encoded));
__node := __code.createAndAppendNode(root).setData(-1, nil, O_BIT_NOT, operand1);
end;
INST_BIT_AND shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_BIT_AND, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_BIT_AND, operand1, operand2);
end;
end;
INST_BIT_OR shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_BIT_OR, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_BIT_OR, operand1, operand2);
end;
end;
INST_BIT_XOR shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_BIT_XOR, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_BIT_XOR, operand1, operand2);
end;
end;
INST_DUP1 shr 8: begin
decoded := decodeType(encoded);
if decoded = TYP_REF then begin
operand1 := typeObject;
end else begin
operand1 := getPrimitiveType(decoded);
end;
__node := __code.createAndAppendNode(root).setData(-1, nil, DUP1, operand1);
end;
INST_DUP2 shr 8: begin
decoded := decodeType(encoded);
if decoded = TYP_REF then begin
operand1 := typeObject;
end else begin
operand1 := getPrimitiveType(decoded);
end;
__node := __code.createAndAppendNode(root).setData(-1, nil, DUP2, operand1);
end;
INST_VECT_HMUL shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_HMUL, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_HMUL, operand1, operand2);
end;
end;
INST_VECT_HMULU shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_HMULU, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_HMULU, operand1, operand2);
end;
end;
INST_VECT_SADD shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_SADD, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_SADD, operand1, operand2);
end;
end;
INST_VECT_SADDU shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_SADDU, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_SADDU, operand1, operand2);
end;
end;
INST_VECT_SSUB shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_SSUB, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_SSUB, operand1, operand2);
end;
end;
INST_VECT_SSUBU shr 8: begin
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_SSUBU, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, O_VECT_SSUBU, operand1, operand2);
end;
end;
INST_SCAL_NEG shr 8: begin
operand1 := getPrimitiveType(decodeType(encoded));
__node := __code.createAndAppendNode(root).setData(-1, nil, O_SCAL_NEG, operand1);
end;
INST_INSTANCE_OF shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
__type := readIndex();
operand1 := (constants.readComponent(__type) as TypeElement).getItem();
ru.malik.elaborarer.avtoo.lang.&Type(operand1).makeCompilable();
__node := __code.createAndAppendNode(root).setData(-1, nil, EXP_INSTANCEOF, operand1);
end;
INST_TEST_EQZ shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, TEST_EQZ, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, TEST_EQZ, operand1, operand2);
end;
end;
INST_TEST_NEZ shr 8: begin
hasBooleanJump := (encoded and FLAG_BOOLEAN_JUMP) <> 0;
operand := decodeOperand(encoded);
if operand = OPERAND_NONE then begin
index := -1;
end else begin
index := readIndex();
end;
operand1 := getPrimitiveType(decodeType(encoded));
if operand = OPERAND_CONSTANT then begin
operandC := getAdditionalConstant(constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, TEST_NEZ, operand1, operandC);
end else begin
operand2 := getAdditionalOperand(operand, primLocals, constants, index);
__node := __code.createAndAppendNode(root).setData(-1, nil, TEST_NEZ, operand1, operand2);
end;
end;
INST_NEW_VECTOR shr 8: begin
operand1 := getPrimitiveType(decodeType(encoded));
__node := __code.createAndAppendNode(root).setData(-1, nil, NEW_VECTOR, operand1);
end;
INST_NEW_INSTANCE shr 8: begin
__type := readIndex();
operand1 := (constants.readComponent(__type) as TypeElement).getItem();
ru.malik.elaborarer.avtoo.lang.&Type(operand1).makeCompilable();
__node := __code.createAndAppendNode(root).setData(-1, nil, NEW_INSTANCE, operand1);
end;
INST_NEW_ARRAY_MONO shr 8: begin
__type := readIndex();
operand1 := (constants.readComponent(__type) as TypeElement).getItem();
ru.malik.elaborarer.avtoo.lang.&Type(operand1).makeCompilable();
__node := __code.createAndAppendNode(root).setData(-1, nil, NEW_ARRAY_MONO, operand1);
end;
INST_NEW_ARRAY_MULTI shr 8: begin
__type := readIndex();
operand1 := (constants.readComponent(__type) as TypeElement).getItem();
ru.malik.elaborarer.avtoo.lang.&Type(operand1).makeCompilable();
__node := __code.createAndAppendNode(root).setData(-1, nil, NEW_ARRAY_MULTI, operand1);
end;
INST_DUP1X1 shr 8: begin
decoded := decodeType(encoded);
if decoded = TYP_REF then begin
operand1 := typeObject;
end else begin
operand1 := getPrimitiveType(decoded);
end;
__node := __code.createAndAppendNode(root).setData(-1, nil, DUP1X1, operand1);
end;
INST_DUP1X2 shr 8: begin
decoded := decodeType(encoded);
if decoded = TYP_REF then begin
operand1 := typeObject;
end else begin
operand1 := getPrimitiveType(decoded);
end;
__node := __code.createAndAppendNode(root).setData(-1, nil, DUP1X2, operand1);
end;
INST_METHOD_LEAVE shr 8: begin
__node := __code.createAndAppendNode(root).setData(-1, METHOD_LEAVE);
end;
INST_EXCEPT_ENTER shr 8: begin
__node := __code.createAndAppendNode(root).setData(-1, EXCEPT_ENTER);
end;
INST_EXCEPT_TRY shr 8: begin
blabel := readLabel();
elabel := readLabel();
jmap[cindex] := [ blabel, elabel ];
__node := __code.createAndAppendNode(root).setData(-1, EXCEPT_TRY, nil, nil);
end;
INST_EXCEPT_CATCH shr 8: begin
blabel := readLabel();
__type := readIndex();
operand2 := (constants.readComponent(__type) as TypeElement).getItem();
jmap[cindex] := [ blabel ];
__node := __code.createAndAppendNode(root).setData(-1, EXCEPT_CATCH, nil, operand2);
end;
INST_EXCEPT_FINALLY shr 8: begin
blabel := readLabel();
jmap[cindex] := [ blabel ];
__node := __code.createAndAppendNode(root).setData(-1, EXCEPT_FINALLY, nil);
end;
INST_EXCEPT_LEAVE shr 8: begin
__node := __code.createAndAppendNode(root).setData(-1, EXCEPT_LEAVE);
end;
end;
if hasBooleanJump then begin
tlabel := readLabel();
flabel := readLabel();
jmap[cindex] := [ flabel, tlabel ];
end;
__node.location := Vector.newInt2(lineIndex, -1);
__node.debugIndex := debugIndex;
if debugIndex >= 0 then begin
if debugIndex >= dlength then begin
capacity := getBestArrayCapacity(debugIndex + 1);
buffer := Node_Array1d(&Array.newTObject1d(capacity));
&Array.copyObjects(debugs, 0, buffer, 0, dlength);
debugs := buffer;
dlength := capacity;
end;
debugs[debugIndex] := __node;
end;
__node.labelIndex := labelIndex;
if labelIndex >= 0 then begin
if labelIndex >= llength then begin
capacity := getBestArrayCapacity(labelIndex + 1);
buffer := Node_Array1d(&Array.newTObject1d(capacity));
&Array.copyObjects(labels, 0, buffer, 0, llength);
labels := buffer;
llength := capacity;
end;
labels[labelIndex] := __node;
end;
__code.assignOrder(__node, cindex);
inc(cindex);
end;
finally
primLocals.free();
refsLocals.free();
end;
{ расстановка переходов }
__next := nil;
for cindex := root.getLength() - 1 downto 0 do begin
__node := root.readComponent(cindex);
case __node.instruction of
FCT_BRANCH: begin
jumps := jmap[cindex];
jlength := system.length(jumps) - 1;
for jindex := 0 to jlength - 1 do begin
jcase := jumps[jindex];
jlabel := jcase[0];
if jlabel = NEXT then begin
__node.setJumpCase(jcase[1], __next);
end else
if jlabel >= 0 then begin
__node.setJumpCase(jcase[1], labels[jlabel]);
end else begin
__node.setJumpCase(jcase[1], debugs[not jlabel]);
end;
end;
begin
jcase := jumps[jlength];
jlabel := jcase[0];
if jlabel = NEXT then begin
__node.jumpDefault := __next;
end else
if jlabel >= 0 then begin
__node.jumpDefault := labels[jlabel];
end else begin
__node.jumpDefault := debugs[not jlabel];
end;
end;
end;
FCT_JUMP: begin
jlabel := jmap[cindex][0][0];
if jlabel = NEXT then begin
__node.jumpDefault := __next;
end else
if jlabel >= 0 then begin
__node.jumpDefault := labels[jlabel];
end else begin
__node.jumpDefault := debugs[not jlabel];
end;
end;
EXCEPT_CATCH,
EXCEPT_FINALLY,
INVOKE_FINALLY: begin
jlabel := jmap[cindex][0][0];
if jlabel = NEXT then begin
__node.reference1 := __next;
end else
if jlabel >= 0 then begin
__node.reference1 := labels[jlabel];
end else begin
__node.reference1 := debugs[not jlabel];
end;
end;
EXCEPT_TRY: begin
jumps := jmap[cindex];
begin
jlabel := jumps[0][0];
if jlabel = NEXT then begin
__node.reference1 := __next;
end else
if jlabel >= 0 then begin
__node.reference1 := labels[jlabel];
end else begin
__node.reference1 := debugs[not jlabel];
end;
end;
begin
jlabel := jumps[1][0];
if jlabel = NEXT then begin
__node.reference2 := __next;
end else
if jlabel >= 0 then begin
__node.reference2 := labels[jlabel];
end else begin
__node.reference2 := debugs[not jlabel];
end;
end;
end;
else
jumps := jmap[cindex];
if jumps <> nil then begin
begin
jlabel := jumps[0][0];
if jlabel = NEXT then begin
__node.jumpIsFalse := __next;
end else
if jlabel >= 0 then begin
__node.jumpIsFalse := labels[jlabel];
end else begin
__node.jumpIsFalse := debugs[not jlabel];
end;
end;
begin
jlabel := jumps[1][0];
if jlabel = NEXT then begin
__node.jumpIsTrue := __next;
end else
if jlabel >= 0 then begin
__node.jumpIsTrue := labels[jlabel];
end else begin
__node.jumpIsTrue := debugs[not jlabel];
end;
end;
end;
end;
__next := __node;
end;
end;
end;
procedure ImmediateBuilder.parseCallableBody(__callable: Callable);
label
break_label0,
break_label1,
break_label2,
break_label3,
break_label4,
break_label5,
break_label6,
break_label7,
break_label8,
break_label9;
var
hasElse: boolean;
isConstant: boolean;
isNeedExceptEnter: boolean;
step: int;
order: int;
index: int;
cindex: int;
jindex: int;
nindex: int;
pindex: int;
before: int;
length: int;
clength: int;
jlength: int;
position: int;
condition: int;
lastIndex: int;
lineIndex: int;
orderCase: int;
orderTrue: int;
orderFalse: int;
orderAfter: int;
labelIndex: int;
instruction: int;
foundLength: int;
stackElements: int;
message: AnsiString;
attainability: byte_Array1d;
list: Node_Array1d;
jumps: Node_Array1d;
buffer: Node_Array1d;
arguments: Type_Array1d;
foundConstructors: InstInit_Array1d;
root: Node;
next: Node;
enter: Node;
leave: Node;
cover: Node;
child: Node;
after: Node;
parent: Node;
target: Node;
__exit: Node;
__node: Node;
__code: Code;
isTrue: Node;
isFalse: Node;
__type: &Type;
declare: Node;
control: Node;
subnode: Node;
subnode0: Node;
subnode1: Node;
subblock: Node;
markable: Node;
blockTry: Node;
blockFin: Node;
monitor: Local;
relation1: Node;
relation2: Node;
item: TableItem;
value: Constant;
unattained: Node;
block: ClassInit;
branchTrue: Node;
jumpIsTrue: Node;
branchFalse: Node;
jumpIsFalse: Node;
__method: Callable;
source: TextSource;
__constructor: Node;
stack: ElementStack;
constTrue: Constant;
constFalse: Constant;
typeBoolean: PrimitiveType;
superconstructor: InstInit;
foundConstructor: InstInit;
foundArguments: ArgumentArray;
place: ru.malik.elaborarer.avtoo.lang.ClassType;
__class: ru.malik.elaborarer.avtoo.lang.ClassType;
enclosing: ru.malik.elaborarer.avtoo.lang.ClassType;
typeObject: ru.malik.elaborarer.avtoo.lang.ClassType;
superclass: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
__code := __callable.code;
enclosing := __callable.parentType;
source := TextSource(Lang.cast(__callable.source, TextSource));
if (source <> nil) and (__callable.specialSimpleName.indexOf('.') < 1) then begin
position := __callable.implementationPosition;
begin
if __callable is InstInit then begin
{ --- конструктор (метод инициализации объекта), добавленный компилятором --- }
if position < 0 then begin
position := enclosing.declarationPosition;
superclass := enclosing.getSuperclassType();
if superclass = nil then begin
{ вставка пустого тела }
root := __code.root.setData(-1, METHOD_ENTER, nil);
__code.createAndAppendNode(root).setData(-1, METHOD_LEAVE);
goto break_label0;
end;
{ вставка инструкции вызова конструктора из суперкласса }
superconstructor := superclass.getChildCallable(SPECNAME_INST_INIT, Type_Array1d(nil)) as InstInit;
if superconstructor = nil then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'required-explicit-constructor.no-default-constructor'), [
CoAnsiString.create(superclass.specialCanonicalName + ArgumentArray.toString(nil))
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if not superconstructor.isVisibleFrom(enclosing, enclosing) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'required-explicit-constructor.invisible-default-constructor'), [
CoObject.create(superconstructor), CoAnsiString.create(enclosing.specialSimpleName)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
__class := getUnhandledException(superconstructor, nil, __callable);
if __class <> nil then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'required-explicit-constructor.unhandled-exception'), [
CoObject.create(superconstructor), CoObject.create(__class)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
root := __code.root.setData(-1, METHOD_ENTER, nil);
__constructor := __code.createAndPrependNode(root).setData(-1, nil, INVOKE_SPECIAL, superconstructor);
__code.createAndPrependNode(__constructor).setData(-1, superclass, LOAD_LOCAL, __callable.arguments.thisArgument);
__code.createAndAppendNode(root).setData(-1, METHOD_LEAVE);
goto break_label0;
end;
{ --- конструктор (метод инициализации объекта), написанный в исходном коде --- }
if source.getLexemeKind(position) <> COLON then begin
superclass := enclosing.getSuperclassType();
if superclass <> nil then begin
{ вставка инструкции вызова конструктора из суперкласса }
superconstructor := superclass.getChildCallable(SPECNAME_INST_INIT, Type_Array1d(nil)) as InstInit;
if superconstructor = nil then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'required-explicit-constructor.no-default-constructor'), [
CoAnsiString.create(superclass.specialCanonicalName + ArgumentArray.toString(nil))
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
if not superconstructor.isVisibleFrom(enclosing, enclosing) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'required-explicit-constructor.invisible-default-constructor'), [
CoObject.create(superconstructor), CoAnsiString.create(enclosing.specialSimpleName)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
__class := getUnhandledException(superconstructor, nil, __callable);
if __class <> nil then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'required-explicit-constructor.unhandled-exception'), [
CoObject.create(superconstructor), CoObject.create(__class)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
__constructor := __code.createAndPrependNode(nil).setData(-1, nil, INVOKE_SPECIAL, superconstructor);
__code.createAndPrependNode(__constructor).setData(-1, superclass, LOAD_LOCAL, __callable.arguments.thisArgument);
end;
goto break_label1;
end;
{ вставка вызова другого конструктора из этого класса или суперкласса }
inc(position);
case source.getLexemeKind(position) of
EXP_SUPER:
place := enclosing.getSuperclassType();
EXP_THIS:
place := enclosing;
else
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.super-or-this'));
exception.source := source;
exception.position := position;
raise exception;
end;
if place = nil then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'can-not-use.super'), [
CoAnsiString.create(enclosing.specialSimpleName)
]
));
exception.source := source;
exception.position := position;
raise exception;
end;
before := position;
inc(position);
if source.getLexemeKind(position) <> PARENTH_OPENED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
__constructor := __code.createAndPrependNode(nil);
inc(position);
if source.getLexemeKind(position) <> PARENTH_CLOSED then repeat
position := parseExpression(__constructor, source, position, true);
requiresValue(__constructor.readComponent(-1));
case source.getLexemeKind(position) of
PARENTH_CLOSED:
break;
COMMA:
inc(position);
else
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
until false;
inc(position);
length := __constructor.getLength();
arguments := Type_Array1d(&Array.newTObject1d(length));
for index := 0 to length - 1 do arguments[index] := __constructor.readComponent(index).&type;
foundConstructors := place.findConstructors(arguments, enclosing);
foundLength := system.length(foundConstructors);
if foundLength < 1 then begin
if place = enclosing then begin
message := place.specialSimpleName;
end else begin
message := place.specialCanonicalName;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-found.constructor'), [
CoAnsiString.create(message), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundConstructor := foundConstructors[0];
if not foundConstructor.isConvertableArguments(arguments) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-applicable.constructor'), [
CoObject.create(foundConstructor), CoAnsiString.create(ArgumentArray.toString(arguments))
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if not foundConstructor.isVisibleFrom(enclosing, enclosing) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'invisible.constructor'), [
CoAnsiString.create(enclosing.specialSimpleName), CoObject.create(foundConstructor)
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
if foundLength > 1 then begin
if place = enclosing then begin
message := place.specialSimpleName;
end else begin
message := place.specialCanonicalName;
end;
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'ambiguous.constructor'), [
CoAnsiString.create(message + foundConstructor.arguments.toString())
]
));
exception.source := source;
exception.position := before;
raise exception;
end;
foundArguments := foundConstructor.arguments;
for index := 0 to length - 1 do cast(__constructor.readComponent(index), foundArguments.readComponent(index).&type);
__code.createAndPrependNode(__constructor).setData(before, place, LOAD_LOCAL, __callable.arguments.thisArgument);
__constructor.setData(before, nil, INVOKE_SPECIAL, foundConstructor);
goto break_label1;
end;
if __callable is ClassInit then begin
{ --- статичный блок (метод инициализации типа), добавленный компилятором --- }
if position < 0 then begin
position := enclosing.declarationPosition;
root := __code.root.setData(-1, METHOD_ENTER, nil);
__code.createAndAppendNode(root).setData(-1, METHOD_LEAVE);
goto break_label0;
end;
{ --- статичный блок (метод инициализации типа), написанный в исходном коде --- }
goto break_label1;
end;
if __code = nil then begin
{ --- абстрактный или родной метод --- }
if source.getLexemeKind(position) <> SEMICOLON then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.semicolon'));
exception.source := source;
exception.position := position;
raise exception;
end;
exit;
end;
end;
break_label1:
{ чтение тела метода }
if source.getLexemeKind(position) <> CURLY_OPENED then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.opened-curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
root := __code.root.setData(position, METHOD_ENTER, nil);
inc(position);
if source.getLexemeKind(position) <> CURLY_CLOSED then repeat
position := parseControl(root, source, position);
case source.getLexemeKind(position) of
L_END: begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.closed-curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
CURLY_CLOSED: break;
end;
until false;
__code.createAndAppendNode(root).setData(position, METHOD_LEAVE);
end;
break_label0:
if __code = nil then exit;
root := __code.root;
{ проверка обязательной обработки исключений }
__node := root;
parent := nil;
index := -1;
while true do begin
case __node.instruction of
INVOKE_STATIC,
INVOKE_SPECIAL,
INVOKE_VIRTUAL,
INVOKE_SERVICE: begin
__class := nil;
item := __node.operand1;
if item is Method then begin
__class := getUnhandledException(Method(item), parent, __callable);
if __class <> nil then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unhandled-exception'), [
CoObject.create(__class)
]
));
exception.source := source;
exception.position := __node.position;
raise exception;
end;
end;
end;
FCT_THROW: begin
__class := __node.reference1 as ru.malik.elaborarer.avtoo.lang.ClassType;
if not __class.isFreeThrowableType() and not isHandledException(__class, parent, __callable) then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unhandled-exception'), [
CoObject.create(__class)
]
));
exception.source := source;
exception.position := __node.position;
raise exception;
end;
end;
end;
if __node.getLength() > 0 then begin
parent := __node;
index := 0;
__node := __node.readComponent(0);
continue;
end;
if parent = nil then break;
inc(index);
if index < parent.getLength() then begin
__node := parent.readComponent(index);
continue;
end;
repeat
index := parent.index + 1;
parent := parent.parentNode;
if parent = nil then goto break_label2;
if index < parent.getLength() then begin
__node := parent.readComponent(index);
break;
end;
until false;
end;
break_label2:
{ подготовка к дальнейшей работе с кодом }
__exit := root.readComponent(-1);
with fldConstantFactory do begin
constTrue := createBoolean(true);
constFalse := createBoolean(false);
end;
typeObject := fldTypeObject;
typeBoolean := fldTypeBoolean;
{ обёртывание тела статичного блока специальными инструкциями }
if __callable is ClassInit then begin
enclosing.makeCompilable();
control := __code.createAndPrependNode(root).setData(-1, FCT_IF);
__code.createAndAppendNode(control).setData(-1, typeBoolean, CLINIT_TRY_LOCK, enclosing);
blockTry := __code.createAndAppendNode(control).setData(-1, FCT_TRY);
cover := __code.createAndAppendNode(blockTry).setData(-1, FCT_BEGIN);
blockFin := __code.createAndAppendNode(blockTry).setData(-1, FINALLY_ENTER);
__code.createAndAppendNode(blockFin).setData(-1, nil, CLINIT_UNLOCK, enclosing);
__code.createAndAppendNode(blockFin).setData(-1, FINALLY_LEAVE).special := true;
blockTry := __code.createAndAppendNode(cover).setData(-1, FCT_END);
__code.createAndAppendNode(blockTry).setData(-1, INVOKE_FINALLY, blockFin).special := true;
__code.createAndAppendNode(blockTry).setData(-1, FCT_JUMP).special := true;
for index := root.getLength() - 2 downto 1 do __code.moveNode(root.readComponent(index), cover, 0);
end;
{ обёртывание синхронизированного метода специальными инструкциями }
if __callable.isSynchronized() then begin
if __callable.isStatic() then begin
monitor := __code.createMonitorLocal(typeObject, fldConstantFactory.createClass(enclosing));
end else begin
monitor := __code.createMonitorLocal(typeObject, nil);
end;
control := __code.createAndPrependNode(root).setData(-1, FCT_BLOCK);
declare := __code.createAndAppendNode(control).setData(-1, nil, DECLARE_LOCAL, monitor);
value := monitor.value;
isConstant := monitor.isConstant();
if not isConstant then begin
__code.createAndAppendNode(declare).setData(-1, typeObject, LOAD_LOCAL, __callable.arguments.thisArgument);
end;
enter := __code.createAndAppendNode(control).setData(-1, MONITOR_ENTER);
if isConstant then begin
__code.createAndAppendNode(enter).setData(-1, typeObject, LOAD_CONST, value);
end else begin
__code.createAndAppendNode(enter).setData(-1, typeObject, LOAD_LOCAL, monitor);
end;
blockTry := __code.createAndAppendNode(control).setData(-1, FCT_TRY);
cover := __code.createAndAppendNode(blockTry).setData(-1, FCT_BEGIN);
blockFin := __code.createAndAppendNode(blockTry).setData(-1, FINALLY_ENTER);
leave := __code.createAndAppendNode(blockFin).setData(-1, MONITOR_LEAVE);
if isConstant then begin
__code.createAndAppendNode(leave).setData(-1, typeObject, LOAD_CONST, value);
end else begin
__code.createAndAppendNode(leave).setData(-1, typeObject, LOAD_LOCAL, monitor);
end;
__code.createAndAppendNode(blockFin).setData(-1, FINALLY_LEAVE).special := true;
blockTry := __code.createAndAppendNode(cover).setData(-1, FCT_END);
__code.createAndAppendNode(blockTry).setData(-1, INVOKE_FINALLY, blockFin).special := true;
__code.createAndAppendNode(blockTry).setData(-1, FCT_JUMP).special := true;
for index := root.getLength() - 2 downto 1 do __code.moveNode(root.readComponent(index), cover, 0);
end;
{ вставка инструкций обработки исключений, дополнительных узлов, а также оптимизация кода }
__code.createAndPrependNode(__exit).setData(-1, EXCEPT_LEAVE);
isNeedExceptEnter := false;
__node := root;
parent := nil;
pindex := -1;
while true do begin
if __node = __exit then begin
if isNeedExceptEnter then __code.createAndPrependNode(__exit).setData(-1, EXCEPT_ENTER);
break;
end;
begin
instruction := __node.instruction;
case instruction of
METHOD_ENTER: begin
if (__callable.visibility > VIS_PRIVATE) and (__callable.isStatic() or (__callable is InstInit)) then begin
block := enclosing.getStaticBlock();
if (block <> nil) and (block <> __callable) then __code.createAndPrependNode(__node).setData(__node.position, nil, INVOKE_STATIC, block);
end;
end;
FCT_TRY: begin
isNeedExceptEnter := true;
for nindex := __node.getLength() - 1 downto 0 do begin
subblock := __node.readComponent(nindex);
case subblock.instruction of
FINALLY_ENTER: begin
subblock.persistent := true;
__code.createAndPrependNode(__exit).setData(-1, EXCEPT_FINALLY, subblock);
end;
FCT_CATCH: begin
markable := subblock.readComponent(0);
markable.persistent := true;
__code.createAndPrependNode(__exit).setData(-1, EXCEPT_CATCH, markable, subblock.reference1);
end;
FCT_BEGIN: begin
markable := subblock.readComponent(-1);
subblock.persistent := true;
markable.persistent := true;
__code.createAndPrependNode(__exit).setData(-1, EXCEPT_TRY, subblock, markable);
end;
end;
end;
end;
FCT_BREAK,
FCT_RETURN,
FCT_CONTINUE: begin
position := __node.position;
target := Node(__node.reference1);
control := parent;
while (control <> nil) and (control <> target) do begin
subblock := control.readComponent(-1);
if (control.instruction = FCT_TRY) and (subblock.instruction = FINALLY_ENTER) then __code.createAndAppendNode(__node).setData(position, INVOKE_FINALLY, subblock);
control := control.parentNode;
end;
if instruction <> FCT_RETURN then __code.createAndAppendNode(__node).setData(position, FCT_JUMP);
end;
BOOL_OR,
BOOL_AND,
BOOL_NOT,
BOOL_COND: begin
if (instruction = BOOL_COND) and not __node.&type.isBoolean() then begin
__code.createAndInsertNode(__node, 2).setData(-1, FCT_JUMP);
goto break_label5;
end;
case parent.instruction of
FCT_IF:
if pindex = 0 then goto break_label5;
FCT_DO,
FCT_FOR,
FCT_WHILE:
if pindex = parent.getLength() - 1 then goto break_label5;
BOOL_OR,
BOOL_AND,
BOOL_NOT,
BOOL_COND:
goto break_label5;
end;
if (instruction = BOOL_COND) and not isLogicalConditionNode(__node) then begin
__code.createAndInsertNode(__node, 2).setData(-1, FCT_JUMP);
goto break_label5;
end;
cover := __code.createAndInsertNode(parent, pindex).setData(-1, typeBoolean, BOOL_COND);
__code.moveNode(__node, cover, 0);
__node := cover;
__code.createAndAppendNode(cover).setData(-1, typeBoolean, LOAD_CONST, constTrue);
__code.createAndAppendNode(cover).setData(-1, FCT_JUMP);
__code.createAndAppendNode(cover).setData(-1, typeBoolean, LOAD_CONST, constFalse);
end;
REF_EQ,
REF_NE: begin
relation1 := __node.readComponent(0);
relation2 := __node.readComponent(1);
begin
if (relation1.instruction = LOAD_CONST) and relation1.operandC.isNull() then begin
__node.instruction := instruction + (REF_IS_NULL - REF_EQ);
__code.removeNode(relation1);
child := relation2;
goto break_label6;
end;
if (relation2.instruction = LOAD_CONST) and relation2.operandC.isNull() then begin
__node.instruction := instruction + (REF_IS_NULL - REF_EQ);
__code.removeNode(relation2);
child := relation1;
goto break_label6;
end;
goto break_label5;
end;
break_label6:
instruction := child.instruction;
if (instruction = LOAD_STATIC) or (instruction = LOAD_LOCAL) or (instruction = LOAD_CONST) and not child.operandC.isString() then begin
__node.weak := true;
child.weak := true;
end;
end;
O_SCAL_EQ,
O_SCAL_NE: begin
if (__node.operand1 as &Type).isLong() then begin
relation1 := __node.readComponent(0);
relation2 := __node.readComponent(1);
if (relation1.instruction = O_BIT_AND) and (relation2.instruction = LOAD_CONST) and relation2.operandC.isDefaultValue() then begin
__node.instruction := instruction + (TEST_EQZ - O_SCAL_EQ);
__code.moveNode(relation1.readComponent(0), __node, 0);
__code.moveNode(relation1.readComponent(0), __node, 1);
__code.removeNode(relation1);
__code.removeNode(relation2);
goto break_label5;
end;
if (relation2.instruction = O_BIT_AND) and (relation1.instruction = LOAD_CONST) and relation1.operandC.isDefaultValue() then begin
__node.instruction := instruction + (TEST_EQZ - O_SCAL_EQ);
__code.moveNode(relation2.readComponent(0), __node, 0);
__code.moveNode(relation2.readComponent(0), __node, 1);
__code.removeNode(relation1);
__code.removeNode(relation2);
end;
end;
end;
LOAD_CONST,
LOAD_LOCAL,
LOAD_STATIC: begin
if instruction = LOAD_STATIC then begin
__class := (__node.operand1 as Member).parentType;
if enclosing <> __class then begin
block := __class.getStaticBlock();
if block <> nil then begin
__code.createAndPrependNode(__node).setData(__node.position, nil, INVOKE_STATIC, block);
goto break_label5;
end;
end;
end;
if pindex = parent.getLength() - 1 then begin
case parent.instruction of
STORE_LOCAL,
STORE_STATIC,
DECLARE_WITH,
DECLARE_LOCAL: begin
if (pindex = 0) and (instruction = LOAD_CONST) then begin
value := __node.operandC;
__type := value.&type;
if __type.isInt() or __type.isBoolean() or value.isNull() then begin
parent.operandC := value;
goto break_label7;
end;
end;
goto break_label5;
end;
REF_EQ,
REF_NE: begin
if (instruction = LOAD_CONST) and __node.operandC.isString() then goto break_label5;
child := parent.readComponent(0);
instruction := child.instruction;
if (instruction = LOAD_STATIC) or (instruction = LOAD_LOCAL) or (instruction = LOAD_CONST) and not child.operandC.isString() then begin
parent.weak := true;
child.weak := true;
end;
parent.operand1 := __node.operand1;
parent.operandC := __node.operandC;
end;
READ_ELEMENT: begin
if instruction <> LOAD_CONST then goto break_label5;
parent.operandC := __node.operandC;
end;
READ_FIELD,
READ_SPECIAL,
READ_PROPERTY: begin
if (instruction = LOAD_CONST) and __node.operandC.isString() then goto break_label5;
parent.operand2 := __node.operand1;
parent.operandC := __node.operandC;
end;
READ_COMPONENT,
TEST_EQZ,
TEST_NEZ,
O_BIT_AND,
O_BIT_OR,
O_BIT_XOR,
O_SCAL_MUL,
O_SCAL_DIV,
O_SCAL_DIVU,
O_SCAL_REM,
O_SCAL_REMU,
O_SCAL_ADD,
O_SCAL_SUB,
O_SCAL_SHR,
O_SCAL_SHRU,
O_SCAL_SHL,
O_SCAL_GT,
O_SCAL_GE,
O_SCAL_LT,
O_SCAL_LE,
O_SCAL_EQ,
O_SCAL_NE,
O_VECT_MUL,
O_VECT_DIV,
O_VECT_ADD,
O_VECT_SUB,
O_VECT_SHR,
O_VECT_SHRU,
O_VECT_SHL,
O_VECT_GT,
O_VECT_GE,
O_VECT_LT,
O_VECT_LE,
O_VECT_EQ,
O_VECT_NE,
O_VECT_HMUL,
O_VECT_HMULU,
O_VECT_SADD,
O_VECT_SADDU,
O_VECT_SSUB,
O_VECT_SSUBU: begin
parent.operand2 := __node.operand1;
parent.operandC := __node.operandC;
end;
else
goto break_label5;
end;
break_label7:
__code.removeNode(__node);
dec(pindex);
goto break_label4;
end;
end;
end;
break_label5:
if __node.getLength() > 0 then begin
parent := __node;
pindex := 0;
__node := __node.readComponent(0);
continue;
end;
if parent = nil then break;
end;
break_label4:
inc(pindex);
if pindex < parent.getLength() then begin
__node := parent.readComponent(pindex);
continue;
end;
repeat
pindex := parent.index + 1;
parent := parent.parentNode;
if parent = nil then goto break_label3;
if pindex < parent.getLength() then begin
__node := parent.readComponent(pindex);
break;
end;
until false;
end;
break_label3:
{ нумерация узлов }
__code.assignOrder(root, 0);
__node := root;
parent := nil;
pindex := -1;
while true do begin
order := __node.order;
instruction := __node.instruction;
case instruction of
NOP,
FCT_IF,
FCT_SWITCH,
FCT_CASE,
FCT_DEFAULT,
FCT_LABEL,
FCT_DO,
FCT_FOR,
FCT_WHILE,
FCT_BLOCK,
FCT_BREAK,
FCT_CONTINUE,
FCT_TRY,
FCT_CATCH,
BOOL_OR,
BOOL_AND,
BOOL_NOT,
BOOL_COND: begin
{ нумеруются только дочерние узлы, этот узел не нумеруется }
__code.clearOrder(__node);
for nindex := 0 to __node.getLength() - 1 do begin
__code.assignOrder(__node.readComponent(nindex), order);
inc(order);
end;
end;
FCT_BEGIN,
FINALLY_ENTER,
METHOD_ENTER,
METHOD_LEAVE,
NEW_ARRAY,
NEW_INSTANCE: begin
{ сперва нумеруется этот узел, а затем — дочерние узлы }
for nindex := 0 to __node.getLength() - 1 do begin
inc(order);
__code.assignOrder(__node.readComponent(nindex), order);
end;
end;
else
{ не нумеруется узел с объявлением локальной константы }
if ((instruction = DECLARE_WITH) or (instruction = DECLARE_LOCAL)) and __node.isEmpty() and (__node.operand1 as Local).isConstant() then begin
__code.clearOrder(__node);
end;
{ сперва нумеруются дочерние узлы, а затем — этот узел }
for nindex := 0 to __node.getLength() - 1 do begin
__code.assignOrder(__node.readComponent(nindex), order);
inc(order);
end;
end;
if __node.getLength() > 0 then begin
parent := __node;
pindex := 0;
__node := __node.readComponent(0);
continue;
end;
if parent = nil then break;
inc(pindex);
if pindex < parent.getLength() then begin
__node := parent.readComponent(pindex);
continue;
end;
repeat
pindex := parent.index + 1;
parent := parent.parentNode;
if parent = nil then goto break_label8;
if pindex < parent.getLength() then begin
__node := parent.readComponent(pindex);
break;
end;
until false;
end;
break_label8:
{ расстановка переходов и замена условных переходов по константам типа boolean на безусловные переходы }
__node := root;
parent := nil;
pindex := -1;
while true do begin
case __node.instruction of
FCT_IF: begin
hasElse := __node.getLength() > 3;
orderAfter := __node.maxOrder() + 1;
orderTrue := __node.readComponent(1).minOrder();
if hasElse then begin
orderFalse := __node.readComponent(3).minOrder();
end else begin
orderFalse := orderAfter;
end;
if orderTrue < 0 then orderTrue := orderAfter;
if orderFalse < 0 then orderFalse := orderAfter;
with __node.readComponent(0) do begin
jumpIsTrue := __code.readComponent(orderTrue);
jumpIsFalse := __code.readComponent(orderFalse);
end;
if hasElse then begin
__node.readComponent(2).jumpDefault := __code.readComponent(orderAfter);
end;
end;
FCT_SWITCH: begin
orderAfter := __node.maxOrder() + 1;
with __node.readComponent(0) do for nindex := __node.getLength() - 1 downto 1 do begin
subnode := __node.readComponent(nindex);
orderCase := subnode.minOrder();
if orderCase < 0 then begin
orderCase := orderAfter;
end else begin
orderAfter := orderCase;
end;
if subnode.instruction = FCT_CASE then begin
setJumpCase((subnode.reference1 as CoInt).asInt(), __code.readComponent(orderCase));
continue;
end;
jumpDefault := __code.readComponent(orderCase);
end;
end;
FCT_DO: begin
orderAfter := __node.maxOrder() + 1;
orderTrue := __node.readComponent(-2).minOrder();
with __node.readComponent(-1) do begin
if orderTrue < 0 then orderTrue := minOrder();
jumpIsTrue := __code.readComponent(orderTrue);
jumpIsFalse := __code.readComponent(orderAfter);
end;
end;
FCT_FOR: begin
orderAfter := __node.maxOrder() + 1;
orderTrue := __node.readComponent(-3).minOrder();
with __node.readComponent(-1) do begin
condition := minOrder();
if orderTrue < 0 then begin
orderTrue := __node.readComponent(-2).minOrder();
if orderTrue < 0 then orderTrue := condition;
end;
__node.readComponent(-4).jumpDefault := __code.readComponent(condition);
jumpIsTrue := __code.readComponent(orderTrue);
jumpIsFalse := __code.readComponent(orderAfter);
end;
end;
FCT_WHILE: begin
orderAfter := __node.maxOrder() + 1;
orderTrue := __node.readComponent(-2).minOrder();
with __node.readComponent(-1) do begin
condition := minOrder();
if orderTrue < 0 then orderTrue := condition;
__node.readComponent(-3).jumpDefault := __code.readComponent(condition);
jumpIsTrue := __code.readComponent(orderTrue);
jumpIsFalse := __code.readComponent(orderAfter);
end;
end;
FCT_BREAK: begin
__node.readComponent(-1).jumpDefault := __code.readComponent((__node.reference1 as Node).maxOrder() + 1);
end;
FCT_CONTINUE: begin
target := __node.reference1 as Node;
if target.instruction <> FCT_FOR then begin
condition := target.readComponent(-1).minOrder();
end else begin
step := target.readComponent(-2).minOrder();
if step >= 0 then begin
condition := step;
end else begin
condition := target.readComponent(-1).minOrder();
end;
end;
__node.readComponent(-1).jumpDefault := __code.readComponent(condition);
end;
FCT_RETURN: begin
__node.jumpDefault := __exit;
end;
FCT_TRY: begin
after := __code.readComponent(__node.maxOrder() + 1);
__node.readComponent(0).readComponent(-1).readComponent(-1).jumpDefault := after;
for nindex := __node.getLength() - 2 downto 1 do begin
__node.readComponent(nindex).readComponent(-1).jumpDefault := after;
end;
end;
BOOL_OR: begin
isTrue := __node.jumpIsTrue;
isFalse := __node.jumpIsFalse;
subnode0 := __node.readComponent(0);
subnode1 := __node.readComponent(1);
subnode0.jumpIsTrue := isTrue;
subnode0.jumpIsFalse := __code.readComponent(subnode1.minOrder());
subnode1.jumpIsTrue := isTrue;
subnode1.jumpIsFalse := isFalse;
__node.jumpIsTrue := nil;
__node.jumpIsFalse := nil;
end;
BOOL_AND: begin
isTrue := __node.jumpIsTrue;
isFalse := __node.jumpIsFalse;
subnode0 := __node.readComponent(0);
subnode1 := __node.readComponent(1);
subnode0.jumpIsTrue := __code.readComponent(subnode1.minOrder());
subnode0.jumpIsFalse := isFalse;
subnode1.jumpIsTrue := isTrue;
subnode1.jumpIsFalse := isFalse;
__node.jumpIsTrue := nil;
__node.jumpIsFalse := nil;
end;
BOOL_NOT: begin
isTrue := __node.jumpIsTrue;
isFalse := __node.jumpIsFalse;
with __node.readComponent(0) do begin
jumpIsTrue := isFalse;
jumpIsFalse := isTrue;
end;
__node.jumpIsTrue := nil;
__node.jumpIsFalse := nil;
end;
BOOL_COND: begin
isTrue := __node.jumpIsTrue;
isFalse := __node.jumpIsFalse;
branchTrue := __node.readComponent(1);
branchFalse := __node.readComponent(-1);
with __node.readComponent(0) do begin
jumpIsTrue := __code.readComponent(branchTrue.minOrder());
jumpIsFalse := __code.readComponent(branchFalse.minOrder());
end;
if (isTrue = nil) or (isFalse = nil) then begin
__node.readComponent(2).jumpDefault := __code.readComponent(__node.maxOrder() + 1);
end else begin
branchTrue.jumpIsTrue := isTrue;
branchTrue.jumpIsFalse := isFalse;
branchFalse.jumpIsTrue := isTrue;
branchFalse.jumpIsFalse := isFalse;
end;
__node.jumpIsTrue := nil;
__node.jumpIsFalse := nil;
end;
LOAD_CONST: begin
isTrue := __node.jumpIsTrue;
isFalse := __node.jumpIsFalse;
value := __node.operandC;
if value.isBoolean() and (isTrue <> nil) and (isFalse <> nil) then begin
__node.setData(__node.position, FCT_JUMP);
__node.clearJumpCases();
if value.asBoolean() then begin
__node.jumpDefault := isTrue;
end else begin
__node.jumpDefault := isFalse;
end;
end;
end;
METHOD_LEAVE: begin
__node.special := true;
__node.endPoint := true;
end;
FCT_THROW,
FINALLY_LEAVE: begin
__node.endPoint := true;
end;
end;
if __node.getLength() > 0 then begin
parent := __node;
pindex := 0;
__node := __node.readComponent(0);
continue;
end;
if parent = nil then break;
inc(pindex);
if pindex < parent.getLength() then begin
__node := parent.readComponent(pindex);
continue;
end;
repeat
pindex := parent.index + 1;
parent := parent.parentNode;
if parent = nil then goto break_label9;
if pindex < parent.getLength() then begin
__node := parent.readComponent(pindex);
break;
end;
until false;
end;
break_label9:
{ проверка и оптимизация связности кода }
begin
clength := __code.getLength();
attainability := &Array.newByte1d(clength);
{ проверка наличия недостижимых узлов и отмена нумерации для специальных из них }
begin
unattained := nil;
defineAttainability(attainability, __code, clength);
cindex := clength - 1;
while cindex >= 0 do begin
cindex := &Array.lastIndexOf(0, attainability, cindex, 0);
if cindex < 0 then break;
__node := __code.readComponent(cindex);
dec(cindex);
if not __node.special or (__node.instruction = FCT_BEGIN) then begin
unattained := __node;
continue;
end;
if not __node.persistent then begin
dec(clength);
__code.clearOrder(__node);
end;
end;
if unattained <> nil then repeat
position := unattained.position;
if position >= 0 then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'detected.unreachable-code'));
exception.source := source;
exception.position := position;
raise exception;
end;
if unattained.instruction = FCT_JUMP then begin
unattained := unattained.jumpDefault;
continue;
end;
unattained := __code.readComponent(unattained.order + 1);
until false;
end;
{ проверка обязательного возвращения значения }
if not __callable.&type.isVoid() then for cindex := clength - 1 downto 0 do begin
__node := __code.readComponent(cindex);
if (__node.instruction <> FCT_RETURN) and __node.hasJumpsTo(__exit) then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'required.return'));
exception.source := source;
exception.position := __exit.position;
raise exception;
end;
end;
{ оптимизация переходов, отмена нумерации для узлов — переходов на следующий по номеру узел }
jumps := Node_Array1d(&Array.newTObject1d($0f));
jlength := 0;
for cindex := clength - 1 downto 0 do begin
__node := __code.readComponent(cindex);
instruction := __node.instruction;
jindex := __node.getJumpCasesLength();
if (instruction <> FCT_JUMP) and (instruction <> FCT_RETURN) then begin
if instruction = FCT_BEGIN then __node.position := -1;
if jindex <= 0 then continue;
jlength := 0;
end else begin
target := __node.jumpDefault;
if target.order = __node.order + 1 then begin
dec(clength);
__code.clearOrder(__node);
__code.replaceJumpNode(__node, target);
continue;
end;
jlength := 1;
jumps[0] := __node;
end;
while jindex > -1 do begin
dec(jindex);
if jindex < 0 then begin
target := __node.jumpDefault;
end else begin
target := __node.getJumpCaseNodeAt(jindex);
end;
if target <> nil then begin
instruction := target.instruction;
while ((instruction = FCT_RETURN) or (instruction = FCT_JUMP)) and ((jlength <= 0) or (&Array.indexOf(target, jumps, 0, jlength) < 0)) do begin
if jlength = system.length(jumps) then begin
buffer := Node_Array1d(&Array.newTObject1d((jlength shl 1) or 1));
&Array.copyObjects(jumps, 0, buffer, 0, jlength);
jumps := buffer;
end;
jumps[jlength] := target;
inc(jlength);
target := target.jumpDefault;
instruction := target.instruction;
end;
if jindex < 0 then begin
__node.jumpDefault := target;
continue;
end;
__node.setJumpCase(__node.getJumpCaseValueAt(jindex), target);
end;
end;
end;
{ отмена нумерации для недостижимых узлов, возможно образовавшихся в результате оптимизации переходов }
begin
&Array.fillPrimitives(attainability, 0, clength, 0);
defineAttainability(attainability, __code, clength);
cindex := clength - 1;
while cindex >= 0 do begin
cindex := &Array.lastIndexOf(0, attainability, cindex, 0);
if cindex < 0 then break;
__node := __code.readComponent(cindex);
dec(cindex);
if not __node.persistent then __code.clearOrder(__node);
end;
end;
end;
{ массив инструкций }
list := __code.clone();
clength := system.length(list);
{ расстановка меток }
begin
next := nil;
for cindex := clength - 1 downto 0 do begin
__node := list[cindex];
if __node.persistent then __node.labelIndex := 0;
for jindex := __node.getJumpCasesLength() - 1 downto -1 do begin
if jindex < 0 then begin
target := __node.jumpDefault;
end else begin
target := __node.getJumpCaseNodeAt(jindex);
end;
if (target <> nil) and (target <> next) then target.labelIndex := 0;
end;
next := __node;
end;
labelIndex := 0;
lastIndex := -1;
for cindex := 0 to clength - 1 do begin
__node := list[cindex];
lineIndex := __node.location[0];
if (lineIndex >= 0) and (lastIndex <> lineIndex) then begin
__node.labelIndex := -1;
__node.debugIndex := __code.createDebugIndex(lineIndex);
lastIndex := lineIndex;
continue;
end;
if __node.labelIndex = 0 then begin
__node.labelIndex := labelIndex;
inc(labelIndex);
end;
end;
end;
{ определение максимального количества занимаемых элементов стака }
begin
stack := ElementStack.create();
try
for cindex := 1 to clength - 1 do begin
__node := list[cindex];
stackElements := __node.stackElements;
if stackElements >= 0 then stack.stackElements := stackElements;
case __node.instruction of
EXP_INSTANCEOF,
REF_IS_NULL,
REF_IS_OBJECT: ;
FCT_RETURN,
METHOD_LEAVE: begin
stack.reset();
continue;
end;
FCT_THROW,
FCT_BRANCH,
FINALLY_LEAVE,
MONITOR_ENTER,
MONITOR_LEAVE: begin
stack.change(-1);
continue;
end;
CLINIT_TRY_LOCK: begin
stack.change(+1);
end;
NEW_ARRAY,
NEW_INSTANCE,
FINALLY_ENTER,
LOAD_INTERRUPT: begin
stack.change(+1);
continue;
end;
LOAD_CONST: begin
stack.change(__node.operandC.&type.stackElements);
end;
LOAD_LOCAL,
LOAD_STATIC: begin
stack.change((__node.operand1 as TypedItem).&type.stackElements);
end;
INC_PRED_LOAD_LOCAL,
DEC_PRED_LOAD_LOCAL,
INC_POST_LOAD_LOCAL,
DEC_POST_LOAD_LOCAL: begin
stack.change((__node.operand1 as TypedItem).&type.stackElements);
continue;
end;
READ_ELEMENT: begin
if __node.operandC = nil then begin
stack.change(+0 - (__node.operand1 as &Type).stackElements);
continue;
end;
stack.change(+1 - (__node.operand1 as &Type).stackElements);
continue;
end;
READ_COMPONENT: begin
if (__node.operand2 = nil) and (__node.operandC = nil) then begin
stack.change(-2 + (__node.operand1 as &Type).stackElements);
end else begin
stack.change(-1 + (__node.operand1 as &Type).stackElements);
end;
end;
READ_FIELD,
READ_SPECIAL,
READ_PROPERTY: begin
if (__node.operand2 = nil) and (__node.operandC = nil) then begin
stack.change(-1 + (__node.operand1 as TypedItem).&type.stackElements);
end else begin
stack.change(+0 + (__node.operand1 as TypedItem).&type.stackElements);
end;
end;
DUP1,
DUP1X1,
DUP1X2: begin
stack.change((__node.operand1 as &Type).stackElements);
continue;
end;
DUP2: begin
stack.change((__node.operand1 as &Type).stackElements + 1);
continue;
end;
INVOKE_STATIC,
INVOKE_SPECIAL,
INVOKE_VIRTUAL,
INVOKE_SERVICE: begin
__method := __node.operand1 as Callable;
if __node.weak then begin
stack.change(+0 - __method.arguments.stackElements);
end else begin
stack.change(__method.&type.stackElements - __method.arguments.stackElements);
end;
end;
NEW_VECTOR: begin
__type := __node.operand1 as PrimitiveType;
stack.change(__type.stackElements - PrimitiveType(__type).vectorLength);
continue;
end;
CAST_TO: begin
stack.change((__node.operand1 as &Type).stackElements - (__node.operand2 as &Type).stackElements);
continue;
end;
REF_EQ,
REF_NE: begin
if (__node.operand1 = nil) and (__node.operandC = nil) then begin
stack.change(-1);
end else begin
stack.change(+0);
end;
end;
TEST_EQZ,
TEST_NEZ: begin
if (__node.operand2 = nil) and (__node.operandC = nil) then begin
stack.change(-1);
end else begin
stack.change(+0);
end;
end;
O_BIT_OR,
O_BIT_AND,
O_BIT_XOR: begin
if (__node.operand2 = nil) and (__node.operandC = nil) then begin
stack.change(-(__node.operand1 as &Type).stackElements);
end else begin
stack.change(+0);
end;
end;
O_SCAL_MUL,
O_SCAL_DIV,
O_SCAL_DIVU,
O_SCAL_REM,
O_SCAL_REMU,
O_SCAL_ADD,
O_SCAL_SUB,
O_VECT_MUL,
O_VECT_DIV,
O_VECT_ADD,
O_VECT_SUB,
O_VECT_EQ,
O_VECT_NE,
O_VECT_GT,
O_VECT_GE,
O_VECT_LT,
O_VECT_LE,
O_VECT_HMUL,
O_VECT_HMULU,
O_VECT_SADD,
O_VECT_SADDU,
O_VECT_SSUB,
O_VECT_SSUBU: begin
if (__node.operand2 = nil) and (__node.operandC = nil) then begin
stack.change(-(__node.operand1 as &Type).stackElements);
continue;
end;
stack.change(+0);
continue;
end;
O_SCAL_SHR,
O_SCAL_SHRU,
O_SCAL_SHL,
O_VECT_SHR,
O_VECT_SHRU,
O_VECT_SHL: begin
if (__node.operand2 = nil) and (__node.operandC = nil) then begin
stack.change(-1);
continue;
end;
stack.change(+0);
continue;
end;
O_SCAL_EQ,
O_SCAL_NE,
O_SCAL_GT,
O_SCAL_GE,
O_SCAL_LT,
O_SCAL_LE: begin
if (__node.operand2 = nil) and (__node.operandC = nil) then begin
stack.change(+1 - ((__node.operand1 as &Type).stackElements shl 1));
end else begin
stack.change(+1 - (__node.operand1 as &Type).stackElements);
end;
end;
O_VECT_LUP,
O_VECT_UUP,
O_VECT_PCK: begin
stack.change(__node.&type.stackElements - (__node.operand1 as &Type).stackElements);
continue;
end;
STORE_LOCAL,
STORE_STATIC,
DECLARE_WITH,
DECLARE_LOCAL: begin
if (__node.operand2 = nil) and (__node.operandC = nil) then begin
stack.change(-(__node.operand1 as TypedItem).&type.stackElements);
end else begin
stack.change(+0);
end;
end;
WRITE_COMPONENT: begin
stack.change(-((__node.operand1 as &Type).stackElements + 2));
end;
WRITE_FIELD,
WRITE_SPECIAL,
WRITE_PROPERTY: begin
stack.change(-((__node.operand1 as TypedItem).&type.stackElements + 1));
end;
else
continue;
end;
jumpIsTrue := __node.jumpIsTrue;
jumpIsFalse := __node.jumpIsFalse;
if (jumpIsTrue <> nil) and (jumpIsFalse <> nil) then begin
stack.change(-1);
if (jumpIsTrue.order > cindex) and (jumpIsFalse.order > cindex) then begin
stackElements := stack.stackElements;
jumpIsTrue.stackElements := stackElements;
jumpIsFalse.stackElements := stackElements;
end;
end;
end;
root.setData(root.position, METHOD_ENTER, CoInt.create(stack.maximumElements));
finally
stack.free();
end;
end;
end;
function ImmediateBuilder.isStaticFieldsOnly(): boolean;
begin
result := fldStaticFieldsOnly;
end;
function ImmediateBuilder.isLibrary(): boolean;
begin
result := fldLibrary;
end;
constructor ImmediateBuilder.create();
begin
inherited create();
fldGlobalItemHolder := ImmediateBuilderItemHolder.create();
end;
constructor ImmediateBuilder.create(__staticFieldsOnly: boolean);
begin
inherited create();
fldStaticFieldsOnly := __staticFieldsOnly;
fldGlobalItemHolder := ImmediateBuilderItemHolder.create();
end;
constructor ImmediateBuilder.create(__staticFieldsOnly, __library: boolean);
begin
inherited create();
fldLibrary := __library;
fldStaticFieldsOnly := __staticFieldsOnly;
fldGlobalItemHolder := ImmediateBuilderItemHolder.create();
end;
destructor ImmediateBuilder.destroy;
begin
fldGlobalItemHolder.free();
inherited destroy;
end;
procedure ImmediateBuilder.compile();
var
__isLibrary: boolean;
__isStaticFieldsOnly: boolean;
aindex: int;
cindex: int;
lindex: int;
mindex: int;
tindex: int;
alength: int;
clength: int;
dlength: int;
nlength: int;
tlength: int;
__maxThreads: int;
allTypes: Type_Array1d;
buffer: ClassType_Array1d;
content: ClassType_Array1d;
__types: ClassType_Array1d;
__arrays: ArrayType_Array1d;
__classes: ClassType_Array1d;
__type: &Type;
__member: Member;
__array: ArrayType;
componentType: &Type;
staticBlock: ClassInit;
factory: ConstantFactory;
__libraries: LibraryArray;
objectsHolder: ObjectVector;
parallelWorker: CompilerParallelWorker;
__class: ru.malik.elaborarer.avtoo.lang.ClassType;
__library: ru.malik.elaborarer.avtoo.lang.&Library;
__project: ru.malik.elaborarer.avtoo.lang.&Library;
begin
{ -- предыдущие стадии -- }
inherited compile();
{ -- константы и типы, используемые в следующей стадии -- }
factory := getConstantFactory();
fldTypeNull := getNullType();
fldTypeClass := getClassType(PACKNAME_LANG + '.' + TYPENAME_CLASS);
fldTypeObject := getClassType(PACKNAME_LANG + '.' + TYPENAME_OBJECT);
fldTypeString := getClassType(PACKNAME_LANG + '.' + TYPENAME_STRING);
fldTypePackage := getClassType(PACKNAME_LANG + '.' + TYPENAME_PACKAGE);
fldTypeThrowable := getClassType(PACKNAME_LANG + '.' + TYPENAME_THROWABLE);
fldTypeVoid := getPrimitiveType(TYP_VOID);
fldTypeBoolean := getPrimitiveType(TYP_BOOLEAN);
fldTypeInt := getPrimitiveType(TYP_INT);
fldTypeLong := getPrimitiveType(TYP_LONG);
fldConstantFactory := factory;
{ 6. Стадия построения исполняемого кода проекта }
__project := project;
__classes := __project.classes.clone();
__arrays := arrays.clone();
clength := system.length(__classes);
alength := system.length(__arrays);
__maxThreads := maxThreads;
__isLibrary := isLibrary();
__isStaticFieldsOnly := isStaticFieldsOnly();
for cindex := 0 to clength - 1 do begin
__class := __classes[cindex];
staticBlock := __class.getStaticBlock();
for mindex := 0 to __class.getLength() - 1 do begin
__member := __class.readComponent(mindex);
if __member is Field then parseStaticFieldValue(Field(__member), staticBlock);
end;
if (staticBlock <> nil) and (staticBlock.declarationPosition < 0) and staticBlock.code.root.isEmpty() then __class.removeStaticBlock();
end;
if __isStaticFieldsOnly then exit;
if not __isLibrary then begin
tlength := 0;
__types := nil;
__libraries := libraries;
for lindex := 0 to __libraries.getLength() - 1 do begin
__library := __libraries.readComponent(lindex);
if __project <> __library then begin
content := __library.classes.clone();
if __types = nil then begin
tlength := system.length(content);
__types := ClassType_Array1d(&Array.newTObject1d(getBestArrayCapacity(tlength)));
&Array.copyObjects(content, 0, __types, 0, tlength);
end else begin
dlength := system.length(content);
nlength := tlength + dlength;
if nlength > system.length(__types) then begin
buffer := ClassType_Array1d(&Array.newTObject1d(getBestArrayCapacity(nlength)));
&Array.copyObjects(__types, 0, buffer, 0, tlength);
__types := buffer;
end;
&Array.copyObjects(content, 0, __types, tlength, dlength);
tlength := nlength;
end;
end;
end;
with CompilerParallelWorker.create(__maxThreads) do try
objectsHolder := ObjectVector.create(false, TObject_Array1d(__types), tlength);
try
targets := objectsHolder;
run(ImmediateBuilderForBinarySources.create(self));
finally
objectsHolder.free();
end;
finally
free();
end;
end;
for cindex := 0 to clength - 1 do begin
__class := __classes[cindex];
for mindex := 0 to __class.getLength() - 1 do begin
__member := __class.readComponent(mindex);
if not __member.isAbstract() and (__member is &Property) then parsePropertySpecifiers(&Property(__member));
end;
end;
for aindex := 0 to alength - 1 do begin
__array := __arrays[aindex];
componentType := __array.componentType;
if not(componentType is PrimitiveType) and (componentType <> fldTypeObject) then begin
alength := aindex;
break;
end;
__class := __array;
for mindex := 0 to __class.getLength() - 1 do begin
__member := __class.readComponent(mindex);
if not __member.isAbstract() and (__member is &Property) then buildPropertySpecifiers(&Property(__member));
end;
end;
begin
__types := ClassType_Array1d(&Array.newTObject1d(clength + alength));
&Array.copyObjects(__classes, 0, __types, 0, clength);
&Array.copyObjects(__arrays, 0, __types, clength, alength);
parallelWorker := CompilerParallelWorker.create(__maxThreads);
try
fldThreadItemHolder := parallelWorker;
try
objectsHolder := ObjectVector.create(false, TObject_Array1d(__types), system.length(__types));
try
parallelWorker.targets := objectsHolder;
parallelWorker.run(ImmediateBuilderForTextSources.create(self));
finally
objectsHolder.free();
end;
finally
fldThreadItemHolder := nil;
end;
finally
parallelWorker.free();
end;
end;
{ 7. Стадия разметки данных }
allTypes := types.clone();
tlength := system.length(allTypes);
if not __isLibrary then for tindex := 0 to tlength - 1 do begin
__type := allTypes[tindex];
if __type is ru.malik.elaborarer.avtoo.lang.ClassType then ru.malik.elaborarer.avtoo.lang.ClassType(__type).markupClass();
end;
for tindex := 0 to tlength - 1 do begin
__type := allTypes[tindex];
if __type is ru.malik.elaborarer.avtoo.lang.ClassType then ru.malik.elaborarer.avtoo.lang.ClassType(__type).markupStruct();
end;
end;
procedure ImmediateBuilder.clear();
begin
fldTypeNull := nil;
fldTypeClass := nil;
fldTypeObject := nil;
fldTypeString := nil;
fldTypePackage := nil;
fldTypeThrowable := nil;
fldTypeVoid := nil;
fldTypeBoolean := nil;
fldTypeInt := nil;
fldTypeLong := nil;
inherited clear();
end;
{%endregion}
{%region ImmediateBuilderItemHolder }
procedure ImmediateBuilderItemHolder.setResultWith(newResultWith: Local);
begin
fldResultWith := newResultWith;
end;
procedure ImmediateBuilderItemHolder.setResultItem(newResultItem: TableItem);
begin
if newResultItem is &Type then begin
fldResultType := &Type(newResultItem);
end else begin
fldResultType := nil;
end;
if newResultItem is Package then begin
fldResultPack := Package(newResultItem);
end else begin
fldResultPack := nil;
end;
fldResultItem := newResultItem;
end;
function ImmediateBuilderItemHolder.getResultWith(): Local;
begin
result := fldResultWith;
end;
function ImmediateBuilderItemHolder.getResultItem(): TableItem;
begin
result := fldResultItem;
end;
procedure ImmediateBuilderItemHolder.setHelpersAllowed(newHelpersAllowed: boolean);
begin
fldHelpersAllowed := newHelpersAllowed;
end;
procedure ImmediateBuilderItemHolder.setResultKind(newResultKind: int);
begin
fldResultKind := newResultKind;
end;
procedure ImmediateBuilderItemHolder.setResultType(newResultType: &Type);
begin
fldResultType := newResultType;
fldResultPack := nil;
fldResultWith := nil;
fldResultItem := newResultType;
end;
procedure ImmediateBuilderItemHolder.setResultPack(newResultPack: Package);
begin
fldResultType := nil;
fldResultPack := newResultPack;
fldResultWith := nil;
fldResultItem := newResultPack;
end;
function ImmediateBuilderItemHolder.isHelpersAllowed(): boolean;
begin
result := fldHelpersAllowed;
end;
function ImmediateBuilderItemHolder.getResultKind(): int;
begin
result := fldResultKind;
end;
function ImmediateBuilderItemHolder.getResultType(): &Type;
begin
result := fldResultType;
end;
function ImmediateBuilderItemHolder.getResultPack(): Package;
begin
result := fldResultPack;
end;
{%endregion}
{%region CompilerParallelWorkerRunnable }
constructor CompilerParallelWorkerRunnable.create(parentWorker: CompilerParallelWorker; handler: CompilerRunnable);
begin
inherited create();
fldParentWorker := parentWorker;
fldHandler := handler;
end;
procedure CompilerParallelWorkerRunnable.run();
var
handler: CompilerRunnable;
target: TObject;
begin
with fldParentWorker do begin
handler := fldHandler;
repeat
target := nextTarget();
if target = nil then begin
terminate(nil);
break;
end;
if handler <> nil then try
handler.run(target);
except
on __exception: Exception do begin
terminate(__exception);
break;
end;
end;
until false;
end;
end;
{%endregion}
{%region ProjectSourcesLoader }
procedure ProjectSourcesLoader.findBinarySources(__library: &Library; const __relativePath: UnicodeString);
var
objectName: UnicodeString;
begin
with fldParentProject.excludes, __library.fileSystem.findFirst(__library.directoryPath + __relativePath) do try
repeat
objectName := name;
if ('.' <> objectName) and ('..' <> objectName) and not contains(objectName) then begin
if directory then begin
findBinarySources(__library, __relativePath + objectName + '/');
continue;
end;
if Project.isBinarySourceFileName(objectName) then begin
__library.createSource(__relativePath + objectName, AVTOOConstants.BINARY_SOURCE);
end;
end;
until not findNext();
finally
close();
end;
end;
procedure ProjectSourcesLoader.findTypeSources(__library: &Library; const __relativePath: UnicodeString);
var
objectName: UnicodeString;
begin
with fldParentProject.excludes, __library.fileSystem.findFirst(__library.directoryPath + __relativePath) do try
repeat
objectName := name;
if ('.' <> objectName) and ('..' <> objectName) and not contains(objectName) then begin
if directory then begin
findTypeSources(__library, __relativePath + objectName + '/');
continue;
end;
if Project.isTypeSourceFileName(objectName) then begin
__library.createSource(__relativePath + objectName, AVTOOConstants.TEXT_SOURCE);
end;
end;
until not findNext();
finally
close();
end;
end;
procedure ProjectSourcesLoader.findPackageSources(__library: &Library);
var
objectName: UnicodeString;
begin
with fldParentProject.excludes, __library.fileSystem.findFirst(__library.directoryPath) do try
repeat
objectName := name;
if ('.' <> objectName) and ('..' <> objectName) and not contains(objectName) and not directory and Project.isPackageSourceFileName(objectName) then begin
__library.createSource(objectName, AVTOOConstants.TEXT_SOURCE);
end;
until not findNext();
finally
close();
end;
end;
constructor ProjectSourcesLoader.create(parentProject: Project);
begin
inherited create();
fldParentProject := parentProject;
end;
procedure ProjectSourcesLoader.run(target: TObject);
label
break_label0;
var
index: int;
__type: AnsiString;
directoryPath: UnicodeString;
sources: Source_Array1d;
__library: &Library;
begin
with fldParentProject do begin
__library := target as &Library;
__type := getSourceType(__library);
begin
if __type = TEXT_SOURCE then with __library.fileSystem do begin
directoryPath := __library.directoryPath;
findPackageSources(__library);
if isObjectExists(directoryPath + TEXT_SOURCE_MAIN_PATH) then begin
findTypeSources(__library, TEXT_SOURCE_MAIN_PATH + '/');
goto break_label0;
end;
if isObjectExists(directoryPath + TEXT_SOURCE_ALTERNATIVE_PATH) then begin
findTypeSources(__library, TEXT_SOURCE_ALTERNATIVE_PATH + '/');
end;
goto break_label0;
end;
if __type = BINARY_SOURCE then with __library.fileSystem do begin
directoryPath := __library.directoryPath;
if isObjectExists(directoryPath + BINARY_SOURCE_PATH) then begin
findBinarySources(__library, BINARY_SOURCE_PATH + '/');
end;
goto break_label0;
end;
raise IOException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'source.type.unknown'), [
CoAnsiString.create(__type)
]));
end;
break_label0:
sources := __library.sources.clone();
for index := system.length(sources) - 1 downto 0 do sources[index].loadFromFileStream();
end;
end;
{%endregion}
{%region TableBuilderAnsiStringHolder }
procedure TableBuilderAnsiStringHolder.appendResultString(const suffix: AnsiString);
begin
fldResultString := fldResultString + suffix;
end;
procedure TableBuilderAnsiStringHolder.clear();
begin
fldResultString := '';
end;
function TableBuilderAnsiStringHolder.toString(): AnsiString;
begin
result := fldResultString;
end;
{%endregion}
{%region TableBuilderBinarySource }
destructor TableBuilderBinarySource.destroy;
var
component: TObject;
begin
if getLength() > 1 then begin
component := readComponent(1);
if component is ObjectVector then component.free();
end;
inherited destroy;
end;
{%endregion}
{%region TableBuilderClassTypeHolder }
procedure TableBuilderClassTypeHolder.setResultClassType(newResultClassType: ClassType);
begin
fldResultClassType := newResultClassType;
end;
function TableBuilderClassTypeHolder.getResultClassType(): ClassType;
begin
result := fldResultClassType;
end;
procedure TableBuilderClassTypeHolder.setResultType(newResultType: &Type);
begin
if (newResultType <> nil) and not(newResultType is ru.malik.elaborarer.avtoo.lang.ClassType) then begin
raise IllegalArgumentException.create(AnsiString.format(AResource.readUnitResourceAsAnsiString(pascalx.lang.UNIT_NAME, 'illegal-argument.must-have-type'), [
CoAnsiString.create('newResultType'), CoAnsiString.create(Lang.classFor(ru.malik.elaborarer.avtoo.lang.ClassType).getSimpleName())
]));
end;
fldResultClassType := ru.malik.elaborarer.avtoo.lang.ClassType(newResultType);
end;
function TableBuilderClassTypeHolder.isHelpersAllowed(): boolean;
begin
result := false;
end;
function TableBuilderClassTypeHolder.getResultType(): &Type;
begin
result := fldResultClassType;
end;
{%endregion}
{%region TableBuilderOperatorAndTypeHolder }
procedure TableBuilderOperatorAndTypeHolder.setResultKind(newResultKind: int);
begin
fldResultKind := newResultKind;
end;
procedure TableBuilderOperatorAndTypeHolder.setResultType(newResultType: &Type);
begin
fldResultType := newResultType;
end;
function TableBuilderOperatorAndTypeHolder.isHelpersAllowed(): boolean;
begin
result := false;
end;
function TableBuilderOperatorAndTypeHolder.getResultKind(): int;
begin
result := fldResultKind;
end;
function TableBuilderOperatorAndTypeHolder.getResultType(): &Type;
begin
result := fldResultType;
end;
{%endregion}
{%region TableBuilderSourcesLexer }
constructor TableBuilderSourcesLexer.create(__lexer: Lexer);
begin
inherited create();
fldLexer := __lexer;
end;
procedure TableBuilderSourcesLexer.run(target: TObject);
const
INT2_0 : int2 = ( 0, 0 );
INT2_MAX_VALUE: int2 = ( CoInt.MAX_VALUE, CoInt.MAX_VALUE );
var
index: int;
length: int;
line: UnicodeString;
sequence: uchar_Array1d;
empty: uchar_Array1d;
lines: uchar_Array2d;
content: UnicodeString_Array1d;
source: TextSource;
begin
source := target as TextSource;
content := source.contents.clone();
length := system.length(content);
lines := &Array.newUChar2d(length);
empty := &Array.newUChar1d(1);
for index := length - 1 downto 0 do begin
line := content[index];
length := line.length;
if length <= 0 then begin
lines[index] := empty;
continue;
end;
sequence := &Array.newUChar1d(length + 1);
line.getChars(1, length + 1, sequence, 0);
lines[index] := sequence;
end;
fldLexer.split(lines, INT2_0, INT2_MAX_VALUE, source);
end;
{%endregion}
{%region TableBuilderSourcesParser }
procedure TableBuilderSourcesParser.run(target: TObject);
label
break_label0,
break_label1;
var
isField: boolean;
kind: int;
curly: int;
finish: int;
bracket: int;
parenth: int;
llength: int;
tlength: int;
position: int;
lcapacity: int;
tcapacity: int;
equalsPosition: int;
leafa: int_Array1d;
leafb: int_Array1d;
treea: int_Array2d;
treeb: int_Array2d;
source: TableBuilderTextSource;
exception: TextSourceException;
begin
with AVTOOConstants do begin
source := target as TableBuilderTextSource;
if Project.isPackageSourceFileName(source.textSourcePath) or (source.getLexemeKind(0) = L_END) then exit;
position := 0;
repeat
inc(position);
kind := source.getLexemeKind(position);
if kind = L_END then exit;
until kind = SEMICOLON;
tlength := 1;
tcapacity := $0f;
treea := &Array.newInt2d(tcapacity);
begin
inc(position);
kind := source.getLexemeKind(position);
if kind <> DCL_IMPORT then begin
treea[0] := [ -1 ];
end else begin
treea[0] := [ position ];
repeat
repeat
inc(position);
kind := source.getLexemeKind(position);
if kind = L_END then goto break_label0;
until kind = SEMICOLON;
inc(position);
kind := source.getLexemeKind(position);
until kind <> DCL_IMPORT;
end;
if kind = L_END then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'expected.definition.type'));
exception.source := source;
exception.position := position;
raise exception;
end;
repeat
llength := 1;
lcapacity := $0f;
leafa := &Array.newInt1d(lcapacity);
leafa[0] := position;
begin
repeat
inc(position);
kind := source.getLexemeKind(position);
if kind = L_END then goto break_label1;
until kind = CURLY_OPENED;
repeat
inc(position);
kind := source.getLexemeKind(position);
if (kind = L_END) or (kind = CURLY_CLOSED) then break;
if llength = lcapacity then begin
lcapacity := (lcapacity shl 1) or 1;
leafb := &Array.newInt1d(lcapacity);
&Array.copyPrimitives(leafa, 0, leafb, 0, llength);
leafa := leafb;
end;
leafa[llength] := position;
inc(llength);
isField := false;
equalsPosition := -1;
repeat
case kind of
L_END: begin
goto break_label1;
end;
COLON,
SEMICOLON,
CURLY_OPENED: begin
break;
end;
L_NAME: begin
equalsPosition := position + 1;
end;
EQUAL: begin
if equalsPosition = position then begin
isField := true;
break;
end;
end;
end;
inc(position);
kind := source.getLexemeKind(position);
until false;
if kind <> SEMICOLON then begin
if isField then begin
finish := SEMICOLON;
end else begin
finish := CURLY_CLOSED;
end;
curly := 0;
bracket := 0;
parenth := 0;
repeat
case kind of
CURLY_OPENED: begin
inc(curly);
end;
CURLY_CLOSED: begin
if curly = 0 then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'extra.curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
dec(curly);
end;
BRACKET_OPENED: begin
inc(bracket);
end;
BRACKET_CLOSED: begin
if bracket = 0 then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'extra.bracket'));
exception.source := source;
exception.position := position;
raise exception;
end;
dec(bracket);
end;
PARENTH_OPENED: begin
inc(parenth);
end;
PARENTH_CLOSED: begin
if parenth = 0 then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'extra.parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
dec(parenth);
end;
L_END: begin
if curly > 0 then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-closed.curly'));
exception.source := source;
exception.position := position;
raise exception;
end;
if bracket > 0 then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-closed.bracket'));
exception.source := source;
exception.position := position;
raise exception;
end;
if parenth > 0 then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'not-closed.parenth'));
exception.source := source;
exception.position := position;
raise exception;
end;
goto break_label1;
end;
end;
if (kind = finish) and ((curly or bracket or parenth) = 0) then break;
inc(position);
kind := source.getLexemeKind(position);
until false;
end;
until false;
end;
break_label1:
if kind = L_END then begin
exception := TextSourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unexpected-end.source'));
exception.source := source;
exception.position := position;
raise exception;
end;
if llength = lcapacity then begin
lcapacity := (lcapacity shl 1) or 1;
leafb := &Array.newInt1d(lcapacity);
&Array.copyPrimitives(leafa, 0, leafb, 0, llength);
leafa := leafb;
end;
leafa[llength] := position;
inc(llength);
if llength <> lcapacity then begin
lcapacity := llength;
leafb := &Array.newInt1d(lcapacity);
&Array.copyPrimitives(leafa, 0, leafb, 0, llength);
leafa := leafb;
end;
if tlength = tcapacity then begin
tcapacity := (tcapacity shl 1) or 1;
treeb := &Array.newInt2d(tcapacity);
&Array.copyArrays(treea, 0, treeb, 0, tlength);
treea := treeb;
end;
treea[tlength] := leafa;
inc(tlength);
inc(position);
until source.getLexemeKind(position) = L_END;
end;
break_label0:
if tlength <> tcapacity then begin
tcapacity := tlength;
treeb := &Array.newInt2d(tcapacity);
&Array.copyArrays(treea, 0, treeb, 0, tlength);
treea := treeb;
end;
source.parsingTree := treea;
end;
end;
{%endregion}
{%region TableBuilderSourcesReader }
constructor TableBuilderSourcesReader.create(__programme: Programme);
begin
inherited create();
fldProgramme := __programme;
end;
procedure TableBuilderSourcesReader.run(target: TObject);
var
index: int;
length: int;
__type: int;
__name: int;
__args: int_Array1d;
chars: uchar_Array1d;
store: TObject_Array1d;
iend: Chunk;
version: Chunk;
constants: Chunk;
element: TObject;
chunks: ChunkArray;
source: BinarySource;
vector: ObjectVector;
__programme: Programme;
exception: BinarySourceException;
begin
with AVTOORecompilable do begin
source := target as BinarySource;
chunks := source.chunks;
length := chunks.getLength();
if length < 3 then begin
exception := BinarySourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'binary.chunk.too-low'));
exception.source := source;
exception.offset := 0;
raise exception;
end;
dec(length);
version := chunks.readComponent(0);
constants := chunks.readComponent(1);
iend := chunks.readComponent(length);
if version.&type <> CHUNK_VERS then begin
exception := BinarySourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'binary.chunk.1st'));
exception.source := source;
exception.position := 0;
raise exception;
end;
if constants.&type <> CHUNK_CONS then begin
exception := BinarySourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'binary.chunk.2nd'));
exception.source := source;
exception.position := 1;
raise exception;
end;
if iend.&type <> CHUNK_IEND then begin
exception := BinarySourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'binary.chunk.last'));
exception.source := source;
exception.position := length;
raise exception;
end;
if version.readInt() <> VERSION_AVTR then begin
exception := BinarySourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'binary.unsupported-version'));
exception.source := source;
exception.offset := version.dataOffsetToSourceOffset(0);
raise exception;
end;
vector := ObjectVector.create(true);
try
vector.append(nil);
__programme := fldProgramme;
while constants.available() > 0 do case constants.readUnsignedShort() of
CONST_Z: begin
vector.append(CoBoolean.create(constants.readBoolean()));
end;
CONST_C: begin
vector.append(CoUChar.create(constants.readUChar()));
end;
CONST_R: begin
vector.append(VCoReal.create(constants.readReal()));
end;
CONST_D: begin
vector.append(VCoDouble.create(constants.readDouble()));
end;
CONST_D2: begin
vector.append(VCoDouble2.create(constants.readDouble2()));
end;
CONST_D4: begin
vector.append(VCoDouble4.create(constants.readDouble4()));
end;
CONST_D8: begin
vector.append(VCoDouble8.create(constants.readDouble8()));
end;
CONST_F: begin
vector.append(VCoFloat.create(constants.readFloat()));
end;
CONST_F2: begin
vector.append(VCoFloat2.create(constants.readFloat2()));
end;
CONST_F4: begin
vector.append(VCoFloat4.create(constants.readFloat4()));
end;
CONST_F8: begin
vector.append(VCoFloat8.create(constants.readFloat8()));
end;
CONST_B: begin
vector.append(VCoByte.create(constants.readByte()));
end;
CONST_B2: begin
vector.append(VCoByte2.create(long2(constants.readByte2())));
end;
CONST_B4: begin
vector.append(VCoByte4.create(long4(constants.readByte4())));
end;
CONST_B8: begin
vector.append(VCoByte8.create(long8(constants.readByte8())));
end;
CONST_S: begin
vector.append(VCoShort.create(constants.readShort()));
end;
CONST_S2: begin
vector.append(VCoShort2.create(long2(constants.readShort2())));
end;
CONST_S4: begin
vector.append(VCoShort4.create(long4(constants.readShort4())));
end;
CONST_S8: begin
vector.append(VCoShort8.create(long8(constants.readShort8())));
end;
CONST_I: begin
vector.append(VCoInt.create(constants.readInt()));
end;
CONST_I2: begin
vector.append(VCoInt2.create(long2(constants.readInt2())));
end;
CONST_I4: begin
vector.append(VCoInt4.create(long4(constants.readInt4())));
end;
CONST_I8: begin
vector.append(VCoInt8.create(long8(constants.readInt8())));
end;
CONST_J: begin
vector.append(VCoLong.create(constants.readLong()));
end;
CONST_J2: begin
vector.append(VCoLong2.create(constants.readLong2()));
end;
CONST_J4: begin
vector.append(VCoLong4.create(constants.readLong4()));
end;
CONST_J8: begin
vector.append(VCoLong8.create(constants.readLong8()));
end;
CONST_ST: begin
chars := &Array.newUChar1d(constants.readUnsignedShort());
constants.readFully(chars);
vector.append(CoUnicodeString.create(UnicodeString.create(chars)));
end;
CONST_PK: begin
__name := constants.readInt();
vector.append(PackageElement.create(__programme, __name));
end;
CONST_TP: begin
__name := constants.readInt();
vector.append(TypeElement.create(__programme, __name));
end;
CONST_FL: begin
__type := constants.readInt();
__name := constants.readInt();
vector.append(FieldElement.create(__programme, __type, __name));
end;
CONST_PR: begin
__type := constants.readInt();
__name := constants.readInt();
vector.append(PropertyElement.create(__programme, __type, __name));
end;
CONST_CL: begin
__type := constants.readInt();
__name := constants.readInt();
length := constants.readUnsignedShort();
if length > LIMIT_ARGUMENTS_LENGTH then begin
exception := BinarySourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'too-many.arguments.class-member'));
exception.source := source;
exception.offset := constants.dataOffsetToSourceOffset(constants.position);
raise exception;
end;
__args := &Array.newInt1d(length);
for index := 0 to length - 1 do __args[index] := constants.readInt();
vector.append(CallableElement.create(__programme, __type, __name, __args));
end;
else
exception := BinarySourceException.create(AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'unknown.type.constant'));
exception.source := source;
exception.offset := constants.dataOffsetToSourceOffset(constants.position);
raise exception;
end;
store := vector.clone();
except
vector.free();
raise;
end;
source.writeComponent(1, vector);
for index := system.length(store) - 1 downto 0 do begin
element := store[index];
if element is RecompilableElement then RecompilableElement(element).constants := store;
end;
end;
end;
{%endregion}
{%region TableBuilderTextSource }
{%endregion}
{%region TableBuilderVectorAndTypeHolder }
procedure TableBuilderVectorAndTypeHolder.setResultType(newResultType: &Type);
begin
fldResultType := newResultType;
end;
function TableBuilderVectorAndTypeHolder.isHelpersAllowed(): boolean;
begin
result := false;
end;
function TableBuilderVectorAndTypeHolder.getResultType(): &Type;
begin
result := fldResultType;
end;
{%endregion}
{%region ImmediateBuilderForBinarySources }
constructor ImmediateBuilderForBinarySources.create(parent: ImmediateBuilder);
begin
inherited create();
fldParent := parent;
end;
procedure ImmediateBuilderForBinarySources.run(target: TObject);
var
index: int;
__member: Member;
parent: ImmediateBuilder;
enclosing: ru.malik.elaborarer.avtoo.lang.ClassType;
begin
parent := fldParent;
enclosing := target as ru.malik.elaborarer.avtoo.lang.ClassType;
for index := 0 to enclosing.getLength() - 1 do begin
__member := enclosing.readComponent(index);
if __member is Callable then parent.readCallableBody(Callable(__member));
end;
end;
{%endregion}
{%region ImmediateBuilderForTextSources }
constructor ImmediateBuilderForTextSources.create(parent: ImmediateBuilder);
begin
inherited create();
fldParent := parent;
end;
procedure ImmediateBuilderForTextSources.run(target: TObject);
var
mindex: int;
mlength: int;
blength: int;
buffer: TObject_Array1d;
__member: Member;
__constructor: Node;
__callable: Callable;
parent: ImmediateBuilder;
thisConstructor: InstInit;
enclosing: ru.malik.elaborarer.avtoo.lang.ClassType;
exception: TextSourceException;
begin
parent := fldParent;
enclosing := target as ru.malik.elaborarer.avtoo.lang.ClassType;
mlength := enclosing.getLength();
for mindex := 0 to mlength - 1 do begin
__member := enclosing.readComponent(mindex);
if __member is Callable then parent.parseCallableBody(Callable(__member));
end;
buffer := &Array.newTObject1d(mlength);
for mindex := 0 to mlength - 1 do begin
__member := enclosing.readComponent(mindex);
if not(__member is InstInit) then continue;
thisConstructor := InstInit(__member);
buffer[0] := __member;
blength := 1;
repeat
__constructor := thisConstructor.code.root.readComponent(0);
if __constructor.instruction <> AVTOOConstants.INVOKE_SPECIAL then break;
__callable := __constructor.operand1 as Callable;
if not(__callable is InstInit) or (__callable.parentType <> enclosing) then break;
if &Array.indexOf(__callable, buffer, 0, blength) >= 0 then begin
exception := TextSourceException.create(AnsiString.format(
AResource.readUnitResourceAsAnsiString(ru.malik.elaborarer.avtoo.compiler.UNIT_NAME, 'constructor.recursive-invocation'), [
CoObject.create(__callable)
]
));
exception.source := TextSource(Lang.cast(enclosing.source, TextSource));
exception.position := __constructor.position;
raise exception;
end;
thisConstructor := InstInit(__callable);
buffer[blength] := __callable;
inc(blength);
until false;
end;
end;
function ImmediateBuilderForTextSources.createThreadObject(): TObject;
begin
result := ImmediateBuilderItemHolder.create();
end;
{%endregion}
{%region ImmediateBuilderUnaryOperation }
constructor ImmediateBuilderUnaryOperation.create(__position, __operation: int);
begin
inherited create();
fldPosition := __position;
fldOperation := __operation;
end;
constructor ImmediateBuilderUnaryOperation.create(__position, __operation: int; __newType: &Type);
begin
inherited create();
fldPosition := __position;
fldOperation := __operation;
fldNewType := __newType;
end;
{%endregion}
{%region} initialization
Lang.registerInterfaces([
typeInfo(CompilerRunnable),
typeInfo(CompilerThreadObjectCreator),
typeInfo(OperatorHolder),
typeInfo(TypeHolder),
typeInfo(PackageHolder)
]);
LanguageLexer.initialize();
DocumentLexer.initialize();
{%endregion}
{%region} finalization
LanguageLexer.finalize();
{%endregion}
end.