{
Этот исходный код является частью проекта ПВТ-ОО.
Copyright © 2021 Малик Разработчик
Это свободная программа: вы можете перераспространять её и/или
изменять её на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она может быть полезна,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<http://www.gnu.org/licenses/>.
}
unit ru.malik.elaborarer.avt.compiler;
{$MODE DELPHI}
interface
uses
charset,
cp866,
pascalx.lang,
pascalx.io,
pascalx.io.vfs,
pascalx.osapi,
pascalx.utils,
ru.malik.elaborarer.avt.programme,
ru.malik.elaborarer.avt.operation,
ru.malik.elaborarer.avt.lexer,
ru.malik.elaborarer.avt.table,
ru.malik.elaborarer.avt.tree,
ru.malik.elaborarer.avt.generator;
{$ASMMODE INTEL,CALLING REGISTER,TYPEINFO ON}
{%region pulic }
type
AVTLibrarySource = class;
AVTCompiler = class;
AVTLibrarySource = class(AVTSource)
private
fldDirectory: UnicodeString;
public
constructor create(parentProgramme: AVTProgramme; const directory, fileName: UnicodeString);
procedure realize(); overload;
end;
AVTCompiler = class(_Object)
private
class function asConsoleString(const str: AnsiString): AnsiString; static;
class function toConsoleString(const str: AnsiString): AnsiString; static; overload;
class function toConsoleString(const str: UnicodeString): AnsiString; static; overload;
class function makeFullName(const path, workingDirectory: UnicodeString): UnicodeString; static;
private
fldWorkingDirectory: UnicodeString;
fldProjectDirectory: UnicodeString;
fldLibrariesDirectory: UnicodeString;
fldLibraries: UnicodeString_Array1d;
fldProgramme: AVTProgramme;
procedure readSourcesFrom(const directory, path: UnicodeString);
procedure realizeSources();
procedure lexicalAnalyzer();
procedure loadLibraries();
procedure printTypeList();
procedure printType(typ: AVTType);
procedure printTree(code: AVTCode; ordered: boolean);
procedure printNode(margin: int; node: AVTNode);
function operandToString(asc: _Object): AnsiString;
function buildProgramme(): UnicodeString;
public
constructor create();
destructor destroy; override;
procedure run(const args: UnicodeString_Array1d);
end;
{%endregion}
implementation
{%region AVTLibrarySource }
constructor AVTLibrarySource.create(parentProgramme: AVTProgramme; const directory, fileName: UnicodeString);
begin
inherited create(parentProgramme, fileName);
self.fldDirectory := directory;
end;
procedure AVTLibrarySource.realize();
begin
realize(LocalFileSystem.getInstance(), fldDirectory);
end;
{%endregion}
{%region AVTCompiler }
class function AVTCompiler.asConsoleString(const str: AnsiString): AnsiString;
var
nst: RawByteString;
begin
nst := stringCopy(str);
setCodePage(nst, 866, false);
result := nst;
end;
class function AVTCompiler.toConsoleString(const str: AnsiString): AnsiString;
begin
result := toConsoleString(stringToUTF16(str));
end;
class function AVTCompiler.toConsoleString(const str: UnicodeString): AnsiString;
var
idx: int;
len: int;
buf: char_Array1d;
enc: PUnicodeMap;
begin
len := length(str);
buf := char_Array1d_create(len);
enc := getMap(866);
for idx := 0 to len - 1 do begin
buf[idx] := getASCII(TUnicodeChar(str[idx + 1]), enc)[1];
end;
result := AnsiString_create(buf, 0, len);
end;
class function AVTCompiler.makeFullName(const path, workingDirectory: UnicodeString): UnicodeString;
var
c: wchar;
npt: UnicodeString;
begin
npt := stringReplace(path, DIRECTORY_SEPARATOR, '/');
if stringStartsWith(UnicodeString('/'), npt) then npt := stringCopy(npt, 2);
if length(npt) <= 0 then begin
result := workingDirectory;
exit;
end;
if not stringEndsWith(UnicodeString('/'), npt) then npt := npt + '/';
if length(npt) < 3 then begin
result := workingDirectory + npt;
exit;
end;
c := npt[1];
if ((c >= 'A') and (c <= 'Z') or (c >= 'a') and (c <= 'z')) and (npt[2] = ':') and (npt[3] = '/') then begin
result := '/' + npt;
exit;
end;
result := workingDirectory + npt;
end;
procedure AVTCompiler.readSourcesFrom(const directory, path: UnicodeString);
var
e: FileEnumeration;
app: AVTProgramme;
nam: UnicodeString;
begin
app := fldProgramme;
e := LocalFileSystem.getInstance().findFirst(directory + path);
if e = nil then begin
raise AVTGlobalException.create('"' + stringToUTF8(directory + path) + '" does not exists or is not readable');
end;
try
repeat
if e.isDirectory() then begin
readSourcesFrom(directory, path + e.getName() + '/');
continue;
end;
nam := e.getName();
if stringEndsWith(UnicodeString('.avt'), nam) then begin
AVTLibrarySource.create(app, directory, path + nam);
end;
until not e.findNext();
finally
e.close();
end;
end;
procedure AVTCompiler.realizeSources();
begin
with fldProgramme.sources() do while hasMoreElements() do begin
(nextElement().objectValue() as AVTLibrarySource).realize();
end;
end;
procedure AVTCompiler.lexicalAnalyzer();
begin
with AVTLexer.create() do begin
try
with fldProgramme.sources() do while hasMoreElements() do begin
split(nextElement().objectValue() as AVTSource, true);
end;
finally
free();
end;
end;
end;
procedure AVTCompiler.loadLibraries();
{var
i: int;
item: byte2;
storage: AVTByte2Storage;}
begin
{item[0] := 0;
item[1] := 0;
storage := AVTByte2Storage.create();
try
for i := 0 to 9 do begin
storage.indexAcquire(item);
inc(item[0]);
end;
for i := 0 to storage.length - 1 do begin
item := storage[i];
writeln(intToString(item[0]) + ', ' + intToString(item[1]));
end;
finally
storage.free();
end;}
end;
procedure AVTCompiler.printTypeList();
var
app: AVTProgramme;
typ: AVTType;
begin
app := fldProgramme;
with app.types() do while hasMoreElements() do begin
printType(nextElement().objectValue() as AVTType);
end;
with app.systemPackage.types() do while hasMoreElements() do begin
typ := nextElement().objectValue() as AVTType;
if typ is AVTTypePrimitive then printType(typ);
end;
with app.arrays() do while hasMoreElements() do begin
printType(nextElement().objectValue() as AVTType);
end;
end;
procedure AVTCompiler.printType(typ: AVTType);
var
idx: int;
cod: AVTCode;
mem: AVTItem;
ovr: AVTOverriddable;
ext: AVTTypeStructured;
str: AnsiString;
begin
str := typ.fullName;
if typ is AVTTypeStructured then with AVTTypeStructured(typ) do begin
ext := extends();
if ext <> nil then begin
str := str + '(' + ext.fullName;
with implements() do while hasMoreElements() do begin
ext := nextElement().objectValue() as AVTTypeStructured;
str := str + ', ' + ext.fullName;
end;
str := str + ')';
end;
writeln(asConsoleString(toConsoleString(str)));
str := ' fasm: ' + fasmFullName;
writeln(asConsoleString(toConsoleString(str)));
with members() do while hasMoreElements() do begin
mem := nextElement().objectValue() as AVTItem;
str := ' ' + mem.fullName + ' : ';
if mem is AVTField then with AVTField(mem) do begin
str := str + valueType.fullName;
end else
if mem is AVTProperty then with AVTProperty(mem) do begin
str := str + valueType.fullName + ' { ';
if readSynthetic = nil then begin
str := str + 'write';
end else
if writeSynthetic = nil then begin
str := str + 'read';
end else begin
str := str + 'read, write';
end;
str := str + ' }';
end else
if mem is AVTMethod then with AVTMethod(mem) do begin
str := str + returnType.fullName;
str := str + (LINE_ENDING + ' fasm full : ') + fasmFullName;
str := str + (LINE_ENDING + ' fasm short : ') + fasmShortName;
idx := virtualIndex;
if idx >= 0 then begin
str := str + (LINE_ENDING + ' virt. index: ') + intToString(idx);
end;
idx := serviceIndex;
if idx >= 0 then begin
str := str + (LINE_ENDING + ' serv. index: ') + intToString(idx);
end;
end;
writeln(asConsoleString(toConsoleString(str)));
if mem is AVTOverriddable then begin
with AVTOverriddable(mem).overriddenMembers() do while hasMoreElements() do begin
ovr := nextElement().objectValue() as AVTOverriddable;
writeln(asConsoleString(toConsoleString(' overrides ' + ovr.fullName)));
end;
end;
if mem is AVTMethod then begin
cod := AVTMethod(mem).code;
if cod <> nil then printTree(cod, false);
end;
end;
end else with typ do begin
writeln(asConsoleString(toConsoleString(str)));
str := ' fasm: ' + fasmFullName;
writeln(asConsoleString(toConsoleString(str)));
end;
end;
procedure AVTCompiler.printTree(code: AVTCode; ordered: boolean);
var
margin: int;
index: int;
oldLineIndex: int;
newLineIndex: int;
child: AVTNode;
node: AVTNode;
source: AVTSource;
begin
if ordered then begin
oldLineIndex := -1;
source := code.parentMethod.source;
with code.instructions() do while hasMoreElements() do begin
node := nextElement().objectValue() as AVTNode;
newLineIndex := node.lineIndex;
if (newLineIndex >= 0) and (newLineIndex <> oldLineIndex) then begin
writeln(asConsoleString(toConsoleString(' ' + stringTrim(stringToUTF8(source[newLineIndex])))));
oldLineIndex := newLineIndex;
end;
printNode(6, node);
end;
exit;
end;
margin := 6;
index := 0;
node := code.root;
printNode(margin, node);
if node.length <= 0 then exit;
inc(margin);
repeat
child := node[index];
printNode(margin, child);
if child.length > 0 then begin
node := child;
index := 0;
inc(margin);
continue;
end;
inc(index);
while index >= node.length do begin
index := node.index + 1;
node := node.parent;
dec(margin);
if node = nil then exit;
end;
until false;
end;
procedure AVTCompiler.printNode(margin: int; node: AVTNode);
var
i: int;
str: AnsiString;
ins: AnsiString;
opr: _Object;
jnd: AVTNode;
begin
case node.instruction of
AVT_CLASS: ins := 'class'; (* ---- null class(AVTTypeStructured) *)
AVT_INSTANCEOF: ins := 'instanceof'; (* boolean instanceof(AVTTypeStructured) *)
AVT_WITH: ins := 'with'; (* xxxx void with() *)
AVT_IF: ins := 'if'; (* xxxx void if() *)
AVT_SWITCH: ins := 'switch'; (* void switch() *)
AVT_CASE: ins := 'case'; (* void case(AVTConstant) *)
AVT_DEFAULT: ins := 'default'; (* void default() *)
AVT_LABEL: ins := 'label'; (* xxxx void label(AVTConstant{value.asString <> ''}) *)
AVT_DO: ins := 'do'; (* xxxx void do() *)
AVT_FOR: ins := 'for'; (* xxxx void for() *)
AVT_WHILE: ins := 'while'; (* xxxx void while() *)
AVT_BLOCK: ins := '{...}'; (* xxxx void {…}() *)
AVT_BREAK: ins := 'break'; (* ---- null break(AVTNode{instruction in [AVT_SWITCH, AVT_LABEL, AVT_DO, AVT_FOR, AVT_WHILE]}) *)
AVT_CONTINUE: ins := 'continue'; (* ---- null continue(AVTNode{instruction in [AVT_DO, AVT_FOR, AVT_WHILE]}) *)
AVT_RETURN: ins := 'return'; (* ???? void return() *)
AVT_THROW: ins := 'throw'; (* void throw() *)
AVT_TRY_BEGIN: ins := 'tryBegin'; (* void tryBegin() *)
AVT_TRY_END: ins := 'tryEnd'; (* void tryEnd() *)
AVT_CATCH: ins := 'catch'; (* void catch(AVTVariable) (аналогично storeVariable) *)
AVT_FINALLY: ins := 'finally'; (* void finally() *)
AVT_FINALLY_INVOKE: ins := 'invokeFinally'; (* void invokeFinally(AVTNode{instruction = AVT_FINALLY}) *)
AVT_FINALLY_RETURN: ins := 'leaveFinally'; (* void leaveFinally() *)
AVT_MONITOR_ENTER: ins := 'enterMonitor'; (* void enterMonitor() *)
AVT_MONITOR_LEAVE: ins := 'leaveMonitor'; (* void leaveMonitor() *)
AVT_ENTER: ins := 'enter'; (* void enter() *)
AVT_LEAVE: ins := 'leave'; (* void leave(AVTType) *)
AVT_CLINIT_TRY_LOCK: ins := 'tryLockClinit'; (* boolean tryLockClinit(AVTTypeStructured) *)
AVT_CLINIT_UNLOCK: ins := 'unlockClinit'; (* void unlockClinit() *)
LOAD_VARIABLE: ins := 'loadVariable'; (* T loadVariable(AVTVariable) *)
LOAD_STATIC: ins := 'loadStatic'; (* T loadStatic(AVTField{isStatic() = true}) *)
LOAD_CLASS: ins := 'loadClass'; (* xxxx avt.lang.Class loadClass(AVTType) { НЕ ИСПОЛЬЗУЕТСЯ! ИСПОЛЬЗУЙ LOAD_CONST ВМЕСТО ЭТОЙ ИНСТРУКЦИИ. } *)
LOAD_CONST: ins := 'loadConstant'; (* T loadConstant(AVTConstant) *)
GET_FIELD: ins := 'getField'; (* T getField(AVTField{isStatic() = false}) *)
GET_PROPERTY: ins := 'getProperty'; (* T getProperty(AVTProperty) *)
GET_ARRAY_ELEMENT: ins := 'getArrayElement'; (* T getArrayElement(AVTType/*тип элементов массива*/) *)
GET_VECTOR_ELEMENT: ins := 'getVectorElement'; (* T getVectorElement(AVTTypePrimitive/*тип вектора*/) *)
DECLARE_VARIABLE: ins := 'declareVariable'; (* void declareVariable(AVTVariable) (аналогично storeVariable) *)
DUP1: ins := 'dup1'; (* void dup1() *)
DUP2: ins := 'dup2'; (* void dup2() *)
DUP1X1: ins := 'dup1x1'; (* void dup1x1() *)
DUP1X2: ins := 'dup1x2'; (* void dup1x2() *)
POP1: ins := 'pop1'; (* void pop1() *)
JUMP: ins := 'jump'; (* void jump() *)
INVOKE_STATIC: ins := 'invokeStatic'; (* void|T invokeStatic(AVTMethod{isStatic() = true}) *)
INVOKE_SPECIAL: ins := 'invokeSpecial'; (* void|T invokeSpecial(AVTMethod{isStatic() = false}) *)
INVOKE_VIRTUAL: ins := 'invokeVirtual'; (* void|T invokeVirtual(AVTMethod{isStatic() = false, visibility > AVT_PRIVATE, parentType.isClass() = true}) *)
INVOKE_SERVICE: ins := 'invokeService'; (* void|T invokeService(AVTMethod{isStatic() = false, visibility > AVT_PRIVATE, parentType.isService() = true}) *)
NEW_ARRAY_BY_LENGTH: ins := 'newArrayByLength'; (* T[] newArrayByLength(AVTTypeArray) *)
NEW_MULTI_ARRAY: ins := 'newMultiArray'; (* T[] newMultiArray(AVTTypeArray) *)
NEW_ARRAY_BY_ELEMENTS: ins := 'newArrayByElements'; (* T[] newArrayByElements(AVTTypeArray, AVTConstant{valueType in [byte, short, int]}/*длина массива*/) *)
NEW_VECTOR: ins := 'newVector'; (* T newVector(AVTTypePrimitive) *)
NEW_CLASS: ins := 'newClass'; (* T newClass(AVTTypeStructured) *)
NEW_STRUCT: ins := 'newStruct'; (* T newStruct(AVTTypeStructured) *)
NEW_SERVICE: ins := 'newService'; (* T newService(AVTTypeStructured) *)
OPER_TYPE_CAST: ins := 'cast'; (* T cast(AVTType/*новый тип*/, AVTType/*старый тип*/) *)
OPER_INCREMENT: ins := 'operator ++'; (* void operator ++(AVTVariable) *)
OPER_DECREMENT: ins := 'operator --'; (* void operator --(AVTVariable) *)
OPER_INC_POST: ins := 'operator x++'; (* T operator x++(AVTVariable) *)
OPER_DEC_POST: ins := 'operator x--'; (* T operator x--(AVTVariable) *)
OPER_INC_PRED: ins := 'operator ++x'; (* T operator ++x(AVTVariable) *)
OPER_DEC_PRED: ins := 'operator --x'; (* T operator --x(AVTVariable) *)
OPER_BOOL_NOT: ins := 'operator !'; (* xxxx boolean operator !() *)
OPER_BOOL_AND: ins := 'operator &&'; (* xxxx boolean operator &&() *)
OPER_BOOL_OR: ins := 'operator ||'; (* xxxx boolean operator ||() *)
OPER_BOOL_COND: ins := 'operator ?:'; (* xxxx T operator ?:() *)
OPER_BIT_NOT: ins := 'operator ~'; (* T operator ~(AVTTypePrimitive) *)
OPER_BIT_AND: ins := 'operator &'; (* T operator &(AVTTypePrimitive) *)
OPER_BIT_OR: ins := 'operator |'; (* T operator |(AVTTypePrimitive) *)
OPER_BIT_XOR: ins := 'operator ^'; (* T operator ^(AVTTypePrimitive) *)
OPER_SCAL_PLUS: ins := 'operator +/*unary*/'; (* xxxx T operator +/*unary*/(AVTTypePrimitive) *)
OPER_SCAL_MINUS: ins := 'operator -/*unary*/'; (* T operator -/*unary*/(AVTTypePrimitive) *)
OPER_SCAL_MUL: ins := 'operator *'; (* T operator *(AVTTypePrimitive) *)
OPER_SCAL_DIV: ins := 'operator /'; (* T operator /(AVTTypePrimitive) *)
OPER_SCAL_DIVU: ins := 'operator //'; (* T operator //(AVTTypePrimitive) *)
OPER_SCAL_REM: ins := 'operator %'; (* T operator %(AVTTypePrimitive) *)
OPER_SCAL_REMU: ins := 'operator %%'; (* T operator %%(AVTTypePrimitive) *)
OPER_SCAL_ADD: ins := 'operator +'; (* T operator +(AVTTypePrimitive) *)
OPER_SCAL_SUB: ins := 'operator -'; (* T operator -(AVTTypePrimitive) *)
OPER_SCAL_SAR: ins := 'operator >>'; (* T operator >>(AVTTypePrimitive) *)
OPER_SCAL_SAL: ins := 'operator <<'; (* T operator <<(AVTTypePrimitive) *)
OPER_SCAL_SHR: ins := 'operator >>>'; (* T operator >>>(AVTTypePrimitive) *)
OPER_SCAL_G: ins := 'operator >'; (* boolean operator >(AVTTypePrimitive) *)
OPER_SCAL_GE: ins := 'operator >='; (* boolean operator >=(AVTTypePrimitive) *)
OPER_SCAL_L: ins := 'operator <'; (* boolean operator <(AVTTypePrimitive) *)
OPER_SCAL_LE: ins := 'operator <='; (* boolean operator <=(AVTTypePrimitive) *)
OPER_SCAL_E: ins := 'operator =='; (* boolean operator ==(AVTType) *)
OPER_SCAL_NE: ins := 'operator !='; (* boolean operator !=(AVTType) *)
OPER_VECT_PACK: ins := 'operator @@@@'; (* T operator @@@@(AVTTypePrimitive) *)
OPER_VECT_UNPCKL: ins := 'operator ####'; (* T operator ####(AVTTypePrimitive) *)
OPER_VECT_UNPCKU: ins := 'operator ^^^^'; (* T operator ^^^^(AVTTypePrimitive) *)
OPER_VECT_PLUS: ins := 'operator ++++/*unary*/'; (* xxxx T operator ++++/*unary*/(AVTTypePrimitive) *)
OPER_VECT_MINUS: ins := 'operator ----/*unary*/'; (* T operator ----/*unary*/(AVTTypePrimitive) *)
OPER_VECT_MUL: ins := 'operator ****'; (* T operator ****(AVTTypePrimitive) *)
OPER_VECT_DIV: ins := 'operator ////'; (* T operator ////(AVTTypePrimitive) *)
OPER_VECT_ADD: ins := 'operator ++++'; (* T operator ++++(AVTTypePrimitive) *)
OPER_VECT_SUB: ins := 'operator ----'; (* T operator ----(AVTTypePrimitive) *)
OPER_VECT_SAR: ins := 'operator >>>>'; (* T operator >>>>(AVTTypePrimitive) *)
OPER_VECT_SAL: ins := 'operator <<<<'; (* T operator <<<<(AVTTypePrimitive) *)
OPER_VECT_SHR: ins := 'operator >>>>>'; (* T operator >>>>>(AVTTypePrimitive) *)
OPER_VECT_G: ins := 'operator |>>|'; (* T operator |>>|(AVTTypePrimitive) *)
OPER_VECT_GE: ins := 'operator |>=|'; (* T operator |>=|(AVTTypePrimitive) *)
OPER_VECT_L: ins := 'operator |<<|'; (* T operator |<<|(AVTTypePrimitive) *)
OPER_VECT_LE: ins := 'operator |<=|'; (* T operator |<=|(AVTTypePrimitive) *)
OPER_VECT_E: ins := 'operator |==|'; (* T operator |==|(AVTTypePrimitive) *)
OPER_VECT_NE: ins := 'operator |!=|'; (* T operator |!=|(AVTTypePrimitive) *)
OPER_VECT_MULS: ins := 'operator |**|'; (* T operator |**|(AVTTypePrimitive) *)
OPER_VECT_ADDS: ins := 'operator |++|'; (* T operator |++|(AVTTypePrimitive) *)
OPER_VECT_SUBS: ins := 'operator |--|'; (* T operator |--|(AVTTypePrimitive) *)
OPER_VECT_MULU: ins := 'operator #**#'; (* T operator #**#(AVTTypePrimitive) *)
OPER_VECT_ADDU: ins := 'operator #++#'; (* T operator #++#(AVTTypePrimitive) *)
OPER_VECT_SUBU: ins := 'operator #--#'; (* T operator #--#(AVTTypePrimitive) *)
STORE_VARIABLE: ins := 'storeVariable'; (* void|T storeVariable(AVTVariable) *)
STORE_STATIC: ins := 'storeStatic'; (* void|T storeStatic(AVTField{isStatic() = true}) *)
SET_FIELD: ins := 'setField'; (* void|T setField(AVTField{isStatic() = false}) *)
SET_PROPERTY: ins := 'setProperty'; (* void|T setProperty(AVTProperty) *)
SET_ARRAY_ELEMENT: ins := 'setArrayElement'; (* void|T setArrayElement(AVTType/*тип элементов массива*/) *)
else ins := '<invalid>'
end; (* xxxx – служебный (некомпилируемый) узел *)
str := ''; (* ---- – промежуточный (уничтожаемый) узел *)
for i := margin - 1 downto 0 do begin (* ???? – не всегда компилируемый узел *)
str := str + ' ';
end;
str := str + longToHexString(pointerToLongBits(node)) + ' ';
i := node.lineIndex + 1;
if i > 0 then begin
str := str + '[' + intToString(i) + '] ';
end;
i := node.labelNumber;
if i >= 0 then begin
str := str + '.L.' + intToString(i) + ': ';
end;
str := str + AVTTableBuilder.itemToString(node.dataType) + ' ' + ins + '(';
opr := node.operand1;
if opr <> nil then begin
str := str + operandToString(opr);
opr := node.operand2;
if opr <> nil then begin
str := str + ', ' + operandToString(opr);
end;
end;
str := str + ')';
jnd := node.jumpDefault;
if jnd <> nil then begin
str := str + ' { default=>' + longToHexString(pointerToLongBits(jnd));
with node.jumpCaseValues() do while hasMoreElements() do begin
i := nextElement().intValue();
jnd := node.jumpCaseGetNode(i);
str := str + ', ' + intToString(i) + '=>' + longToHexString(pointerToLongBits(jnd));
end;
str := str + ' }';
end;
writeln(asConsoleString(toConsoleString(str)));
end;
function AVTCompiler.operandToString(asc: _Object): AnsiString;
var
i: int;
l: int;
c: wchar;
s: AnsiString;
v: UnicodeString;
typ: AVTType;
begin
s := '<invalid>';
if asc = nil then begin
s := '<null>';
end else
if asc is AVTNode then begin
s := longToHexString(pointerToLongBits(asc));
end else
if asc is AVTItem then begin
s := AVTItem(asc).fullName;
end else
if asc is AVTConstant then with AVTConstant(asc).value do begin
typ := AVTConstant(asc).valueType;
if (typ = nil) or (typ is AVTTypeStructured) then begin
typ := asClass;
if isNull then begin
s := 'null'
end else
if typ <> nil then begin
s := typ.fullName + '.class';
end else begin
s := '"';
v := asString;
for i := 1 to length(v) do begin
if i > 16 then begin
s := s + '...';
break;
end;
c := v[i];
if (c >= #$0020) and (c <= #$007e) then begin
s := s + char(c);
end else begin
s := s + '\u' + intToHexString((int(c) shr 12) and $0f) + intToHexString((int(c) shr 8) and $0f) + intToHexString((int(c) shr 4) and $0f) + intToHexString(int(c) and $0f);
end;
end;
s := s + '"';
end;
end else
if typ is AVTTypePrimitive then with AVTTypePrimitive(typ) do begin
case compoundBase of
AVT_BOOLEAN: begin
if asBoolean then begin
s := 'true';
end else begin
s := 'false';
end;
end;
AVT_CHAR: begin
i := int(asChar);
s := '''\u' + intToHexString((i shr 12) and $0f) + intToHexString((i shr 8) and $0f) + intToHexString((i shr 4) and $0f) + intToHexString(i and $0f) + '''';
end;
AVT_REAL: begin
s := realToString(asReal);
end;
AVT_BYTE: begin
l := compoundLength;
if l = 1 then begin
s := intToString(asByte);
end else begin
s := 'new byte' + char(l + int('0')) + ' { ';
dec(l);
for i := 0 to l do begin
s := s + intToString(asByte8[i]);
if i < l then s := s + ', ';
end;
s := s + ' }';
end;
end;
AVT_SHORT: begin
l := compoundLength;
if l = 1 then begin
s := intToString(asShort);
end else begin
s := 'new short' + char(l + int('0')) + ' { ';
dec(l);
for i := 0 to l do begin
s := s + intToString(asShort8[i]);
if i < l then s := s + ', ';
end;
s := s + ' }';
end;
end;
AVT_INT: begin
l := compoundLength;
if l = 1 then begin
s := intToString(asInt);
end else begin
s := 'new int' + char(l + int('0')) + ' { ';
dec(l);
for i := 0 to l do begin
s := s + intToString(asInt8[i]);
if i < l then s := s + ', ';
end;
s := s + ' }';
end;
end;
AVT_LONG: begin
l := compoundLength;
if l = 1 then begin
s := longToString(asLong) + 'L';
end else begin
s := 'new long' + char(l + int('0')) + ' { ';
dec(l);
for i := 0 to l do begin
s := s + longToString(asLong8[i]);
if i < l then s := s + 'L, ';
end;
s := s + 'L }';
end;
end;
AVT_FLOAT: begin
l := compoundLength;
if l = 1 then begin
s := floatToString(asFloat) + 'f';
end else begin
s := 'new float' + char(l + int('0')) + ' { ';
dec(l);
for i := 0 to l do begin
s := s + floatToString(asFloat8[i]);
if i < l then s := s + 'f, ';
end;
s := s + 'f }';
end;
end;
AVT_DOUBLE: begin
l := compoundLength;
if l = 1 then begin
s := doubleToString(asDouble) + 'd';
end else begin
s := 'new double' + char(l + int('0')) + ' { ';
dec(l);
for i := 0 to l do begin
s := s + doubleToString(asDouble8[i]);
if i < l then s := s + 'd, ';
end;
s := s + 'd }';
end;
end;
end;
end;
end;
result := s;
end;
function AVTCompiler.buildProgramme(): UnicodeString;
var
src: AVTSource;
typ: AVTTypeStructured;
app: AVTProgramme;
begin
app := fldProgramme;
with AVTCodeGenerator.create(app) do begin
try
{ Будущий алгоритм компиляции:
1. Создать пакеты из исходного кода
2. Создать типы из исходного кода
3. Создать основные типы массивов
4. Прочитать раздел импортов
5. Определить реализуемые типы для:
А. Типов из исходного кода
Б. Основных типов массивов
6. Проверить реализуемые типы и добавить недостающие
7. Отсортировать типы из исходного кода
8. Создать члены типов из исходного кода. (Параллельно будут созданы дополнительные типы массивов, а также определены и проверены их реализуемые типы и добавлены недостающие реализуемые типы.)
9. Создать члены основных типов массивов
10. Проверить члены, добавить недостающие члены, найти перекрытые члены для:
А. Типов из исходного кода
Б. Основных типов массивов
В. Дополнительных типов массивов
11. Работа с членами всех типов:
А. Чтение начальных значений полей
Б. Чтение реализации свойств
В. Определение смещений полей, индексов виртуальных и сервисных методов
Г. Построение деревьев разбора кода методов и работа с ними
(Параллельно будут созданы дополнительные типы массивов, а также определены и проверены их реализуемые типы и добавлены недостающие реализуемые типы.)
12. Сохранение (запись) результата на диск
1.
with app.sources() do while hasMoreElements() do begin
src := nextElement().objectValue() as AVTSource;
parsePackage(src);
end;
2.
with app.sources() do while hasMoreElements() do begin
src := nextElement().objectValue() as AVTSource;
parseTypes(src);
end;
3.
app.createArrays();
4, 5.
with app.sources() do while hasMoreElements() do begin
src := nextElement().objectValue() as AVTSource;
parseImports(src);
parseSuperTypes(src);
end;
app.realizeArrays();
6, 7.
app.prefetchTypes();
8.
with app.types() do while hasMoreElements() do begin
typ := nextElement().objectValue() as AVTTypeStructured;
parseMembers(typ);
end;
9.
app.prefetchArrays();
10.
with app.types() do while hasMoreElements() do begin
(nextElement().objectValue() as AVTTypeStructured).prefetchMembers();
end;
with app.arrays() do while hasMoreElements() do begin
(nextElement().objectValue() as AVTTypeStructured).prefetchMembers();
end;
11.
with app.types() do while hasMoreElements() do begin
typ := nextElement().objectValue() as AVTTypeStructured;
parseFields(typ);
parseProperties(typ);
end;
with app.types() do while hasMoreElements() do begin
typ := nextElement().objectValue() as AVTTypeStructured;
parseMethods(typ);
end;
12.
storeProgramme();
}
with app.sources() do while hasMoreElements() do begin
src := nextElement().objectValue() as AVTSource;
parsePackage(src);
end;
with app.sources() do while hasMoreElements() do begin
src := nextElement().objectValue() as AVTSource;
parseTypes(src);
end;
with app.sources() do while hasMoreElements() do begin
src := nextElement().objectValue() as AVTSource;
parseImport(src);
parseSuperTypes(src);
end;
app.prefetchTypes();
with app.types() do while hasMoreElements() do begin
typ := nextElement().objectValue() as AVTTypeStructured;
parseMembers(typ);
end;
with app.types() do while hasMoreElements() do begin
typ := nextElement().objectValue() as AVTTypeStructured;
parseFields(typ);
typ.prefetchMembers();
parseProperties(typ);
end;
app.prefetchArrays();
with app.types() do while hasMoreElements() do begin
typ := nextElement().objectValue() as AVTTypeStructured;
typ.prefetchIndices();
end;
with app.types() do while hasMoreElements() do begin
typ := nextElement().objectValue() as AVTTypeStructured;
parseMethods(typ);
end;
with app.arrays() do while hasMoreElements() do begin
typ := nextElement().objectValue() as AVTTypeStructured;
parseMethods(typ);
end;
with app.arrays() do while hasMoreElements() do begin
typ := nextElement().objectValue() as AVTTypeStructured;
typ.prefetchIndices();
end;
result := generate(LocalFileSystem.getInstance(), fldProjectDirectory);
finally
free();
end;
end;
end;
constructor AVTCompiler.create();
begin
inherited create();
self.fldProgramme := AVTProgramme.create();
end;
destructor AVTCompiler.destroy;
begin
fldProgramme.free();
inherited destroy;
end;
procedure AVTCompiler.run(const args: UnicodeString_Array1d);
var
len: int;
time: long;
programmeFile: AnsiString;
consoleMessage: AnsiString;
workingDirectory: UnicodeString;
projectDirectory: UnicodeString;
librariesDirectory: UnicodeString;
libraries: UnicodeString_Array1d;
begin
writeln(asConsoleString('Advanced Vector Translator (object-oriented) version ' + AVTC_VERSION));
if not AVTProgramme.isSupportedAVX512ByCPU() then begin
writeln(asConsoleString('Launching of this programme is allowed only on the CPUs with AVX, AVX2 and AVX-512 (F, CD, DQ, BW) supported.'));
exit;
end;
if not AVTProgramme.isSupportedAVX512ByOS() then begin
writeln(asConsoleString('Launching of this programme is allowed only in OSes with CPUs with AVX, AVX2 and AVX-512 (F, CD, DQ, BW) supported.'));
exit;
end;
len := length(args);
if len <= 1 then begin
writeln(asConsoleString('The project directory is not specified in command line argument.' + LINE_ENDING +
'Please specify the project directory in command line argument.' + LINE_ENDING +
'The project directory must have the src.asm and src.avt subdirectories.'));
exit;
end;
try
time := systemGetTickCount();
workingDirectory := stringReplace(systemGetCurrentDirectory(), DIRECTORY_SEPARATOR, '/');
if not stringEndsWith(UnicodeString('/'), workingDirectory) then workingDirectory := workingDirectory + '/';
if not stringStartsWith(UnicodeString('/'), workingDirectory) then workingDirectory := '/' + workingDirectory;
projectDirectory := makeFullName(args[1], workingDirectory);
librariesDirectory := '/' + stringReplace(args[0], DIRECTORY_SEPARATOR, '/');
librariesDirectory := stringCopy(librariesDirectory, 1, stringLastIndexOf(UnicodeString('/'), librariesDirectory) + 1) + 'libs/';
dec(len, 2);
libraries := UnicodeString_Array1d_create(len);
arraycopyUnicodeStrings(args, 2, libraries, 0, len);
fldWorkingDirectory := workingDirectory;
fldProjectDirectory := projectDirectory;
fldLibrariesDirectory := librariesDirectory;
fldLibraries := libraries;
readSourcesFrom(projectDirectory + 'src.avt', '/');
realizeSources();
lexicalAnalyzer();
loadLibraries();
programmeFile := stringToUTF8(buildProgramme());
time := (systemGetTickCount() - time) div 100;
writeln(asConsoleString(longToString(time div 10) + '.' + char(int(time mod 10) + int('0')) + ' seconds, ' + stringReplace(stringCopy(programmeFile, 2), '/', '\') + ' generated.'));
{ printTypeList(); }
except
on e: AVTCompilerException do begin
consoleMessage := asConsoleString
(
e.message + LINE_ENDING +
'File: ' + toConsoleString(e.sourceFileName) + LINE_ENDING +
'Line: ' + intToString(e.lineIndex + 1) + LINE_ENDING +
'Char: ' + intToString(e.charIndex + 1) + LINE_ENDING
);
writeln(consoleMessage);
end;
on e: AVTGlobalException do begin
consoleMessage := asConsoleString
(
e.message + LINE_ENDING
);
writeln(consoleMessage);
end;
on e: Throwable do begin
e.printStackTrace();
end;
end;
end;
{%endregion}
end.