{
Этот исходный код является частью проекта ПВТ-ОО.
Copyright © 2021 Малик Разработчик
Это свободная программа: вы можете перераспространять её и/или
изменять её на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она может быть полезна,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<http://www.gnu.org/licenses/>.
}
unit ru.malik.elaborarer.avt.table;
{$MODE DELPHI}
interface
uses
pascalx.lang,
pascalx.utils,
ru.malik.elaborarer.avt.programme,
ru.malik.elaborarer.avt.lexer,
ru.malik.elaborarer.avt.constant;
{$ASMMODE INTEL,CALLING REGISTER,TYPEINFO ON}
{%region pulic }
type
AVTTableBuilder = class;
AVTTableBuilder = class(AVTConstantExpression)
private
class function skipParenthesis(source: AVTSource; pos: int): int; static;
class function skipCurly(source: AVTSource; pos: int): int; static;
class function skipValue(source: AVTSource; pos: int): int; static;
protected
class function parseOperator(source: AVTSource; pos: int): int; static;
private
fldTypeObjectRef: AVTTypeStructured;
fldTypeStructRef: AVTTypeStructured;
fldTypeThrowableRef: AVTTypeStructured;
function parseArguments(source: AVTSource; typeRef: AVTTypeStructured; pos: int; arguments: Vector): int;
function parseThrows(source: AVTSource; typeRef: AVTTypeStructured; methodRef: AVTMethod; pos: int): int;
function parseStructuredTypeName(source: AVTSource; typeRef: AVTTypeStructured; pos: int): AVTTypeStructured;
public
procedure parsePackage(source: AVTSource);
procedure parseTypes(source: AVTSource);
procedure parseImport(source: AVTSource);
procedure parseSupertypes(source: AVTSource);
procedure parseMembers(typeRef: AVTTypeStructured);
procedure parseFields(typeRef: AVTTypeStructured);
procedure parseProperties(typeRef: AVTTypeStructured);
end;
{%endregion}
implementation
{%region AVTTableBuilder }
class function AVTTableBuilder.skipParenthesis(source: AVTSource; pos: int): int;
var
counter: int;
begin
if source.getLexemeType(pos) = CHAR_PARENTH_OPENED then begin
counter := 1;
repeat
inc(pos);
case source.getLexemeType(pos) of
CHAR_PARENTH_OPENED: begin
inc(counter);
end;
CHAR_PARENTH_CLOSED: begin
dec(counter);
if counter = 0 then begin
inc(pos);
break;
end;
end;
AVT_END:
raise AVTCompilerException.create('")" expected', source, pos);
end;
until false;
end;
result := pos;
end;
class function AVTTableBuilder.skipCurly(source: AVTSource; pos: int): int;
var
counter: int;
begin
if source.getLexemeType(pos) = CHAR_CURLY_OPENED then begin
counter := 1;
repeat
inc(pos);
case source.getLexemeType(pos) of
CHAR_CURLY_OPENED: begin
inc(counter);
end;
CHAR_CURLY_CLOSED: begin
dec(counter);
if counter = 0 then begin
inc(pos);
break;
end;
end;
AVT_END:
raise AVTCompilerException.create('"}" expected', source, pos);
end;
until false;
end;
result := pos;
end;
class function AVTTableBuilder.skipValue(source: AVTSource; pos: int): int;
var
counterCurly: int;
counterBracket: int;
counterParenth: int;
begin
counterCurly := 0;
counterBracket := 0;
counterParenth := 0;
repeat
case source.getLexemeType(pos) of
CHAR_CURLY_OPENED: begin
inc(counterCurly);
end;
CHAR_CURLY_CLOSED: begin
dec(counterCurly);
end;
CHAR_BRACKET_OPENED: begin
inc(counterBracket);
end;
CHAR_BRACKET_CLOSED: begin
dec(counterBracket);
end;
CHAR_PARENTH_OPENED: begin
inc(counterParenth);
end;
CHAR_PARENTH_CLOSED: begin
dec(counterParenth);
end;
CHAR_SEMICOLON: begin
if (counterCurly or counterBracket or counterParenth) = 0 then break;
end;
AVT_END: begin
raise AVTCompilerException.create('";" expected', source, pos);
end;
end;
inc(pos);
until false;
result := pos;
end;
class function AVTTableBuilder.parseOperator(source: AVTSource; pos: int): int;
var
lexemeType: int;
operatorKind: int;
begin
lexemeType := source.getLexemeType(pos);
case lexemeType of
CHAR_BRACKET_OPENED: begin
inc(pos);
if source.getLexemeType(pos) <> CHAR_BRACKET_CLOSED then begin
raise AVTCompilerException.create('"]" expected', source, pos);
end;
inc(pos);
if source.getLexemeType(pos) = CHAR_EQUALS then begin
inc(pos);
operatorKind := SET_ARRAY_ELEMENT;
end else begin
operatorKind := GET_ARRAY_ELEMENT;
end;
end;
CHAR_PARENTH_OPENED: begin
inc(pos);
if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then begin
raise AVTCompilerException.create('")" expected', source, pos);
end;
inc(pos);
operatorKind := INVOKE_VIRTUAL;
end;
OPER_BIT_NOT, OPER_BIT_AND, OPER_BIT_OR, OPER_BIT_XOR, OPER_SCAL_PLUS, OPER_SCAL_MINUS,
OPER_SCAL_MUL, OPER_SCAL_DIV, OPER_SCAL_DIVU, OPER_SCAL_REM, OPER_SCAL_REMU, OPER_SCAL_ADD, OPER_SCAL_SUB,
OPER_SCAL_SAR, OPER_SCAL_SAL, OPER_SCAL_SHR, OPER_SCAL_G, OPER_SCAL_GE, OPER_SCAL_L, OPER_SCAL_LE,
OPER_VECT_UNPCKL, OPER_VECT_UNPCKU, OPER_VECT_PACK, OPER_VECT_PLUS, OPER_VECT_MINUS,
OPER_VECT_MUL, OPER_VECT_DIV, OPER_VECT_ADD, OPER_VECT_SUB, OPER_VECT_SAR, OPER_VECT_SAL, OPER_VECT_SHR,
OPER_VECT_G, OPER_VECT_GE, OPER_VECT_L, OPER_VECT_LE, OPER_VECT_E, OPER_VECT_NE,
OPER_VECT_MULS, OPER_VECT_ADDS, OPER_VECT_SUBS, OPER_VECT_MULU, OPER_VECT_ADDU, OPER_VECT_SUBU: begin
inc(pos);
operatorKind := lexemeType;
end
else
raise AVTCompilerException.create('Valid operator symbol expected', source, pos);
end;
source.position := pos;
result := operatorKind;
end;
function AVTTableBuilder.parseArguments(source: AVTSource; typeRef: AVTTypeStructured; pos: int; arguments: Vector): int;
var
names: Vector;
nameAsValue: Value;
typeParsedRef: AVTType;
argumentName: AnsiString;
begin
names := Vector.create();
try
if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then repeat
typeParsedRef := parseType(typeRef, pos);
if typeParsedRef.isVoid() then begin
raise AVTCompilerException.create('The type void is an invalid type for parameter', source, pos);
end;
pos := source.position;
if source.getLexemeType(pos) <> LITR_NAME then begin
raise AVTCompilerException.create('Parameter name expected', source, pos);
end;
argumentName := source.getLexemeAnsiString(pos);
nameAsValue := ValueOfAnsiString.create(argumentName);
if names.contains(nameAsValue) then begin
raise AVTCompilerException.create('Duplicate parameter ' + argumentName, source, pos);
end;
names.append(nameAsValue);
arguments.append(ValueOfObject.create(AVTVariable.create(typeParsedRef, argumentName, source, pos)));
inc(pos);
case source.getLexemeType(pos) of
CHAR_COMMA: begin
inc(pos);
end;
CHAR_PARENTH_CLOSED: begin
break;
end
else
raise AVTCompilerException.create('")" expected', source, pos);
end;
until false;
finally
names.free();
end;
result := pos + 1;
end;
function AVTTableBuilder.parseThrows(source: AVTSource; typeRef: AVTTypeStructured; methodRef: AVTMethod; pos: int): int;
var
typeParsedRef: AVTTypeStructured;
typeThrowableRef: AVTTypeStructured;
begin
typeThrowableRef := fldTypeThrowableRef;
repeat
typeParsedRef := parseStructuredTypeName(source, typeRef, pos);
if not typeParsedRef.isImplements(typeThrowableRef) then begin
raise AVTCompilerException.create('No exception of type ' + typeParsedRef.fullName + ' can be thrown; an exception type must be subtype of ' + typeThrowableRef.fullName, source, pos);
end;
if methodRef.isThrows(typeParsedRef) then begin
raise AVTCompilerException.create('Duplicate exception ' + typeParsedRef.fullName, source, pos);
end;
methodRef.addThrows(typeParsedRef);
pos := source.position;
if source.getLexemeType(pos) <> CHAR_COMMA then break;
inc(pos);
until false;
result := pos;
end;
function AVTTableBuilder.parseStructuredTypeName(source: AVTSource; typeRef: AVTTypeStructured; pos: int): AVTTypeStructured;
var
itemParsedRef: AVTItem;
begin
if source.getLexemeType(pos) <> LITR_NAME then begin
raise AVTCompilerException.create('Type or package name expected', source, pos);
end;
itemParsedRef := resolveName(source.getLexemeAnsiString(pos), typeRef, pos);
if itemParsedRef is AVTPackage then begin
result := parseFullyQualifiedTypeName(AVTPackage(itemParsedRef), typeRef, pos + 1);
exit;
end;
if itemParsedRef is AVTTypeStructured then begin
source.position := pos + 1;
result := AVTTypeStructured(itemParsedRef);
exit;
end;
raise AVTCompilerException.create('Type or package name expected', source, pos);
end;
procedure AVTTableBuilder.parsePackage(source: AVTSource);
var
pos: int;
lxt: int;
packageName: AnsiString;
packageRef0: AVTPackage;
packageRef1: AVTPackage;
programme: AVTProgramme;
begin
packageRef0 := nil;
programme := self.programme;
if source.getLexemeType(0) <> AVT_PACKAGE then begin
raise AVTCompilerException.create('"package" expected', source, 0);
end;
pos := 1;
repeat
if source.getLexemeType(pos) <> LITR_NAME then begin
raise AVTCompilerException.create('Package name expected', source, pos);
end;
packageName := source.getLexemeAnsiString(pos);
if packageRef0 = nil then begin
packageRef1 := programme.getPackage(packageName);
end else begin
packageRef1 := packageRef0.getSubpackage(packageName);
end;
if packageRef1 = nil then begin
packageRef1 := AVTPackage.create(programme, packageRef0, packageName);
end;
packageRef0 := packageRef1;
inc(pos);
lxt := source.getLexemeType(pos);
if lxt <> CHAR_PERIOD then break;
inc(pos);
until false;
if lxt <> CHAR_SEMICOLON then begin
raise AVTCompilerException.create('";" expected', source, pos);
end;
source.position := pos + 1;
source.package := packageRef0;
end;
procedure AVTTableBuilder.parseTypes(source: AVTSource);
var
pos: int;
lxt: int;
flags: int;
typeName: AnsiString;
typeDoc: UnicodeString;
packageRef: AVTPackage;
begin
pos := source.position;
packageRef := source.package;
repeat
{ раздел импортов }
lxt := source.getLexemeType(pos);
if (lxt <> AVT_IMPORT) and (lxt <> LITR_NAME) and (lxt <> CHAR_PERIOD) and (lxt <> OPER_SCAL_MUL) and (lxt <> CHAR_SEMICOLON) then break;
inc(pos);
until false;
repeat
{ документация }
typeDoc := '';
if lxt = LITR_DOCUMENTATION then begin
typeDoc := source.getLexemeUnicodeString(pos);
inc(pos);
end;
{ видимость }
case source.getLexemeType(pos) of
AVT_PUBLISHED, AVT_PROTECTED, AVT_PRIVATE: begin
raise AVTCompilerException.create('Type can not have published, protected or private visibility', source, pos);
end;
AVT_PUBLIC: begin
flags := FLAG_PUBLIC;
inc(pos);
end;
AVT_PACKAGE: begin
flags := FLAG_PACKAGE;
inc(pos);
end
else
flags := FLAG_SOURCE;
end;
{ абстрактность }
case source.getLexemeType(pos) of
AVT_ABSTRACT: begin
flags := flags or FLAG_ABSTRACT;
inc(pos);
end;
AVT_FINAL: begin
flags := flags or FLAG_FINAL;
inc(pos);
end;
end;
{ разновидность }
case source.getLexemeType(pos) of
AVT_CLASS: begin
inc(pos);
end;
AVT_STRUCT: begin
if (flags and FLAG_ABSTRACT) <> 0 then begin
raise AVTCompilerException.create('Structure can not be abstract', source, pos);
end;
flags := flags or FLAG_STRUCT;
inc(pos);
end;
AVT_SERVICE: begin
if (flags and FLAG_FINAL) <> 0 then begin
raise AVTCompilerException.create('Service can not be final', source, pos);
end;
flags := flags or FLAG_SERVICE;
inc(pos);
end;
AVT_INTERFACE: begin
if (flags and FLAG_FINAL) <> 0 then begin
raise AVTCompilerException.create('Interface can not be final', source, pos);
end;
flags := flags or (FLAG_INTERFACE or FLAG_ABSTRACT);
inc(pos);
end
else
raise AVTCompilerException.create('"class", "service", "interface" or "struct" expected', source, pos);
end;
{ название }
if source.getLexemeType(pos) <> LITR_NAME then begin
raise AVTCompilerException.create('Type name expected', source, pos);
end;
typeName := source.getLexemeAnsiString(pos);
if packageRef.fullName = 'avt.lang' then begin
if (typeName = 'Object') and (flags <> FLAG_PUBLIC) then begin
raise AVTCompilerException.create('This type must be a "public class" type', source, pos);
end;
if (typeName = 'Struct') and (flags <> FLAG_PUBLIC) then begin
raise AVTCompilerException.create('This type must be a "public class" type', source, pos);
end;
end;
if packageRef.getSubpackage(typeName) <> nil then begin
raise AVTCompilerException.create('Type name conflicts with same package name ' + typeName, source, pos);
end;
if packageRef.getType(typeName, false) <> nil then begin
raise AVTCompilerException.create('Duplicate declaration of type ' + typeName, source, pos);
end;
AVTTypeStructured.create(packageRef, false, flags, typeName, source, pos, typeDoc);
pos := skipCurly(source, skipParenthesis(source, pos + 1));
lxt := source.getLexemeType(pos);
until lxt = AVT_END;
end;
procedure AVTTableBuilder.parseImport(source: AVTSource);
var
isType: boolean;
pos: int;
lxt: int;
vis: int;
periodPos: int;
fullName: AnsiString;
typeName: AnsiString;
packageName: AnsiString;
packageRef: AVTPackage;
typeRef: AVTTypeStructured;
programme: AVTProgramme;
begin
pos := source.position;
programme := self.programme;
packageRef := programme.getPackage('avt.lang');
if packageRef <> nil then source.addImportedPackage(packageRef);
while source.getLexemeType(pos) = AVT_IMPORT do begin
inc(pos);
if source.getLexemeType(pos) <> LITR_NAME then begin
raise AVTCompilerException.create('Package name expected', source, pos);
end;
fullName := source.getLexemeAnsiString(pos);
isType := true;
inc(pos);
repeat
case source.getLexemeType(pos) of
CHAR_PERIOD: begin
if not isType then begin
raise AVTCompilerException.create('";" expected', source, pos);
end;
inc(pos);
case source.getLexemeType(pos) of
LITR_NAME: begin
fullName := fullName + '.' + source.getLexemeAnsiString(pos);
inc(pos);
end;
OPER_SCAL_MUL: begin
isType := false;
inc(pos);
end
else
raise AVTCompilerException.create('Name or "*" expected', source, pos);
end;
end;
CHAR_SEMICOLON: begin
if isType then begin
periodPos := stringLastIndexOf('.', fullName);
if periodPos <= 0 then begin
raise AVTCompilerException.create('Type not found: ' + fullName, source, pos);
end;
packageName := stringCopy(fullName, 1, periodPos);
typeName := stringCopy(fullName, periodPos + 1);
packageRef := programme.getPackage(packageName);
if packageRef = nil then begin
raise AVTCompilerException.create('Package not found: ' + packageName, source, pos);
end;
typeRef := packageRef.getType(typeName) as AVTTypeStructured;
if typeRef = nil then begin
raise AVTCompilerException.create('Type not found: ' + fullName, source, pos);
end;
if source.getImportedType(typeName) <> nil then begin
raise AVTCompilerException.create('Type already imported: ' + typeName, source, pos);
end;
if source.getDeclaredType(typeName) <> nil then begin
raise AVTCompilerException.create('Type already declared: ' + typeName, source, pos);
end;
vis := typeRef.visibility;
if (vis <> AVT_PUBLIC) and ((vis <> AVT_PACKAGE) or (typeRef.package <> source.package)) and ((vis <> AVT_SOURCE) or (typeRef.source <> source)) then begin
raise AVTCompilerException.create('The type ' + typeRef.fullName + ' is not visible', source, pos);
end;
source.addImportedType(typeRef);
end else begin
packageRef := programme.getPackage(fullName);
if packageRef = nil then begin
raise AVTCompilerException.create('Package not found: ' + fullName, source, pos);
end;
if source.isImportedPackage(packageRef) then begin
raise AVTCompilerException.create('Package already imported: ' + fullName, source, pos);
end;
source.addImportedPackage(packageRef);
end;
inc(pos);
break;
end
else
if isType then begin
raise AVTCompilerException.create('"." or ";" expected', source, pos);
end;
raise AVTCompilerException.create('";" expected', source, pos);
end;
until false;
end;
lxt := source.getLexemeType(pos);
if (lxt = LITR_NAME) or (lxt = CHAR_PERIOD) or (lxt = OPER_SCAL_MUL) or (lxt = CHAR_SEMICOLON) then begin
raise AVTCompilerException.create('"import" expected', source, pos);
end;
end;
procedure AVTTableBuilder.parseSupertypes(source: AVTSource);
var
isExtends: boolean;
pos: int;
e: Enumeration;
typeRef: AVTTypeStructured;
typeClassRef: AVTTypeStructured;
typeParsedRef: AVTTypeStructured;
typeObjectRef: AVTTypeStructured;
typeStructRef: AVTTypeStructured;
typeStringRef: AVTTypeStructured;
typeThrowableRef: AVTTypeStructured;
packageAvtLangRef: AVTPackage;
begin
typeObjectRef := fldTypeObjectRef;
typeStructRef := fldTypeStructRef;
if (typeObjectRef = nil) or (typeStructRef = nil) then begin
packageAvtLangRef := programme.getPackage('avt.lang');
if packageAvtLangRef <> nil then begin
typeClassRef := packageAvtLangRef.getType('Class') as AVTTypeStructured;
typeObjectRef := packageAvtLangRef.getType('Object') as AVTTypeStructured;
typeStructRef := packageAvtLangRef.getType('Struct') as AVTTypeStructured;
typeStringRef := packageAvtLangRef.getType('String') as AVTTypeStructured;
typeThrowableRef := packageAvtLangRef.getType('Throwable') as AVTTypeStructured;
fldTypeObjectRef := typeObjectRef;
fldTypeStructRef := typeStructRef;
fldTypeThrowableRef := typeThrowableRef;
end;
if typeClassRef = nil then begin
raise AVTGlobalException.create('Essential type not found: avt.lang.Class');
end;
if typeObjectRef = nil then begin
raise AVTGlobalException.create('Essential type not found: avt.lang.Object');
end;
if typeStructRef = nil then begin
raise AVTGlobalException.create('Essential type not found: avt.lang.Struct');
end;
if typeStringRef = nil then begin
raise AVTGlobalException.create('Essential type not found: avt.lang.String');
end;
if typeThrowableRef = nil then begin
raise AVTGlobalException.create('Essential type not found: avt.lang.Throwable');
end;
end;
e := source.declaredTypes();
while e.hasMoreElements() do begin
typeRef := e.nextElement().objectValue() as AVTTypeStructured;
pos := typeRef.declarationPosition + 1;
if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
if typeRef.isStruct() then begin
typeRef.setExtends(typeStructRef);
end else
if typeRef <> typeObjectRef then begin
typeRef.setExtends(typeObjectRef);
end;
end else begin
isExtends := true;
repeat
inc(pos);
typeParsedRef := parseStructuredTypeName(source, typeRef, pos);
if typeRef.isStruct() then begin
if typeRef.extends() <> nil then begin
raise AVTCompilerException.create('Structure can have only one supertype', source, pos);
end;
if not typeParsedRef.isStruct() and (typeParsedRef <> typeStructRef) then begin
raise AVTCompilerException.create('Structure supertype must be a structure or avt.lang.Struct type', source, pos);
end;
typeRef.setExtends(typeParsedRef, pos);
end else begin
if typeParsedRef.isStruct() then begin
raise AVTCompilerException.create('Structures not allowed here', source, pos);
end;
if not typeParsedRef.isClass() then begin
isExtends := false;
end else
if not isExtends then begin
raise AVTCompilerException.create('Type must be service or interface', source, pos);
end;
if isExtends then begin
typeRef.setExtends(typeParsedRef, pos);
end else begin
typeRef.addImplements(typeParsedRef, pos);
end;
end;
pos := source.position;
case source.getLexemeType(pos) of
CHAR_COMMA: ;
CHAR_PARENTH_CLOSED: begin
inc(pos);
break;
end;
else
raise AVTCompilerException.create('")" expected', source, pos);
end;
isExtends := false;
until false;
if not typeRef.isStruct() and (typeRef.extends() = nil) then begin
typeRef.setExtends(typeObjectRef);
end;
end;
if source.getLexemeType(pos) <> CHAR_CURLY_OPENED then begin
raise AVTCompilerException.create('"{" expected', source, pos);
end;
typeRef.implementationPosition := pos + 1;
end;
end;
procedure AVTTableBuilder.parseMembers(typeRef: AVTTypeStructured);
var
lxt: int;
pos: int;
flags: int;
bindingPos: int;
implDetailsPos: int;
typeReturnPos: int;
namePos: int;
argumentsPos: int;
operatorKind: int;
argumentsSize: int;
fieldLength: int;
memberName: AnsiString;
memberDoc: UnicodeString;
memberFoundRef: TObject;
argumentsList: Vector;
typeReturnRef: AVTType;
overriddableRef: AVTOverriddable;
fieldRef: AVTField;
source: AVTSource;
begin
{ разновидность структурированного типа: class, service, interface, struct }
source := typeRef.source;
pos := typeRef.implementationPosition;
repeat
lxt := source.getLexemeType(pos);
if lxt = CHAR_CURLY_CLOSED then break;
{ документация }
memberDoc := '';
if lxt = LITR_DOCUMENTATION then begin
memberDoc := source.getLexemeUnicodeString(pos);
inc(pos);
end;
{ видимость: published, public, protected, package, <default>, private }
case source.getLexemeType(pos) of
AVT_PUBLISHED: begin
if typeRef.isStruct() then begin
raise AVTCompilerException.create('Structure fields can have only public visibility', source, pos);
end;
flags := FLAG_PUBLISHED;
inc(pos);
end;
AVT_PUBLIC: begin
flags := FLAG_PUBLIC;
inc(pos);
end;
AVT_PROTECTED: begin
if typeRef.isStruct() then begin
raise AVTCompilerException.create('Structure fields can have only public visibility', source, pos);
end;
flags := FLAG_PROTECTED;
inc(pos);
end;
AVT_PACKAGE: begin
if typeRef.isStruct() then begin
raise AVTCompilerException.create('Structure fields can have only public visibility', source, pos);
end;
if typeRef.isInterface() then begin
raise AVTCompilerException.create('Interface members can not be hidden', source, pos);
end;
flags := FLAG_PACKAGE;
inc(pos);
end;
AVT_PRIVATE: begin
if typeRef.isStruct() then begin
raise AVTCompilerException.create('Structure fields can have only public visibility', source, pos);
end;
if typeRef.isInterface() then begin
raise AVTCompilerException.create('Interface members can not be hidden', source, pos);
end;
flags := FLAG_PRIVATE;
inc(pos);
end
else
if typeRef.isStruct() or typeRef.isInterface() then begin
flags := FLAG_PUBLIC;
end else begin
flags := FLAG_SOURCE;
end;
end;
{ связывание: static final, static, abstract, final }
bindingPos := pos;
case source.getLexemeType(pos) of
AVT_STATIC: begin
if typeRef.isStruct() then begin
raise AVTCompilerException.create('Structure fields can not be static', source, pos);
end;
flags := flags or FLAG_STATIC;
inc(pos);
if source.getLexemeType(pos) = AVT_FINAL then begin
flags := flags or FLAG_FINAL;
inc(pos);
end else
if typeRef.isInterface() then begin
flags := flags or FLAG_FINAL;
end;
end;
AVT_FINAL: begin
if typeRef.isStruct() then begin
raise AVTCompilerException.create('Structure fields can not be final', source, pos);
end;
flags := flags or FLAG_FINAL;
inc(pos);
if typeRef.isService() then begin
flags := flags or FLAG_STATIC;
end;
end;
AVT_ABSTRACT: begin
if typeRef.isStruct() then begin
raise AVTCompilerException.create('Structure fields can not be abstract', source, pos);
end;
if typeRef.isService() and (flags <= FLAG_PACKAGE) then begin
raise AVTCompilerException.create('Hidden service members can not be abstract', source, pos);
end;
if typeRef.isClass() and (flags = FLAG_PRIVATE) then begin
raise AVTCompilerException.create('Private class members can not be abstract', source, pos);
end;
flags := flags or FLAG_ABSTRACT;
inc(pos);
end;
end;
{ детали реализации: native interrupt, native, interrupt native, interrupt, synchronized }
implDetailsPos := pos;
case source.getLexemeType(pos) of
AVT_NATIVE: begin
if typeRef.isStruct() then begin
raise AVTCompilerException.create('Implementation details can not be used in structures', source, pos);
end;
if typeRef.isInterface() then begin
raise AVTCompilerException.create('Implementation details can not be used in interfaces', source, pos);
end;
if (flags and FLAG_ABSTRACT) <> 0 then begin
raise AVTCompilerException.create('Abstract members can not have implementation details', source, pos);
end;
flags := flags or FLAG_NATIVE;
inc(pos);
if source.getLexemeType(pos) = AVT_INTERRUPT then begin
if (flags and FLAG_STATIC) = 0 then begin
raise AVTCompilerException.create('"static" expected. Interrupt method requires "static" modifier', source, bindingPos);
end;
flags := flags or FLAG_INTERRUPT;
inc(pos);
end;
end;
AVT_INTERRUPT: begin
if typeRef.isStruct() then begin
raise AVTCompilerException.create('Implementation details can not be used in structures', source, pos);
end;
if typeRef.isInterface() then begin
raise AVTCompilerException.create('Implementation details can not be used in interfaces', source, pos);
end;
if (flags and FLAG_ABSTRACT) <> 0 then begin
raise AVTCompilerException.create('Abstract members can not have implementation details', source, pos);
end;
if (flags and FLAG_STATIC) = 0 then begin
raise AVTCompilerException.create('"static" expected. Interrupt method requires "static" modifier', source, bindingPos);
end;
flags := flags or FLAG_INTERRUPT;
inc(pos);
if source.getLexemeType(pos) = AVT_NATIVE then begin
flags := flags or FLAG_NATIVE;
inc(pos);
end;
end;
AVT_SYNCHRONIZED: begin
if typeRef.isStruct() then begin
raise AVTCompilerException.create('Implementation details can not be used in structures', source, pos);
end;
if typeRef.isInterface() then begin
raise AVTCompilerException.create('Implementation details can not be used in interfaces', source, pos);
end;
if (flags and FLAG_ABSTRACT) <> 0 then begin
raise AVTCompilerException.create('Abstract members can not have implementation details', source, pos);
end;
flags := flags or FLAG_SYNCHRONIZED;
inc(pos);
end;
end;
{ члены типов }
case source.getLexemeType(pos) of
CHAR_CURLY_OPENED: begin
{ метод инициализации типа (статичный блок) }
if typeRef.isStruct() then begin
raise AVTCompilerException.create('Static block can not be used in structures', source, pos);
end;
if (flags and FLAG_STATIC) = 0 then begin
raise AVTCompilerException.create('"static" expected. Static block requires "static" modifier', source, bindingPos);
end;
if (flags and (FLAG_NATIVE or FLAG_INTERRUPT or FLAG_SYNCHRONIZED)) <> 0 then begin
raise AVTCompilerException.create('Implementation details not supported by static block', source, implDetailsPos);
end;
if typeRef.members(SPECNAME_CLASS_INIT).hasMoreElements() then begin
raise AVTCompilerException.create('Duplicate static block in ' + typeRef.simpleName, source, pos);
end;
with AVTClassInit.create(typeRef, pos) do begin
implementationPosition := pos;
end;
pos := skipCurly(source, pos);
continue;
end;
CHAR_PARENTH_OPENED: begin
{ метод инициализации экземпляра типа (конструктор) }
if not typeRef.isClass() then begin
raise AVTCompilerException.create('Constructors allowed in classes only', source, pos);
end;
if (flags and (FLAG_STATIC or FLAG_ABSTRACT or FLAG_FINAL)) <> 0 then begin
raise AVTCompilerException.create('Binding modifiers not supported by constructor', source, bindingPos);
end;
if (flags and (FLAG_NATIVE or FLAG_INTERRUPT or FLAG_SYNCHRONIZED)) <> 0 then begin
raise AVTCompilerException.create('Implementation details not supported by constructor', source, implDetailsPos);
end;
argumentsPos := pos;
argumentsList := Vector.create();
try
pos := parseArguments(source, typeRef, pos + 1, argumentsList);
with typeRef.members(SPECNAME_INST_INIT) do while hasMoreElements() do if (nextElement().objectValue() as AVTMethod).isIdentityArguments(argumentsList) then begin
raise AVTCompilerException.create('Duplicate constructor with same arguments in ' + typeRef.simpleName, source, argumentsPos);
end;
overriddableRef := AVTInstInit.create(typeRef, flags, argumentsList, argumentsPos, pos, memberDoc);
finally
argumentsList.free();
end;
if source.getLexemeType(pos) = AVT_THROWS then begin
pos := parseThrows(source, typeRef, overriddableRef as AVTMethod, pos + 1);
end;
overriddableRef.implementationPosition := pos;
if source.getLexemeType(pos) = CHAR_COLON then begin
inc(pos);
lxt := source.getLexemeType(pos);
if (lxt <> AVT_SUPER) and (lxt <> AVT_THIS) then begin
raise AVTCompilerException.create('"super" or "this" expected', source, pos);
end;
inc(pos);
if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
raise AVTCompilerException.create('"(" expected', source, pos);
end;
pos := skipParenthesis(source, pos);
end;
if source.getLexemeType(pos) <> CHAR_CURLY_OPENED then begin
raise AVTCompilerException.create('"{" expected', source, pos);
end;
pos := skipCurly(source, pos);
continue;
end;
end;
overriddableRef := nil;
typeReturnPos := pos;
typeReturnRef := parseType(typeRef, pos);
pos := source.position;
namePos := pos;
case source.getLexemeType(pos) of
AVT_OPERATOR: begin
{ оператор }
if typeRef.isStruct() then begin
raise AVTCompilerException.create('Operators can not be declared in structures', source, pos);
end;
if (flags and FLAG_STATIC) <> 0 then begin
raise AVTCompilerException.create('Operators can not be static', source, bindingPos);
end;
if typeRef.isInterface() then begin
flags := flags or FLAG_ABSTRACT;
end;
operatorKind := parseOperator(source, pos + 1);
pos := source.position;
if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
raise AVTCompilerException.create('"(" expected', source, pos);
end;
argumentsPos := pos;
argumentsList := Vector.create();
try
pos := parseArguments(source, typeRef, pos + 1, argumentsList);
argumentsSize := argumentsList.size();
if argumentsSize = 0 then begin
case operatorKind of
OPER_SCAL_ADD: operatorKind := OPER_SCAL_PLUS;
OPER_SCAL_SUB: operatorKind := OPER_SCAL_MINUS;
OPER_VECT_ADD: operatorKind := OPER_VECT_PLUS;
OPER_VECT_SUB: operatorKind := OPER_VECT_MINUS;
end;
end;
case operatorKind of
SET_ARRAY_ELEMENT: begin
if not typeReturnRef.isVoid() then begin
raise AVTCompilerException.create('"void" expected. The operator []= can return the type void only', source, typeReturnPos);
end;
if argumentsSize <> 2 then begin
raise AVTCompilerException.create('The operator []= requires 2 parameters', source, argumentsPos);
end;
end;
GET_ARRAY_ELEMENT, OPER_BIT_AND, OPER_BIT_OR, OPER_BIT_XOR, OPER_SCAL_MUL, OPER_SCAL_DIV, OPER_SCAL_DIVU,
OPER_SCAL_REM, OPER_SCAL_REMU, OPER_SCAL_ADD, OPER_SCAL_SUB, OPER_SCAL_SAR, OPER_SCAL_SAL, OPER_SCAL_SHR,
OPER_VECT_MUL, OPER_VECT_DIV, OPER_VECT_ADD, OPER_VECT_SUB, OPER_VECT_SAR, OPER_VECT_SAL, OPER_VECT_SHR,
OPER_VECT_G, OPER_VECT_GE, OPER_VECT_L, OPER_VECT_LE, OPER_VECT_E, OPER_VECT_NE,
OPER_VECT_MULS, OPER_VECT_ADDS, OPER_VECT_SUBS, OPER_VECT_MULU, OPER_VECT_ADDU, OPER_VECT_SUBU: begin
if typeReturnRef.isVoid() then begin
raise AVTCompilerException.create('The type void is an invalid return type for the operator ' + AVTOperator.operatorToChar(operatorKind), source, typeReturnPos);
end;
if argumentsSize <> 1 then begin
raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + ' requires 1 parameter', source, argumentsPos);
end;
end;
OPER_SCAL_G, OPER_SCAL_GE, OPER_SCAL_L, OPER_SCAL_LE: begin
if not typeReturnRef.isBoolean() then begin
raise AVTCompilerException.create('"boolean" expected. The operator ' + AVTOperator.operatorToChar(operatorKind) + ' can return value of the type boolean only', source, typeReturnPos);
end;
if argumentsSize <> 1 then begin
raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + ' requires 1 parameter', source, argumentsPos);
end;
end;
OPER_BIT_NOT, OPER_SCAL_PLUS, OPER_SCAL_MINUS, OPER_VECT_UNPCKL, OPER_VECT_UNPCKU, OPER_VECT_PACK, OPER_VECT_PLUS, OPER_VECT_MINUS: begin
if typeReturnRef.isVoid() then begin
raise AVTCompilerException.create('The type void is an invalid return type for the operator ' + AVTOperator.operatorToChar(operatorKind), source, typeReturnPos);
end;
if argumentsSize <> 0 then begin
raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + ' requires no parameters', source, argumentsPos);
end;
end;
end;
with typeRef.members(AVTOperator.operatorToSpecName(operatorKind)) do while hasMoreElements() do if (nextElement().objectValue() as AVTMethod).isIdentityArguments(argumentsList) then begin
raise AVTCompilerException.create('Duplicate operator ' + AVTOperator.operatorToChar(operatorKind) +' with same arguments in ' + typeRef.simpleName, source, namePos);
end;
overriddableRef := AVTOperator.create(typeRef, flags, typeReturnRef, operatorKind, argumentsList, namePos, memberDoc);
finally
argumentsList.free();
end;
if (flags and (FLAG_ABSTRACT or FLAG_NATIVE)) = 0 then begin
overriddableRef.implementationPosition := pos;
if source.getLexemeType(pos) <> CHAR_CURLY_OPENED then begin
raise AVTCompilerException.create('"{" expected', source, pos);
end;
pos := skipCurly(source, pos);
end else begin
if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
raise AVTCompilerException.create('";" expected', source, pos);
end;
inc(pos);
end;
end;
LITR_NAME: begin
memberName := source.getLexemeAnsiString(pos);
inc(pos);
case source.getLexemeType(pos) of
CHAR_PARENTH_OPENED: begin
{ метод }
if typeRef.isStruct() then begin
raise AVTCompilerException.create('Methods can not be declared in structures', source, pos);
end;
if typeRef.isInterface() then begin
if (flags and (FLAG_STATIC or FLAG_FINAL)) <> 0 then begin
raise AVTCompilerException.create('Interface methods can not be static final', source, bindingPos);
end;
flags := flags or FLAG_ABSTRACT;
end;
argumentsPos := pos;
argumentsList := Vector.create();
try
pos := parseArguments(source, typeRef, pos + 1, argumentsList);
if (flags and FLAG_INTERRUPT) <> 0 then begin
if not typeReturnRef.isVoid() then begin
raise AVTCompilerException.create('"void" expected. The interrupt method can return the type void only', source, typeReturnPos);
end;
end;
with typeRef.members(memberName) do while hasMoreElements() do begin
memberFoundRef := nextElement().objectValue();
if (memberFoundRef is AVTField) or (memberFoundRef is AVTProperty) then begin
raise AVTCompilerException.create('Duplicate member ' + memberName + '. Field or property with same name already declared in ' + typeRef.simpleName, source, namePos);
end;
if (memberFoundRef is AVTMethod) and AVTMethod(memberFoundRef).isIdentityArguments(argumentsList) then begin
raise AVTCompilerException.create('Duplicate method ' + memberName + ' with same argument types in ' + typeRef.simpleName, source, argumentsPos);
end;
end;
overriddableRef := AVTMethod.create(typeRef, flags, typeReturnRef, memberName, argumentsList, namePos, pos, memberDoc);
finally
argumentsList.free();
end;
if source.getLexemeType(pos) = AVT_THROWS then begin
pos := parseThrows(source, typeRef, overriddableRef as AVTMethod, pos + 1);
end;
if (flags and (FLAG_ABSTRACT or FLAG_NATIVE)) = 0 then begin
overriddableRef.implementationPosition := pos;
if source.getLexemeType(pos) <> CHAR_CURLY_OPENED then begin
raise AVTCompilerException.create('"{" expected', source, pos);
end;
pos := skipCurly(source, pos);
end else begin
if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
raise AVTCompilerException.create('";" expected', source, pos);
end;
inc(pos);
end;
end;
CHAR_CURLY_OPENED: begin
{ свойство }
if typeRef.isStruct() then begin
raise AVTCompilerException.create('Properties can not be declared in structures', source, pos);
end;
if (flags and FLAG_STATIC) <> 0 then begin
raise AVTCompilerException.create('Properties can not be static', source, bindingPos);
end;
if (flags and (FLAG_NATIVE or FLAG_INTERRUPT or FLAG_SYNCHRONIZED)) <> 0 then begin
raise AVTCompilerException.create('Implementation details not supported by properties', source, implDetailsPos);
end;
if typeRef.isInterface() then begin
flags := flags or FLAG_ABSTRACT;
end;
if typeReturnRef.isVoid() then begin
raise AVTCompilerException.create('The type void is an invalid type for properties', source, typeReturnPos);
end;
if typeRef.members(memberName).hasMoreElements() then begin
raise AVTCompilerException.create('Duplicate property ' + memberName + '. Another member with same name already declared in ' + typeRef.simpleName, source, namePos);
end;
overriddableRef := AVTProperty.create(typeRef, flags, typeReturnRef, memberName, namePos, memberDoc);
overriddableRef.implementationPosition := pos + 1;
pos := skipCurly(source, pos);
end
else
{ поле }
if (flags and FLAG_ABSTRACT) <> 0 then begin
raise AVTCompilerException.create('Fields can not be abstract', source, bindingPos);
end;
if (flags and (FLAG_NATIVE or FLAG_INTERRUPT or FLAG_SYNCHRONIZED)) <> 0 then begin
raise AVTCompilerException.create('Implementation details not supported by fields', source, implDetailsPos);
end;
if typeRef.isStruct() and not typeReturnRef.isPrimitive() then begin
raise AVTCompilerException.create('Type of structure field must be primitive', source, typeReturnPos);
end;
if typeRef.isService() then begin
if typeRef.isInterface() then begin
flags := flags or (FLAG_STATIC or FLAG_FINAL);
end else begin
flags := flags or FLAG_STATIC;
end;
end;
if typeReturnRef.isVoid() then begin
raise AVTCompilerException.create('The type void is an invalid type for fields', source, typeReturnPos);
end;
if typeRef.members(memberName).hasMoreElements() then begin
raise AVTCompilerException.create('Duplicate field ' + memberName + '. Another member with same name already declared in ' + typeRef.simpleName, source, namePos);
end;
fieldRef := AVTField.create(typeRef, flags, typeReturnRef, 0, memberName, namePos, memberDoc);
if source.getLexemeType(pos) = CHAR_EQUALS then begin
if (flags and FLAG_STATIC) = 0 then begin
raise AVTCompilerException.create('"static" expected. Field with initial value requires static modifier', source, bindingPos);
end;
inc(pos);
fieldRef.implementationPosition := pos;
pos := skipValue(source, pos);
end;
if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
raise AVTCompilerException.create('";" expected', source, pos);
end;
inc(pos);
end;
end;
CHAR_BRACKET_OPENED: begin
{ поле структуры, имеющее длину }
if not typeRef.isStruct() then begin
raise AVTCompilerException.create('Fields with length specified can be declared in structures only', source, pos);
end;
if not typeReturnRef.isPrimitive() then begin
raise AVTCompilerException.create('Type of structure field must be primitive', source, typeReturnPos);
end;
if typeReturnRef.isVoid() then begin
raise AVTCompilerException.create('The type void is an invalid type for fields', source, typeReturnPos);
end;
inc(namePos, 3);
inc(pos);
lxt := source.getLexemeType(pos);
if (lxt <> LITR_BYTE) and (lxt <> LITR_SHORT) and (lxt <> LITR_INT) then begin
raise AVTCompilerException.create('Integer literal between 1 and 65536 expected', source, pos);
end;
fieldLength := source.getLexemeInt(pos);
if (fieldLength < 1) or (fieldLength > $00010000) then begin
raise AVTCompilerException.create('Integer literal between 1 and 65536 expected', source, pos);
end;
inc(pos);
if source.getLexemeType(pos) <> CHAR_BRACKET_CLOSED then begin
raise AVTCompilerException.create('"]" expected', source, pos);
end;
inc(pos);
typeReturnRef := programme.systemPackage.getType(typeReturnRef.simpleName + '[]');
if source.getLexemeType(pos) <> LITR_NAME then begin
AVTField.create(typeRef, flags, typeReturnRef, fieldLength, '');
end else begin
memberName := source.getLexemeAnsiString(pos);
inc(pos);
if typeRef.members(memberName).hasMoreElements() then begin
raise AVTCompilerException.create('Duplicate field ' + memberName + '. Another member with same name already declared in ' + typeRef.simpleName, source, namePos);
end;
AVTField.create(typeRef, flags, typeReturnRef, fieldLength, memberName, namePos, memberDoc);
end;
if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
raise AVTCompilerException.create('";" expected', source, pos);
end;
inc(pos);
end;
CHAR_SEMICOLON: begin
{ поле структуры, безымянное }
if not typeRef.isStruct() then begin
raise AVTCompilerException.create('Unnamed fields can be declared in structures only', source, pos);
end;
if not typeReturnRef.isPrimitive() then begin
raise AVTCompilerException.create('Type of structure field must be primitive', source, typeReturnPos);
end;
if typeReturnRef.isVoid() then begin
raise AVTCompilerException.create('The type void is an invalid type for fields', source, typeReturnPos);
end;
AVTField.create(typeRef, flags, typeReturnRef, 0, '');
inc(pos);
end
else
raise AVTCompilerException.create('Member name or "operator" expected', source, pos);
end;
until false;
end;
procedure AVTTableBuilder.parseFields(typeRef: AVTTypeStructured);
var
mem: TObject;
begin
with typeRef.members() do while hasMoreElements() do begin
mem := nextElement().objectValue();
if (mem is AVTField) and AVTItem(mem).isStatic() then begin
parseFieldInitialValue(AVTField(mem));
end;
end;
end;
procedure AVTTableBuilder.parseProperties(typeRef: AVTTypeStructured);
var
mem: TObject;
begin
with typeRef.members() do while hasMoreElements() do begin
mem := nextElement().objectValue();
if mem is AVTProperty then begin
parsePropertyImplementation(AVTProperty(mem));
end;
end;
end;
{%endregion}
end.